devops

Docker이미지를 ECS를 통해 배포해보기(1)

하리하링웹 2024. 5. 14. 20:52

 ECS는 쿠버네티스와 같은 컨테이너 이미지 오케스트레이션 도구이다.

 

이를 사용하여 Docker이미지를 ECS에 배포하는 과정을 실습해보겠다.

1. 테스트용 노드 서버 만들기

여기서는 fastify를 사용한 서버를 만들어보겠다. 먼저 아래 문서를 참고하여 노드 서버를 만들어보자

https://fastify.dev/docs/latest/Guides/Getting-Started/

  • 디렉토리를 만들고 아래 명령어를 실행해준다.
>yarn init 

>yarn add fastify
  • package.json에 아래 코드를 추가해준다.
{
...
  "scripts": {
    "start": "node index.js"
  },
  "type": "module"
}
  • index.js 파일을 루트에 만든 뒤 아래 코드를 추가한다.
import Fastify from "fastify";
const fastify = Fastify({
  logger: true,
});

// Declare a route
fastify.get("/", function (request, reply) {
  reply.send({ hello: "world" });
});

// Run the server!
fastify.listen({ port: 3000 }, function (err, address) {
  if (err) {
    fastify.log.error(err);
    process.exit(1);
  }
  // Server is now listening on ${address}
});

 

정상적으로 서버가 만들어졌다면 아래 이미지와 같은 디렉토리 구조가 만들어져 있을것이다.

 

서버가 잘 동작하는지 테스트해보자.

> yarn start
yarn run v1.22.11
$ node index.js
{"level":30,"time":1713581762291,"pid":99620,"hostname":"Jongsiks-MacBook-Air.local","msg":"Server listening at <http://127.0.0.1:3000>"}
{"level":30,"time":1713581762292,"pid":99620,"hostname":"Jongsiks-MacBook-Air.local","msg":"Server listening at http://[::1]:3000"}

 

이후 새 터미널을 열어준다.

curl -X GET <http://127.0.0.1:3000>
{"hello":"world"}%                            

hello:world 텍스트가 보인다면 정상적으로 서버가 동작하고 있는것이다.

 

이제 다음 과정을 위해 서버를 종료해준다.

2. Docker Image 만들기 + ECR에 올리기

자세한 명령어 설명 + 로직은 아래 글을 참고하면 된다.

https://jjongsk.tistory.com/entry/Docker-AWS-ECRLambda를-사용하여-nodejs-function-serverless로-배포하기

 

일단 index.js 파일의 서버를 listen하는 부분을 아래처럼 수정해준다.

fastify.listen({ port: 3000, host: "0.0.0.0" }, function (err, address) {
  if (err) {
    fastify.log.error(err);
    process.exit(1);
  }
  // Server is now listening on ${address}
});

host부분을 입력하지 않으면 127.0.0.1에 대해서만 요청을 받게되니 IPv4 요청을 위해 0.0.0.0 으로 host 값을 변경해준다.

 

이제 Docker 파일을 작성해준다. 정말 단순하게 yarn install 이후 start해주는 docker 파일이다.

 

[dockerfile]

FROM node:18 AS test

COPY . . 

RUN yarn
CMD yarn start

 

[.dockerignore]

node_modules/

 

이후 로컬에서 docker image를 빌드 해준다.

docker build -t fastify-ecs-prac . 

 

해당 도커 이미지를 컨테이너로 실행시켜준다.

docker run -dp 3000:3000 --name fastify-ecs-container fastify-ecs-prac

 

이제 테스트 해보면 서버가 정상적으로 동작하는것을 확인할 수 있다.

> curl -X GET <http://127.0.0.1:3000>
{"hello":"world"}%                       

3. ECR에 Docker image 올리기

fastify-ecr-prac 이름으로 ECR repository를 private 설정으로 만들어준다.

 

aws-cli를 사용해서 ecr에 로그인해준다.

aws-cli 권한, key,secret 등의 세팅은 생략하도록 하겠다. 이전에 작성한 Docker, AWS ECR,Lambda를 사용하여 node.js function… 글을 참고하면 된다.

> aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 835907790565.dkr.ecr.ap-northeast-2.amazonaws.com/fastify-ecr-prac
Login Succeeded

이전에 빌드한 이미지에 ECR 푸쉬를 위한 태그를 추가해준다

