본문 바로가기

프로젝트

[기록] AWS EC2 / Docker 환경 마련하기

 현재 진행 중인 졸업 프로젝트에서 나는 데이터 수집 파이프라인 구축 역할과 API 서버 구축 역할을 맡았다. 이 글에서는 API 서버를 실제 환경에 배포하기 위한 첫 단계로 EC2 + Docker 환경을 마련해 본다. 추가적으로 탄력적 IP에 대해 알게 된 점을 설명한다.


 내가 달성하고 싶었던 목표는 다음과 같다.

  1. EC2 환경에서 docker을 운영한다.
  2. 도메인 명을 기반으로 api 서버에 접근한다. 도메인을 구매하고 실제 환경에 연결한다.
  3. 경로에 접근할 때 https을 적용한다. http로 접근하는 경우 https로 redirection한다.

 1번과 2번은 과거 프로젝트를 통해 경험해 본 적이 있었다. 다만 당시에는 클라우드에 대해 잘 이해하지 못하고 있던 상태였기 때문에, 다시 되짚어보자는 마음으로 글을 작성한다.

 이번 글에서는 1번을 다룬다.


EC2 환경 구축 + 포트 개방

AWS EC2 페이지로 들어가서 "인스턴스 시작" 버튼을 클릭한다.

인스턴스 -> 인스턴스 시작

 EC2 환경의 이름을 적당히 짓고, 원하는 운영체제를 선택한다. 나의 경우 프리티어 t2.micro가 지원되는 Amazon Linux 2023을 사용했다.

원하는 운영체제 선택하기

 

인스턴스 유형은 프리티어

 외부에서 EC2 환경에 접근하기 위해서는 키 페어가 필요하다. 새로운 키 페어를 생성하자. 키 페어 생성 버튼을 클릭하면 ssh 프로토콜로 접근할 때 인증 용도로 사용할 수 있는 키 파일이 생성된다. 

새 키 페어 생성 클릭
키 페어를 생성하는 모달. 이름을 적당히 짓고 "키 페어 생성" 버튼을 클릭하자.

 

키 페어 생성 이후에는 보안 그룹을 만들어야 한다. 보단 그룹은 리소스에 대한 트래픽을 제어하는 규칙으로, 인스턴스에 대한 인바운드 및 아웃바운드 트래픽을 조정한다. 여기서 변경하지 않아도 나중에 바꿀 수 있으므로 걱정할 필요는 없다.

보안 그룹

 위 그림에서는 SSH, HTTPS, HTTP 프로토콜에 대한 트래픽 연결 여부를 지정할 수 있다. 여기서 제시하고 있는 트래픽 유형은 그저 웹 환경에서 가장 많이 사용되는 기본값을 지정한다고 생각하면 편하다. 보통 웹 서버 환경을 만든다고 하면 개발 용도로 SSH, 외부 접근 용도로 HTTPS / HTTP 포트를 열어 둔다. 위 그림에서 설정할 수 있는 부분은 딱 거기까지다. 만약 8080 포트로 접근하고 싶다면 나중에 보안 그룹의 인바운드 규칙을 수정하면 된다.

 위와 같이 설정하고 생성하면 가장 표준적인 EC2 인스턴스가 생성된다. 나는 서버를 8080 포트에 대해 열어두었으므로, 위 설정으로는 대응이 안된다. 따라서 인스턴스 생성 이후 보안 그룹을 수정했다.

인스턴스 페이지에서 인스턴스 ID를 클릭하여 인스턴스 요약으로 이동한다.

인스턴스 ID를 클릭

"보안"을 클릭하여 "보안 그룹"으로 이동한 후 인바운드 규칙 편집을 클릭한다.

보안 그룹 클릭. -> 인바운드 규칙 편집 클릭

 

 규칙 추가 버튼을 클릭하여 원하는 인바운드 규칙을 설정한다. 참고로 EC2는 인바운드 규칙에 정의된 트래픽만 수신할 수 수 있으며, 이는 차후 로드밸런싱을 위한 대상 그룹을 만드는 경우에도 동일하게 적용된다. 로드 밸런서에 대상 그룹을 잘 지정하더라도, 그룹에서 EC2 인스턴스의 올바른 포트로 데이터를 전달하지 않는다면 둘은 연결되지 않는다. 8080 같은 포트는 "사용자 지정 TCP"에 속한다.

