Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Continuously Deploying Your Docker Application to AWS EC2 & ECR Using CircleCI
soom
soom

Posted on • Edited on

     

Continuously Deploying Your Docker Application to AWS EC2 & ECR Using CircleCI

Abstract

최근 배포 프로세스는 프로젝트를Docker 이미지로 말아서AWS ECS/ECR 조합으로 가는 것이 일반적이다.

그러나 라이트유저에겐 상대적으로 사악할 수 있는 가격 정책을 보여주는AWS ECS이기에 이번 포스팅에서는 그냥 기본 서버 환경을 제공하는AWS EC2AWS ECR 이미지를 올리는 방법을 소개하고자 한다.

추가로 대세 CI 툴인CircleCI를 통해 파이프 라인을 구성해보았다.

참고할만한 링크:https://circleci.com/developer


Getting Started

Prerequisite


Preparing AWS ECR

AWS ECR (Elastic Container Registry) 서비스에 들어가 Repository를 생성

다른 설정은 기본으로 name 만 잘 설정해주면 앞으로 이미지를 저장할 레포지토리가 생성된다.

여기서 중요한 것은 RepositorynameURI. 기억해두자.

ecr_1

ecr_2


Setting up CircleCI Application

먼저 프로젝트에서/.circleci/config.yml empty 파일을 생성한 후 깃레포지토리에 푸시

Project tree

.├── ./circleci/│   └── config.yml└── ...project
Enter fullscreen modeExit fullscreen mode

CircleCI에 로그인한뒤 프로젝트 탭에서Set Up Project 를 선택

작업할branch 이름를 입력해주면 다음처럼 메세지가 나오고 진행하면 프로젝트 대쉬보드로 진입

cc_1

cc_2


Project Setting에 환경 변수 입력

실제 프로젝트에서config.yml 설정할때 사용하게 될 변수들

추가로SSH Keys 메뉴에서EC2 접속을 위해Additional SSH Keys를 등록해준다
안할 경우CircleCi 에서EC2 접근 불가할 수 있음

해당하는 키 생성 방법 링크 참조:https://circleci.com/docs/add-ssh-key/

cc_3

cc_4

cc_5

Required Env Value

  • AWS_ACCOUNT_ID
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
  • AWS_REGION
  • AWS_ECR_ACCOUNT_URL
  • AWS_ECR_REPO_NAME

Generating Dockerfile

먼저 로컬에서Docker image 를 말아보자.

여기서는 자세한Docker 사용법은 언급하지 않고 넘어가겠다.

참고할만한 링크:https://docs.docker.com/get-started/

Root 폴더에Dockerfile을 생성, 다음과 같이 작성

Doockerfile

ARG node_version=18-bullseye-slimARG prod_port=3000FROM node:${node_version}WORKDIR /appCOPY . .ENV TZ=Asis/SeoulRUNcorepackenableRUNcorepack prepare pnpm@latest--activateRUNpnpminstallRUNpnpm buildEXPOSE ${prod_port}CMD pnpm start:prod
Enter fullscreen modeExit fullscreen mode
  • node 18버전 환경에서 작업: 18-bullseye-slim
  • node 18에서pnpm 패키지는corepack으로 활성 가능하다

Configuring CircleCI in project

Root 폴더에/.circleci 폴더를 생성

해당하는 폴더 내에config.yml 파일을 작성해보자


맨 첫줄은CircleCI version 부분이다.

두번째orbsCircleCI가 제공하는 편의성 패키지
여기서는ecr 을 편리하게 지원해주는aws-ecr 패키지를 사용

executor는 여기서 반복적으로 사용할 환경 실행에 대한 언급

  • machine:image:ubuntu-2004:current

보통CircleCI 에서는 직접Docker 환경을 불러오는 것이 보통이나
여기서는 이미지에 프로젝트를 복사해서 직접 명령어를 실행하는것이 아닌
Dockerfile로 이미지를 빌드 후AWS ECR에 업로드할 예정이기에
다양한 명령어 접근을 위해 이미지가 아닌machine 레벨로 구성하였다. (여기서는ubuntu 환경을 구성)

  • working_directory: ~/project

/project 폴더에 작업할 예정 (checkout도 이 폴더에서 진행된다)

config.yml

version:2.1orbs:aws-ecr:circleci/aws-ecr@8.2.1executors:machine-executor:machine:image:ubuntu-2004:currentdocker_layer_caching:trueworking_directory:~/project# ... more on next line
Enter fullscreen modeExit fullscreen mode

기본적으로CircleCIJobJobs 에 정의하고
workflow 에 흐름을 등록하는 방식으로 진행된다.

여기서는Pre-Build라는 첫번째job 을 선언하였다.

미리 선언해 주었던machine-executor를 이용해 환경 구성을 진행하고

  • checkout

checkout 을 통해 연결된git repository 를 복사한다. (/project 폴더 안에 복사)

  • Getting Node Environment / the Code

여기에서는machineNode Environment 확인,checkout 정상 진행여부 확인

  • persist_to_workspace

마지막으로 이 전체를 다음job에 동일하게 진행할 예정이기에workspace에 관련 부분을 선언