> docker tag fastify-ecs-prac 835907790565.dkr.ecr.ap-northeast-2.amazonaws.com/fastify-ecr-prac

이제 ECR에 해당 이미지를 푸쉬해준다.

docker push 835907790565.dkr.ecr.ap-northeast-2.amazonaws.com/fastify-ecr-prac

위와같이 이미지 이름 뒤에 :latest, :[hash] 와 같이 태깅을 하지 않으면 자동으로 :latest 태그가 붙는다.

 

이제fastify-ecr-prac repository에 들어가보면 도커 이미지를 확인할 수 있다.

 

4. VPC 설정하기

vpc 설정

이제 ECS 컨테이너를 격리된 네트워크로 관리하기 쉽게 동작하게 만들기 위해 VPC를 설정해준다.

 

create VPC를 누른 뒤 아래와 같이 작성하여 생성해준다

 

Name tag는 말 그대로 이름을 설정하는 작업이며 IPv4 CIDR 값은 10.0.0.0/16 설정을 통해 네트워크, 호스트 주소 설정을 해준다 aws vpc는 IPv4 CIDR 설정에 있어 16 ~ 28 사이의 넷 마스크 값만 사용하고 있다.

서브넷 설정

다음으로 서브넷을 설정해준다. VPC 내부에서 subnets 탭으로 이동하여 create subnet 버튼을 누른다.

 

방금 만든 VPC를 선택해준다.

 

서브넷은 2개만 사용할 예정이며 원하는대로 변경해도 상관 없다.

[fastify-ecs-prac-subnet1]

zone: ap-northeast-2a

IPv4 subnet CIDR block: 10.0.1.0/24

 

[fastify-ecs-prac-subnet2]

zone: ap-northeast-2b

IPv4 subnet CIDR block: 10.0.2.0/24

 

잘 만들어졌다면 아래의 이미지와 같은 모습을 확인할 수 있다. 한 서브넷당 251의 사용 가능한 IP를 부여받는다.

(network address, vpc router, aws reverved, broad casting ip,dns server ip 제외)

 

인터넷 게이트웨이 설정

이제 VPC를 인터넷과 통신하도록 만들기 위해 인터넷 게이트웨이를 설정해야한다.

internet gateway 탭으로 이동하여 create 버튼을 누른다.

 

 

생성된 인터넷 게이트웨이를 VPC와 연결해준다.

 

 

라우팅 테이블 설정

다음으로는 라우팅 테이블을 추가/설정해줘야한다.

이 설정이 필요한 이유는 각 VPC는 내부적으로 통신할 수 있도록만 설정되어 있기 때문에 인터넷 게이트웨이를 추가한것이며 이를 각 VPC의 라우팅 테이블에 추가해줘야 인터넷과 통신을 할 수 있게 된다.

 

route table 탭으로 이동하여 create 버튼을 눌러 이름, VPC를 추가해주고 라우팅 테이블을 생성해준다.

 

이제 생성된 route table id를 눌러 들어가 routes와 subnet associations가 아래 이미지처럼 잘 만들어져 있는지 확인해본다.

Explicit subnet associationsSubnets without explicit associations 차이는 라우팅 테이블과 명시적으로 연결이 되어있냐의 유무이다.

Subnets without explicit associations 아래의 서브넷들은 라우팅 테이블을 통해 같은 VPC에 있지만 명시적으로 연결이 되어있지 않기에 VPC 기본 라우팅 테이블과 암시적으로 연결되어있다.

 

 

이제 인터넷 통신을 위해 생성한 라우팅 테이블에 인터넷 게이트웨이 정보를 추가해주자

라우팅 테이블 id를 클릭해

들어가 Edit routes 버튼을 클릭한 뒤 아래와 같이 설정해준다.

 

 

여기까지 VPC의 설정이 완료되었다. 이어지는 Load balancer 설정부터는 다음글에 이어서 작성하도록 하겠다.

 

 

2편 링크

https://jjongsk.tistory.com/entry/Docker%EC%9D%B4%EB%AF%B8%EC%A7%80%EB%A5%BC-ECS%EB%A5%BC-%ED%86%B5%ED%95%B4-%EB%B0%B0%ED%8F%AC%ED%95%B4%EB%B3%B4%EA%B8%B02