지정할 수 있는 인바운드 규칙들

 위와 같이 8080 포트를 열어두면, 이제 우리의 EC2 인스턴스에 8080 포트로 접근할 수 있게 된다. 사실 여기까지만 해도 EC2 인스턴스를 간단한 서버 인프라로 사용할 수 있다. 나는 EC2 환경을 테스트하기 위해 EC2 환경에 간단하게 Node.js를 설치하고, 간단한 웹 서버를 열어 정상적으로 외부에서 접근할 수 있는지 시험해 봤다.

 EC2 인스턴스는 웹 환경에서 SSH로 연결할 수 있다. 인스턴스 요약 -> 연결 -> EC2 인스턴스 연결 흐름대로 이동한다. 참고로 웹 환경에서 연결하기 위해서는 기본적으로 SSH 포트를 열어둬야 한다. 만약 SSH 포트를 열어두지 않았다면 보안 그룹으로 이동한 후 인바운드 규칙에서 추가하자.

인스턴스 요약 페이지 우측 상단 연결 클릭
EC2 인스턴스 연결 선택 후 "연결" 버튼 클릭

연결하면 웹에서 콘솔을 사용할 수 있는 환경을 제공해 준다.

등장한 콘솔의 모습

 나는 Amazon Linux 환경에 Node.js를 설치하고, 간단한 웹 서버를 올려 동작을 확인했다. Node.js는 기본적으로 설치되어 있지 않으나, 공식 문서에서 제시하는 대로 붙여 넣기만 해도 쉽게 설치가 가능하다.

 

자습서: Amazon EC2 인스턴스에서 Node.js 설정 - AWS SDK for JavaScript

노드 설치는 현재 Amazon EC2 세션에만 적용됩니다. CLI 세션을 다시 시작하는 경우 nvm을 사용하여 설치된 노드 버전을 활성화해야 합니다. 인스턴스가 종료되면 노드를 다시 설치해야 합니다. 다음

docs.aws.amazon.com

 공식 문서도 귀찮은 사람들을 위해 코드를 제시한다.

# nvm 설치
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
# nvm 활성화
. ~/.nvm/nvm.sh
# nodejs 최신 버전 설치
nvm install --lts

위 코드를 차례대로 콘솔에 붙여 넣으면 Node.js 최신 LTS 버전이 설치된다. 이후 나는 다음과 같은 코드를 담은 index.js 파일을 생성하고 실행했다. 8080 포트에 대해 어떤 요청이 들어오든 간단한 HTML 파일을 반환하는 코드이다.

const { createServer } = require('http');


const server = createServer((req, res) => {
  res.write(`<html>
    <head>
      <title>hello, world!</title>
    </head>
    <body>
      <h1>hello my world!</h1>
      <div>this is test file!</div>
    </body>
    </html>`);
  res.end();
});
server.listen(8080);

생성한 파일 목록

 package.json 파일은 npm init 명령으로 생성한 파일로, script 부분에 "start": "node index.js" 정도만 추가했다.

명령이 실행된 모습

 간단한 웹 서버도 올렸겠다, 이제 EC2 환경에 접속할 수 있는지 확인해 보자. EC2 인스턴스 요약 페이지의 퍼블릭 IPv4 뒤에 내가 열어 둔 포트를 입력하면 Node.js 서버에 접근할 수 있다.

포트가 성공적으로 열려있는 모습이다.


EC2에 Docker 설치

 당연하지만 EC2에는 도커 역시 설치되어 있지 않다. 내가 참고한 글을 따라 설치하면 된다. Amazon Linux 환경에서는 docker에 docker-compose가 포함되어 있지 않아 따로 설치해야 되는 것 같다. 명령 역시 docker compose가 아니라 docker-compose로 접근한다.

당연히 위 문서도 보기 귀찮을 것이라고 생각해서 명령을 정리해 둔다.