Note

config.yml

# ... continuejobs:Pre-Build:executor:machine-executorsteps:-checkout-run:name:Getting Node Environmentcommand:|node -vnpm -vnpm -g lsecho '^^^ node default env^^^'-run:name:Getting the Codecommand:|ls -alecho '^^^ Your repo files^^^'-persist_to_workspace:root:.paths:-.# ... more on next line
Enter fullscreen modeExit fullscreen mode

두번째job 선언 부분

  • attach_workspace

여기서는 방금 전 step에서 저장한 환경을 다시 load한다.

  • Attach Workspace Complete

그 다음에 환경이 다시 잘 구성되었는지 확인

  • aws-ecr/build-and-push-image

마지막으로aws-ecrorb 설정 부분이다.
orb 는 따로 복잡한 설정 필요없이 간단한 설정만으로
도커로 이미지 빌드후 등록한AWS ECR에 이미지를 푸시해주는 역할을 해준다.

$AWS_ECR_REPO_NAME 은 ECR Repo 이름이고$CIRCLE_SHA1CircleCI에서 자동으로 생성하는 난수
image_name:tag name 형식으로AWS ECR에 이미지 생성

Note

config.yml

# ... continuejobs:#  ... Pre-BuildBuild-and-Push:executor:machine-executorsteps:-attach_workspace:at:~/project-run:name:Attach Workspace Completecommand:|ls- alecho '^^^ Attaching workspace success. ^^^'-aws-ecr/build-and-push-image:repo:$AWS_ECR_REPO_NAMEtag:$CIRCLE_SHA1dockerfile:Dockerfile# ... more on next line
Enter fullscreen modeExit fullscreen mode

마지막jobDeploy

  • Allow Access to Production EC2

먼저 첫번째 step 에서는AWS EC2ssh를 이용해 접속하기 위해 22번 포트를 개방

  • Waiting for AWS Security Settings to Take Effect

적용 하는데 다소 시간이 필요하기에sleep을 실행

  • AWS EC2 Deploy

AWS EC2 에 접속 후 서버 환경에서Docker login 후 ECR에 등록된Docker Image 를 pull 해온다.

이 이미지를 미리AWS EC2에 작성해둔docker-compose.yaml 을 통해 서버에서 실행할 예정
docker-compose.yaml 파일은infra 폴더안에 위치할 예정

이때docker-compose.yaml 에서 사용할 환경변수를 미리 선언

  • Remove Circle CI Instance Ingress Rule

일전에 개방한 22번 포트를 다시 폐쇄

config.yml

# ... continuejobs:#  ... Pre-Build, Build ..Deploy:executor:machine-executorsteps:-run:name:Allow Access to Production EC2command:|CIRCLE_CI_BUILD_MACHINE_IP=$(curl ipinfo.io/ip)aws ec2 authorize-security-group-ingress --region $AWS_REGION \--group-id $PROD_SERVER_SG_ID \--protocol tcp \--port 22 \--cidr $CIRCLE_CI_BUILD_MACHINE_IP/24-run:name:Waiting for AWS Security Settings to Take Effectcommand:sleep5-run:name:AWS EC2 Deploycommand:|ssh -o StrictHostKeyChecking=no $AWS_DEPLOYER@$EC2_PUBLIC_DNS \"sudo docker login --username AWS -p $(aws ecr get-login-password --region $AWS_REGION) $AWS_ECR_ACCOUNT_URL && \sudo docker pull $AWS_ECR_ACCOUNT_URL/$AWS_ECR_REPO_NAME:$CIRCLE_SHA1 && \export CIRCLE_SHA1=$CIRCLE_SHA1 && \export AWS_ECR_ACCOUNT_URL=$AWS_ECR_ACCOUNT_URL && \export AWS_ECR_REPO_NAME=$AWS_ECR_REPO_NAME && \export PROD_PORT=3000 && \cd /home/ec2-user/infra && \docker compose up -d hello-world"-run:name:Remove Circle CI Instance Ingress Rulecommand:|CIRCLE_CI_BUILD_MACHINE_IP=$(curl ipinfo.io/ip)aws ec2 revoke-security-group-ingress --region $AWS_REGION \--group-id $PROD_SERVER_SG_ID \--protocol tcp \--port 22 \--cidr $CIRCLE_CI_BUILD_MACHINE_IP/24# ... more on next line
Enter fullscreen modeExit fullscreen mode

config.yml 전문은 다음과 같다

기본workflow 상태에서는 설정한branch (여기서는main) 소스를 푸시하면 바로 빌드가 시작

여기서는 따로 릴리즈 태그를 등록해야 배포 프로세스가 시작하도록 설정하였다.

config.yml

