사실 이전에 http으로만 돌아가도록 배포작업은 끝내두었었으나, 클라우드 서비스를 공부할 겸 좀 더 딥하고 실무와 유사하게 배포해보는 연습을 하고 싶었습니다. 그렇기 때문에 3가지 레포지토리 ()로 구성된 프로젝트를 하나의 레포지토리로 모아서 관리하여 배포하도록 하는 여정을 떠나보려고 합니다.
일단 오늘은 AWS IAM, AWS ECR 서비스를 통해 배포 시에 Docker 이미지를 ECR에 저장하는 것 까지 구현했습니다.
IAM 설정하기
먼저 IAM 계정을 생성하였습니다.
저는 사용자 생성 버튼을 클릭하여 study-log-manager를 만들어 주고, 해당 사용자 이름을 클릭하여 추가적인 설정을 진행했습니다.
일단 저는 최종적으로 EC2에 배포를 할 예정이므로 AmazonEC2ContainerRegistryFullAccess와 AmazonElasticContainerRegistryPublicFullAccess를 우선적으로 추가했습니다.
그 다음으로는 액세스 키를 발급받았습니다. 이 액세스키를 통해 Github Action에서 CI / CD 파이프라인을 구현할 때 제 계정을 통해 연결을 할 수 있게 되는 것입니다.
액세스 키 만들기 버튼을 클릭하여 액세스 키를 발급받으면 되는데 여기에 시크릿 키도 함께 발급됩니다.
csv 형태로도 저장할 수 있게 해주니 꼭 저장하시길 바랍니다!
여기까지 ECR을 위한 IAM 설정을 마친 것 같습니다. 그 다음으로 ECR을 만들어 보도록 합시다.
ECR 설정하기
저는 Private Registry를 생성하여 진행하였습니다. ECR은 컨테이너에서 생성한 이미지를 저장할 수 있는 공간이며, Docker Hub와 유사한 역할을 한다고 생각하면 될 것 같습니다.
이렇게 생성하면 간단한 ECR 설정은 끝이 났습니다. 이제 도커를 통해 이미지가 빌드가 잘되는지 확인을 해볼 차례입니다.
도커파일 작성하기
도커 이미지가 잘 만들어져서 로컬에서 테스트가 가능한지 확인을 해봐야 한다.
현재 제 프로젝트 폴더 구조는 크게 3가지로 나뉩니다. (백 / 프론트 / 익스텐션)
<저의 레포지토리 구조>
.
├── README.md
├── client
├── extension
└── server
<서버 폴더의 레포지토리 구조>
.
├── README.md
├── config
├── dist
├── nest-cli.json
├── node_modules
├── package-lock.json
├── package.json
├── src
├── tsconfig.build.json
└── tsconfig.json
저는 server 디렉토리 안에 Dockerfile.prod 파일을 만들어서 작성을 해보도록 하겠습니다.
# 1. Node.js의 경량 버전 기반 이미지 사용
FROM node:18-alpine
# 2. 작업 디렉토리 설정
WORKDIR /app
# 3. package.json과 package-lock.json 복사
COPY package*.json ./
# 4. 종속성 설치
RUN npm install
# 5. 애플리케이션 소스 코드 복사
COPY . .
# 6. Nest.js 애플리케이션 빌드
RUN npm run build
# 7. 포트 설정
EXPOSE 8080
# 8. 애플리케이션 시작
CMD ["npm", "run", "start:prod"]
이렇게 도커 파일을 작성했다면 이 도커 파일을 기반으로 이미지를 만들 수 있는지, 컨테이너의 실행이 가능한지, 정상적으로 작동해야 하는지 확인할 필요가 있습니다.
먼저 이미지 빌드가 잘 되는지 확인해봅시다. 다음과 같은 명령어를 통해 이미지를 빌드해봅시다.
docker build -t capstone-server -f ./Dockerfile.prod
그 결과 빌드가 아주 잘 되었음을 확인할 수 있었습니다.
그 다음에는 컨테이너의 실행을 할 수 있는지 확인해보도록 하겠습니다.
docker run -d -p 8080:8080 capstone-server
이미지 기반으로 컨테이너도 잘 실행되는 것을 볼 수 있었습니다.
그 다음 도커 대시보드에서 직접 로그를 보며 잘 실행되었는지 확인했습니다.
DB 연결오류는 MongoDB Atlas 관련된 오류일테니 일단은 실행되는지만 확인하고 넘어가겠습니다
Github Action을 통해 CI / CD 작업 진행하기
이제 마지막으로 Github Action을 통해 소스코드가 특정 브랜치에 푸시되면 특정 디렉토리(server)의 코드를 기반으로 도커 이미지를 만들고, 이미지를 ECR에 전송하는 CI 파이프라인을 구현해보겠습니다.
먼저 아까 IAM에서 받았던 secret key와 access key를 Github Action 환경변수에 추가해줍시다.
설정의 Secrets and variables의 Actions로 들어가봅시다.
여기서 New Repository Secret 버튼을 눌러 Github Action yaml 파일을 작성해보도록 하죠.
환경변수 설정까지 마쳤다면 이제는 ci를 위한 yaml 파일을 만들어보도록 합시다.
프로젝트 디렉터리 최상단에 `.github/workflows/be-ci.yaml` 을 만들고, be-ci.yaml 파일을 채워넣어봅시다.
name: Dockerizing to Amazon ECR # 워크플로우의 이름을 'Dockerizing to Amazon ECR'로 설정합니다.
on:
push: # 특정 브랜치에 코드가 푸시될 때 워크플로우가 트리거됩니다.
branches: ["main"] # 'main' 브랜치에 푸시될 때만 워크플로우 실행
pull_request: # 풀 리퀘스트가 열리거나 업데이트될 때 트리거됩니다.
branches: ["main"] # 'main' 브랜치에 대한 풀 리퀘스트일 때만 실행
env: # 공통 환경 변수를 설정합니다.
AWS_REGION: ap-northeast-2 # AWS 리전을 서울 리전으로 설정
ECR_REPOSITORY: study-log # ECR 저장소 이름을 'study-log'로 설정
jobs: # 실행할 작업을 정의합니다.
deploy: # 'deploy'라는 작업을 정의합니다.
name: Deploy # 작업의 이름을 'Deploy'로 설정
runs-on: ubuntu-latest # 최신 Ubuntu 버전에서 실행되도록 설정
environment: production # 이 작업이 'production' 환경에서 실행됨을 정의
steps: # 이 작업에서 실행될 단계들을 정의합니다.
- name: Checkout # 소스 코드를 체크아웃하는 단계
uses: actions/checkout@v3 # GitHub 제공 체크아웃 액션 사용
- name: Config AWS credentials # AWS 자격 증명을 구성하는 단계
uses: aws-actions/configure-aws-credentials@v2 # AWS 자격 증명 구성 액션 사용
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # GitHub Secrets에 저장된 AWS 액세스 키 ID 사용
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # GitHub Secrets에 저장된 AWS 시크릿 액세스 키 사용
aws-region: ${{ env.AWS_REGION }} # 위에서 정의한 AWS 리전 사용
- name: Login To Amazon ECR # Amazon ECR에 로그인하는 단계
id: login-ecr # 이 단계의 ID를 'login-ecr'로 설정 (후속 단계에서 참조 가능)
uses: aws-actions/amazon-ecr-login@v1 # Amazon ECR 로그인 액션 사용
- name: Build, tag, and push image to Amazon ECR # Docker 이미지를 빌드, 태그, ECR에 푸시하는 단계
id: build-image # 이 단계의 ID를 'build-image'로 설정
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} # ECR 레지스트리 URL 설정
IMAGE_TAG: ${{ github.sha }} # GitHub의 커밋 SHA 값을 이미지 태그로 사용
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG -f ./server/Dockerfile.prod ./server # 지정된 Dockerfile을 사용하여 이미지를 빌드하고 태그 지정
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG # 빌드된 이미지를 ECR에 푸시
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" # 빌드된 이미지 URL을 워크플로우 출력으로 설정
이렇게 구성을 하고, 코드를 메인 브랜치에 푸시를 하게 되면 다음과 같이 성공함을 볼 수 있습니다.
빌드된 이미지가 ECR에 제대로 들어갔는지도 확인해야 합니다.
빌드 프로세스가 잘 들어갔음을 확인할 수 있었습니다..
다음에는 ECR에 들어간 이미지를 기반으로 EC2 인스턴스에서 실행하고, https를 위한 설정을 진행해보도록 하겠습니다
참고한 블로그
https://chance-story.tistory.com/30
https://velog.io/@bik1111/AWS-ECR-Github-Actions-%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EB%93%B1%EB%A1%9D
https://iamiet.tistory.com/entry/EC2-ECR-Docker%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-CICD-%EA%B5%AC%EC%B6%95-with-Github-Actions
https://velog.io/@linho1150/ECS-ECR-Github-Actions%EB%A5%BC-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-Nest.js-CICD%ED%95%98%EA%B8%B0
https://dev-dorydory.tistory.com/m/55