그동안 진행한 팀 프로젝트의 배포는 팀장님이 맡아서 하셨었다.
하지만 프로젝트를 더 잘 이해하고 흐름을 파악하기 위해서 개인적으로 진행해보게 되었다.
(참고로 배포가 끝난 뒤 www.woogy.shop에서도 프로젝트를 확인할 수 있게 되었다.)
프로젝트 최상단 경로(.github/workflows/deploy.yml)에 deploy.yml이라는 파일을 만들어주었다.
해당 파일에 들어갈 내용은 아래와 같다.
name: Build and Push Docker Image
on:
push:
branches:
- main
jobs:
build-and-push-image:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew clean build -x test
run: gradle build -x test
- 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: ECR 리포지토리 이름
IMAGE_TAG: ECR에 업로드 될 이미지 태그
run: |
docker buildx build --platform=linux/amd64 -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
- name: Get current time
uses: 1466587594/get-current-time@v2
id: current-time
with:
format: YYYYMMDD_HH-mm-ss
utcOffset: "+09:00"
- name: Generate deployment package
run: |
mkdir -p deploy/.platform/nginx/conf.d
cp Dockerrun.aws.json deploy/Dockerrun.aws.json
cp .platform/nginx/conf.d/proxy.conf deploy/.platform/nginx/conf.d/proxy.conf
cd deploy && zip -r deploy.zip .
- name: Beanstalk Deploy
uses: einaregilsson/beanstalk-deploy@v14
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: AWS EB Application 이름
environment_name: AWS EB 환경 이름
version_label: earth-docker-${{steps.current-time.outputs.formattedTime}}
region: ap-northeast-2
deployment_package: deploy/deploy.zip
wait_for_environment_recovery: 200
name: Build and Push Docker Image
on:
push:
branches:
- main
팀프로젝트 자체는 deploy 브랜치를 파서 거기에 배포했지만, 나는 연습용으로 쓸 repository를 하나 만들었기 때문에 브랜치는 main으로 해주었다.
jobs:
build-and-push-image:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
...
최소 한개 이상의 job을 정의해야 한다고 한다. 최신 버전의(latest) ubuntu 환경에서 실행되도록 해주고 actions/checkout@v2 부분은 Workflow에서 접근할 수 있도록 checkout 해주기 위한 부분이다.
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
자바 버전을 설정해 주는 부분이다. 1.8은 Java 8버전을 뜻한다. (11이후로는 그대로 11을 써준다고 한다.)
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build with Gradle
run: ./gradlew clean build -x test
- 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
보안을 위해 AWS ACCESS KEY와 AWS SECRET ACCESS KEY는 환경변수화 해서 Github Repository의 settings에 있는 Secrets에 따로 설정해준다.
- 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: ECR 리포지토리 이름
IMAGE_TAG: ECR에 업로드 될 이미지 태그
run: |
docker buildx build --platform=linux/amd64 -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
로컬 Docker 클라이언트에서 도커 이미지를 빌드해 ECR 리포지토리에 Push하는 흐름이다.
이때, 일반적인 경우라면 linux/amd64 환경이어서 docker buildx build -t 라고만 해주어도 괜찮다. 하지만 나는 맥북 M1을 사용하고 있기 때문에 --platform=linux/amd64 를 덧붙여 설정해 준다.
- name: Get current time
uses: 1466587594/get-current-time@v2
id: current-time
with:
format: YYYYMMDD_HH-mm-ss
utcOffset: "+09:00"
이 부분은 우리나라 시간으로 설정해 주기 위한 부분이다.
- name: Generate deployment package
run: |
mkdir -p deploy
cp Dockerrun.aws.json deploy/Dockerrun.aws.json
cd deploy && zip -r deploy.zip .
Dockerrun.aws.json을 zip파일로 만들어주는 부분이다.
아래와 같은 내용으로 구성해주면 된다. 해당 파일은 build.gradle이나 Dockerfile과 같은 경로에 위치하면 된다.
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "이미지 URI(AWS ECR에서 확인 가능)",
"Update": "true"
},
"Ports": [
{
"ContainerPort": 8080
}
]
}
- name: Beanstalk Deploy
uses: einaregilsson/beanstalk-deploy@v14
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: AWS EB Application 이름
environment_name: AWS EB 환경 이름
version_label: earth-docker-${{steps.current-time.outputs.formattedTime}}
region: ap-northeast-2
deployment_package: deploy/deploy.zip
wait_for_environment_recovery: 200
생성된 zip파일은 이 부분을 통해 AWS EB에 업로드, 배포된다.
AWS 설정은 ECR을 통해 Docker 파일이 Push되면 EB를 통해 EC2가 도커 이미지를 빌드하게 된다. 여기에 RDS 설정으로 DB도 연결한다. 이렇게 빌드된 이미지는 ELB를 통해 Route53로 호스팅된다. cloudfront, s3에는 프론트단을 구성하는 파일들을 올릴 수 있도록 구성해 붙여주는 구조다.
AWS는 수업 때 실습한 이후로 설정이 너무 복잡하고 아키텍처 흐름도 잘 이해되지 않아서 손을 놓고 있었다. 그런데 이번에 깃헙을 통한 무중단 배포와 연결해서 실습해 보니 프로젝트가 어떤 식으로 배포되는지 조금 더 잘 이해할 수 있었다.