version:2.1orbs:aws-ecr:circleci/aws-ecr@8.2.1executors:machine-executor:machine:image:ubuntu-2004:currentdocker_layer_caching:trueworking_directory:~/projectjobs:Pre-Build:executor:machine-executorsteps:-checkout-run:name:Getting Node Environmentcommand:|node -vnpm -vnpm -g lsecho '^^^ node default env^^^'-run:name:Getting the Codecommand:|ls -alecho '^^^ Your repo files^^^'-persist_to_workspace:root:.paths:-.Build-and-Push:executor:machine-executorsteps:-attach_workspace:at:~/project-run:name:Attach Workspace Completecommand:|ls- alecho '^^^ Attaching workspace success. ^^^'-aws-ecr/build-and-push-image:repo:$AWS_ECR_REPO_NAMEtag:$CIRCLE_SHA1path:dockerdockerfile:Dockerfile.prodDeploy:executor:machine-executorsteps:-run:name:Allow Access to Production EC2command:|CIRCLE_CI_BUILD_MACHINE_IP=$(curl ipinfo.io/ip)aws ec2 authorize-security-group-ingress --region $AWS_REGION \--group-id $PROD_SERVER_SG_ID \--protocol tcp \--port 22 \--cidr $CIRCLE_CI_BUILD_MACHINE_IP/24-run:name:Waiting for AWS Security Settings to Take Effectcommand:sleep5-run:name:AWS EC2 Deploycommand:|ssh -o StrictHostKeyChecking=no $AWS_DEPLOYER@$EC2_PUBLIC_DNS \"sudo docker login --username AWS -p $(aws ecr get-login-password --region $AWS_REGION) $AWS_ECR_ACCOUNT_URL && \sudo docker pull $AWS_ECR_ACCOUNT_URL/$AWS_ECR_REPO_NAME:$CIRCLE_SHA1 && \export CIRCLE_SHA1=$CIRCLE_SHA1 && \export AWS_ECR_ACCOUNT_URL=$AWS_ECR_ACCOUNT_URL && \export AWS_ECR_REPO_NAME=$AWS_ECR_REPO_NAME && \export PROD_PORT=3000 && \cd /home/ec2-user/infra && \docker compose up -d allco-kids-backend"-run:name:Remove Circle CI Instance Ingress Rulecommand:|CIRCLE_CI_BUILD_MACHINE_IP=$(curl ipinfo.io/ip)aws ec2 revoke-security-group-ingress --region $AWS_REGION \--group-id $PROD_SERVER_SG_ID \--protocol tcp \--port 22 \--cidr $CIRCLE_CI_BUILD_MACHINE_IP/24workflows:build_and_deploy_image:jobs:-Pre-Build:context:fetch-codefilters:tags:only:/server-v\d{1}\.\d{1,2}\.\d{1,3}/# 버전 정규식 server-v1.0.0의 형태branches:ignore:/.*/-Build-and-Push:requires:-Pre-Buildfilters:tags:only:/server-v\d{1}\.\d{1,2}\.\d{1,3}/# 버전 정규식 server-v1.0.0의 형태branches:ignore:/.*/-Deploy:requires:-Pre-Build-Build-and-Pushfilters:tags:only:/server-v\d{1}\.\d{1,2}\.\d{1,3}/# 버전 정규식 server-v1.0.0의 형태branches:ignore:/.*/
Enter fullscreen modeExit fullscreen mode

Setting up docker-compose on EC2

EC2 에 접속해서root/infra 폴더를 생성

그 안에docker-compose.yaml 을 생성한 뒤 다음과 같이 작성

docker-compose.yaml

version:'3.9'services:hello-world:image:${AWS_ECR_ACCOUNT_URL}/${AWS_ECR_REPO_NAME}:${CIRCLE_SHA1}restart:alwaysports:-${PROD_PORT}:${PROD_PORT}volumes:-../src:/app/src
Enter fullscreen modeExit fullscreen mode

이제github 에 태그를 생성하면 자동으로CircleCI 에서 배포 프로세스가 시작될 것이다.

ECR 에 이미지도 정상적으로 생성된 것을 확인할 수 있다.

cc_6

cc_7


Conclusion

CircleCI를 쓰면서 느낀점은Jenkins 보다는 훨씬 직관적인데다 미관적으로 더 낫다 라는 점이었다.
이런 부분이 작업하는 중간중간 만족감을 주었으며, 특히, SasS 레벨에서 환경 변수를 따로 관리해주는 부분은 보안 부분에 있어서도 훨씬 간단하고 쉽게 접근할 수 있다는 장점을 느낄 수 있었다.

여기에는 언급하지 않았지만CircleCI를 통해ECS로 배포하는 과정은aws-ecs orb를 통해 훨씬 간단하게 진행할 수 있으나 Abstract에서 언급했다시피AWS ECS는 가격부분에서 다소 부담스러운게 사실이기 때문에 여기서는 언급하지 않았다.

본 포스팅에서는EC2를 사용하여 적은 비용으로 배포를 진행할 수 있는 나름의 접근 방법을 소개하였다.
물론,ECR 을 쓰지않고Gitlab 등을 통해 무료로 이미지를 관리할 수 있으나 그 부분은 차후 기회가되면 소개하도록 하겠다.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

🐈‍ Proud owner of thousands of dogs and cats memes. 🐈‍⬛
  • Location
    Seoul
  • Education
    Master of Science
  • Work
    Software Engineer at Kakao Enterprise
  • Joined

Trending onDEV CommunityHot

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp