인프라
Docker CI/CD에 Docker Compose 적용하여 자동배포 하기 (EC2, Github Action, NestJS, ECR)(container 3개)
김도리개발자
2023. 5. 1. 16:59
지난 글에서 Docker CI/CD 구성하여 자동배포 하기를 했는데
그 다음 순서로 Docker Compose까지 적용해보자
EC2 인스턴스에 compose 설치해주기
https://docs.docker.com/compose/install/linux/
https://zosystem.tistory.com/324
공홈 그대로 따라하거나 위의 레퍼런스 따라하여 Docker Compose를 설치한다.
curl -L "https://github.com/docker/compose/releases/download/v2.17.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
docker-compose --version
docker-compose.yml & docker-image.yml
version: '3.8'
services:
api-1:
container_name: test-docker-nest-1
image: "647180380627:dkr:ecr:ap-northeast-2:amazonaws:com/test-docker-nest:latest"
ports:
- "3232:3232"
volumes:
- ./:/app/
command:["sh", "-c", "sleep 20 && npm run start"]
api-2:
container_name: test-docker-nest-2
image: "647180380627:dkr:ecr:ap-northeast-2:amazonaws:com/test-docker-nest:latest"
ports:
- "3233:3232"
volumes:
- ./:/app/
command:["sh", "-c", "sleep 20 && npm run start"]
api-3:
container_name: test-docker-nest-3
image: "647180380627:dkr:ecr:ap-northeast-2:amazonaws:com/test-docker-nest:latest"
ports:
- "3234:3232"
volumes:
- ./:/app/
command:["sh", "-c", "sleep 20 && npm run start"]
docker-compose.yml 코드 작성
name: Docker Image CI
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-2
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: "test-docker-nest"
IMAGE_TAG: ${{ github.sha }}
run: |
docker buildx build --platform=linux/amd64 -t $ECR_REGISTRY/$ECR_REPOSITORY:latest .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:latest
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:latest"
- name: SSH Commands
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.AWS_SSH_HOST }}
username: ${{ secrets.AWS_SSH_USERNAME }}
key: ${{ secrets.AWS_SSH_KEY }}
port: ${{ secrets.AWS_SSH_PORT }}
script_stop: true
script: |
sudo aws ecr get-login-password --region ap-northeast-2 | sudo docker login --username AWS --password-stdin 647180380627.dkr.ecr.ap-northeast-2.amazonaws.com
sudo docker pull 647180380627.dkr.ecr.ap-northeast-2.amazonaws.com/test-docker-nest:latest
counter1=`sudo docker container ls -a | sudo grep -c "test-docker-nest-1"`; if [ $counter1 -eq 1 ]; then sudo docker container rm -f "test-docker-nest-1" ;fi
counter2=`sudo docker container ls -a | sudo grep -c "test-docker-nest-2"`; if [ $counter2 -eq 1 ]; then sudo docker container rm -f "test-docker-nest-2" ;fi
counter3=`sudo docker container ls -a | sudo grep -c "test-docker-nest-3"`; if [ $counter3 -eq 1 ]; then sudo docker container rm -f "test-docker-nest-3" ;fi
sudo docker-compose -f docker-compose.yml up
docker-image.yml 코드 수정
docker compose EC2 인스턴스에 CI/CD로 배포해주기
1. docker-compose.yml 빼먹기
- 에러메시지 : Invalid workflow file: .github/workflows/docker-image.yml#L40
- 문제 : docker-compose.yml를 ec2 인스턴스에 어떻게 올릴지 생각이 필요하다.
- 솔루션 : 원래였으면 git으로 관리해서 ec2에 그때마다 docker-compose.yml 파일만 pull 받아와야 하나? 했는데
그럼 시간도 더 들다보니까 로컬에 만들어 놓는 방법으로 일단은 진행하기로 함
2. 이미지 지정 에러
바로 성공하면 Docker Compose가 아니지,
- 에러메시지 : err: Error response from daemon: no such image: ***:dkr:ecr:ap-northeast-2:amazonaws:com/test-docker-nest:latest: invalid reference format
- 문제 : docker-compose에서 image 지정에 “” 큰따옴표 붙여서 발생한 상황
- 솔루션 : docker-compose에서 image를 지정할 때 "" 큰따옴표 제외하고 넣어줌
version: '3.8'
services:
api-1:
container_name: test-docker-nest-1
image: 647180380627.dkr.ecr.ap-northeast-2.amazonaws.com/test-docker-nest:latest
ports:
- "3232:3232"
volumes:
- ./:/app/
command:["sh", "-c", "sleep 20 && npm run start"]
api-2:
container_name: test-docker-nest-2
image: 647180380627.dkr.ecr.ap-northeast-2.amazonaws.com/test-docker-nest:latest
ports:
- "3233:3232"
volumes:
- ./:/app/
command:["sh", "-c", "sleep 20 && npm run start"]
api-3:
container_name: test-docker-nest-3
image: 647180380627.dkr.ecr.ap-northeast-2.amazonaws.com/test-docker-nest:latest
ports:
- "3234:3232"
volumes:
- ./:/app/
command:["sh", "-c", "sleep 20 && npm run start"]
3. 빌드는 되었으나 컨테이너가 죽음
빌드는 성공했다고 뜨나 컨테이너 실행되고 있는지 확인해보니까 3개 모두 돌다가 죽어버림
docker logs로 로그 확인해보기
- 에러메시지 : no such file or directory, open '/app/package.json’
- 문제 :
- package.json을 못찾아오는 문제이며,
Dockerfile에서 WORKDIR를 /app으로 해준 것이 문제인 것 같음COPY . . 이 다 끝나기 전에 npm install을 실행하는데 아직 package.json이 복사되기 이전에 실행해서 package.json을 못 찾는 문제 같음
- package.json을 못찾아오는 문제이며,
https://darrengwon.tistory.com/804
https://2donny-world.tistory.com/14
- 솔루션 :
WORKDIR /home/app으로 바꿔줘서 해봄- COPY package.json ./
npm install
COPY ./ ./
Dockerfile 실행 코드 및 순서를 변경해줌
4. 3개 중 1개만 죽음
- 문제 : 2개의 컨테이너는 돌아가는데 1개의 컨테이너는 죽는 상황
- 솔루션 :
- echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p 를 EC2 인스턴스의 터미널에서 실행시켜 watches의 max개수를 늘린다.
https://velog.io/@crazy4u2/Error-ENOSPC-System-limit-for-number-of-file-watchers-reached
5. 여전히 3개 중 1개 죽음
FROM node:16-alpine asbase
WORKDIR /home/app/
COPY package.json ./
RUN npm install
COPY ./ ./
RUN npm run build
EXPOSE 3232
CMD["npm", "run", "start"]
Dockerfile 코드도 좀 손보고 다시 돌려봄
- 문제 : 로그도 안남고 NestJS가 실행이 되다가 말고 죽는 현상
- 솔루션 : 여전히 watches의 max 개수 문제인 것 같아 더 늘려줌 999999로
6. 성공!
컨테이너 3개 모두 잘 돌아간다!
이렇게 Docker Compose 까지 적용한 CI/CD 를 구성해보았다.