# 패키지 관리자 업데이트
sudo dnf update
# 도커 설치
sudo dnf install docker
# 도커 서비스 시작
sudo systemctl start docker
# 실행할 때마다 도커 시작되게 설정
sudo systemctl enable docker
# 도커 상태 보기
sudo systemctl status docker
# 도커 sudo 없이 사용할 수 있게 설정하기
sudo usermod -aG docker $USER

# compose 설치
sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
# 현재 유저(ec2-user)에게 접근 권한 부여
sudo chmod +x /usr/local/bin/docker-compose
# 버전 보기
docker-compose --version

테스트를 수행하기 위해 docker에서 제공하는 매우 가벼운 리눅스 환경인 busybox을 이용하여 메시지를 출력해 보자.

docker run busybox echo "hello, docker!"

busybox를 동작시켜 본 모습

정상적으로 메시지를 출력하는 모습을 볼 수 있다.


탄력적 IP

 우리가 만든 인스턴스를 퍼블릭 IP로 접근할 수 있는 것은 알고 있다. 그런데, 각 인스턴스에 기본으로 제공되는 퍼블릭 IP는 인스턴스를 다시 시작할 때마다 변경된다. 과거에 프로젝트를 진행했을 때는 이걸 몰라서 ec2 환경을 가지고 몇 시간 동안 헤맸던 기억이 있다.

 탄력적 IP를 이용하면 EC2 인스턴스에 고정된 IP 주소를 할당할 수 있다. 네트워크 및 보안 -> 탄력적 IP를 클릭한다.

탄력적 IP로 이동

탄력적 IP 주소 할당 페이지에서 원하는 네트워크 리전을 설정하여 IP 주소를 할당 받는다. 서울은 ap-northeast-2이다.

네트워크 리전 설정

생성된 탄력적 IP를 클릭하여 상세 페이지로 이동한 후 "탄력적 IP 주소 연결"을 클릭한다.

여기 이 버튼!

인스턴스 또는 네트워크 인터페이스를 선택한다.

인스턴스 설정

이후 연결한 인스턴스의 상세 페이지로 이동하면 탄력적 주소가 할당된 모습을 볼 수 있다.

할당된 IP 주소 ( 현재 다시 지움 )
연결된 모습

참고

 탄력적 IP 자체는 글을 작성하는 시점에는 서비스에 연결하는 경우 무료이다 ( 반대로, 연결하지 않으면 과금 존재 ). 2024년 2월 1일부터는 연결 여부와 관계없이 IPv4 주소에 대해 비용을 부과한다고 하며, IPv6로 변경할 것을 권장하고 있다.

https://aws.amazon.com/ko/blogs/korea/new-aws-public-ipv4-address-charge-public-ip-insights/

 

공지 – AWS Public IPv4 주소 요금 변경 및 Public IP Insights 기능 출시 | Amazon Web Services

AWS에서 퍼블릭(Public) IPv4 주소에 대한 새로운 요금이 도입됩니다. 2024년 2월 1일부터 서비스 연결 여부에 관계없이 모든 퍼블릭 IPv4 주소에 대해 시간당 IP당 0.005 USD의 요금이 부과됩니다. 계정에

aws.amazon.com


후기

 EC2 등록부터 Docker 설정까지 정말 간단하게 처리할 수 있었다. 사실 EC2가 IaaS(Infra as a Service)이므로, 리눅스 명령만 조금 안다면 마치 로컬 운영체제를 다루듯 사용할 수 있다는 점이 좋은 것 같다. 반대로 최소한의 명령도 모르는 상황에서는 조금 접근하기 어려울지도 모른다. 

 AWS에 대해 장기적으로 공부하면서 개념들을 좀 잡을 필요가 있을 것 같다. 근 미래에 IPv4에 대해 가격이 부과된다는 점을 고려하면 IPv6로 전환할 필요가 있을 것으로 보인다. 정보를 찾아보니 VPC(virtual private cloud)을 기반으로 설정할 수 있는 것 같은데, 아직 이 부분에 대해서는 지식이 없다. 공부해서 채워야겠다.