인프라

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/

 

Install the Compose plugin

 

docs.docker.com

https://zosystem.tistory.com/324

 

CentOS 7 - Docker, Docker-compose 설치

docker 설치(repository추가 및 install) # yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin docker 서비스 시작,상태확인, 자동시작

zosystem.tistory.com

공홈 그대로 따라하거나 위의 레퍼런스 따라하여 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을 못 찾는 문제 같음

https://darrengwon.tistory.com/804

 

node.js 기반 앱을 docker 환경에서 실행해보자

요약 dockerfile 생성, .dockerignore 생성 dockerfile 캐싱에 유의하며 작성 docker build -t name 으로 도커 이미지 빌드 docker run -p 사용할 포트:컨테이너 포트 도커이미지를 실행하여 컨테이너 환경에서 앱 실

darrengwon.tistory.com

https://2donny-world.tistory.com/14

 

docker-compose up 실행 시 no such file or directory, open '/usr/src/app/package.json' 에러

AWS로 배포하려고 요즘 애를 많이 먹고있다. 현 상황은 Node.js 기반 서버를 로컬에서 테스트하고 있는 상황이다. 근데 nginx로 프록싱도 해야해서 docker-compose를 쓰는 상황이다. 문제가 된 Node.js 이미

2donny-world.tistory.com

  • 솔루션 :
    • 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

 

Error: ENOSPC: System limit for number of file watchers reached,

가끔 react 를 가지고 열심히 일을 하다보면 라는 에러를 내뱉는 경우를 볼 수 있다. 이럴 경우 라고 터미널에 입력해주면 아주 깔끔하게 처리된다.원인은 너무 열심히 일을 해서 시스템의 파일와

velog.io

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 를 구성해보았다.