사내에서 Github Action을 사용하여 프론트엔드 프로젝트의 배포를 자동화한 과정을 공유하려 한다.
dev
도메인
1. 로컬 환경에서 ECR에 푸쉬 후 ECS 수동 배포
2. Github Action 워크플로우 구문(YML)을 작성하여 ECR - ECS 배포 자동화
dev
도메인에서의 배포 자동화를 성공적으로 실행했다면,prod
도메인에 대한 워크플로우 구문을 작성하고prod
도메인에서의 배포를 진행하려 한다.
develop 브랜치에 푸쉬가 되면 Github action의 워크플로우가 실행된다.
ECR - 프라이빗 레지스트리 - 리포지토리에서 dev 환경에서 사용할 리포지토리를 생성한다.
생성한 리포지토리를 체크하고 푸쉬 명령 보기
를 클릭하여 해당 리포지토리에 푸쉬하는 명령어를 사용하여 푸쉬한다.
먼저, AWS-CLI가 설치되어야 하고, AWS CLI를 사용해 인증을 진행한다. 이후 도커 이미지를 빌드 한 후 빌드가 완료되면 이미지에 태그를 지정하여 ECR에 푸쉬한다.
정상적으로 푸쉬가 되었다면 위 사진과 같이 확인할 수 있다. 이미지 태그는 latest를 사용하여 관리하는게 좋다. latest로 지정하게 되면 새롭게 도커 이미지를 푸쉬할 때 마다 제일 최신 이미지가 latest로 변경되어 관리에 용이하다. 추후 tdf
(task-definition에서 이 latest를 기준으로 ECS에 배포할 것이다)
tdf
는 ECS를 실행시키는데 어떻게 실행시킬지 정의 하는 json 파일이다.
해당 파일에는 어떤 컨테이너의 이름으로 어떤 이미지를 사용할것인지를 정의하고 포트 설정, 환경변수 설정 등을 설정할 수 있다.
새 개정 생성을 눌러 마법사를 통해 JSON 파일을 자동생성할 수도 있고, 곧바로 JSON으로 작성할 수도 있다.
만약, 곧바로 JSON으로 작성한다면,
taskDefinitionArn
,revision
,requireAttributes
,compatibilities
와 같이 자동으로 생성되는Attributes
는 작성 안해도 된다. 작성한다면 github action에서 warning을 뱉을 것이지만, 큰 문제는 없다.
테스크 정의 패밀리는 고유한 테스크 패밀리 이름을 지정해야 하고, 개정은 버전이라고 생각하면 된다. 처음 테스크를 만들게 되면 개정은 1이 되고, 그 이후 테스크가 갱신 된다면 개정은 2, 3.. 이렇게 올라갈 것이다. 개정을 지정하여 ECS에 배포할 수 있다.
그 외 인프라 요구사항은 상황에 맞게 선택하면 될 것이다.
생성할 컨테이너 이름을 지정하고 이 컨테이너에 띄울 이미지를 입력하면 된다. 아까 ECR에 만들어둔 이미지 URI(xxxxxx.dkr.ecr.ap-northeast-2.amazonaws.com/dev:latest)를 넣으면 된다.
docker를 실행할 때 환경변수를 설정할 수 있다. ECS 에서는 docker run 명령어를 직접 입력할 수 없기 때문에 여기서 환경변수를 설정할 수도 있다. 환경 변수가 몇개 되지 않는다면 단순히 환경 변수 추가 버튼을 눌러서 추가하면 되고, 만약 환경변수가 많아서 파일로 관리하고 싶다면 환경 파일 추가 버튼을 누르면 된다.
환경 파일 추가를 통해 s3 버킷에서 환경변수 파일을 가져온다면, 위에서 설정한
ECS 테스크 실행 IAM 역할
에 S3 객체에 대한 액세스 권한을 부여해야 한다.
ELB를 생성하기 전에 대상그룹을 정의한다. 대상은 등록하지 않아도 된다. 나중에 ECS를 실행할 때 대상이 동적으로 등록된다.
생성한 대상그룹을 가지고 ELB를 만들고 리스너 및 규칙을 저으이
Route 53에서 사용할 도메인을 선택하고 서브 도메인(dev)을 생성한다.
클러스터를 만든 후 ECS를 생성한다.
서비스를 선택하고, 만들어두었던 테스크 정의를 선택하여 배포를 진행한다.
프로젝트 루트 경로에서 .github/workflows/타이틀.yml에 깃허브 액션을 통해 실행할 워크플로우를 작성한다.
# 워크플로우 이름
name: Deploy to xxx.com
# develop 브랜치에 푸쉬 되었을 때 워크플로우가 실행됩니다.
on:
push:
branches:
- develop # 해당 브랜치에 머지되면 이 워크플로우가 트리거 된다.
jobs:
deploy:
runs-on: ubuntu-latest
# 변수 설정
env:
AWS_REGION: ap-northeast-2
ECR_REPOSITORY: ECR 레포지토리명
ECS_SERVICE: ECS 서비스명
ECS_CLUSTER: ECS 클러스터명
ECS_TASK_DEFINITION: ./develop-tdf.json # 실행할 TDF, 본인은 프로젝트 안에 tdf를 작성해두어서 경로를 이렇게 설정
CONTAINER_NAME: 컨테이너 이름
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v3
# AWS Config
- 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: ${{ env.AWS_REGION }}
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
# 프로젝트에 주입할 환경변수를 S3 버킷에서 가져와서 프로젝트에 주입
# 가져와서 이름을 변경함
- name: Download Environment File from S3 bucket
run: |
aws s3 cp s3://경로/프로덕트명-production.env .
mv ./프로덕트명-production.env ./.env.production
- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
run: |
# Build a docker container and
# push it to ECR so that it can
# be deployed to ECS.
# 도커 빌드 명령어
docker build --platform linux/amd64 -t ecr 레포지토리 위치/ecr 레포지토리명:latest -f Dockerfile.production .
docker push ecr 레포지토리 위치/ecr 레포지토리명:latest
echo "레포지토리 위치/레포지토리명:latest" >> $GITHUB_OUTPUT
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ${{ env.ECS_TASK_DEFINITION }}
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ steps.build-image.outputs.image }}
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ${{ steps.task-def.outputs.task-definition }}
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true
develop 브랜치에 머지되면,
1. 프로젝트에 주입할 환경변수를 S3 버킷에서 가져와서 프로젝트에 루트폴더에 위치시킨다.
2. 도커 빌드를 진행하고, 빌드된 이미지는 ECR에 latest태그를 붙힌 채로 푸쉬된다.
3. 작성한 tdf에 의해 ECS가 실행되고 배포된다.
develop 브랜치에 머지되면,
1. 프로젝트에 주입할 환경변수를 S3 버킷에서 가져와서 프로젝트에 루트폴더에 위치시킨다.
2. 도커 빌드를 진행하고, 빌드된 이미지는 ECR에 latest태그를 붙힌 채로 푸쉬된다.
3. 작성한 tdf에 의해 ECS가 실행되고 배포된다.
// 변수 설정
MANIFEST=$(aws ecr batch-get-image --repository-name ${ecr 레포지토리 이름} --image-ids imageDigest=${변경 당하는 이미지의 다이제스트 (sha256:...)} --query 'images[0].imageManifest' --output text)
aws ecr put-image --repository-name ${ecr 레포지 토리 이름} --image-tag latest --image-manifest "$MANIFEST"
이렇게 코드를 입력하면 이미지의 latest 태그를 변경한다. latest 태그를 돌리고 싶은 이미지로 지정하고 ECS에서 강제 수동 배포하면 원하는 이미지로 다시 배포할 수 있다.
해당 깃허브 레포지토리에서 Action 탭을 클릭하면 진행되는 워크플로우를 실시간으로 확인할 수 있다. 만약 문제가 생기면 로그도 이쪽에서 나오니 확인하면 된다.