21.12.29 TIL45 자동 배포 (Github Actions + Docker + AWS EB)

서태욱·2021년 12월 29일
1

🔎 오늘 배운 것

그동안 진행한 팀 프로젝트의 배포는 팀장님이 맡아서 하셨었다.
하지만 프로젝트를 더 잘 이해하고 흐름을 파악하기 위해서 개인적으로 진행해보게 되었다.

(참고로 배포가 끝난 뒤 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
          

Part 1

name: Build and Push Docker Image
on:
  push:
    branches:
      - main

팀프로젝트 자체는 deploy 브랜치를 파서 거기에 배포했지만, 나는 연습용으로 쓸 repository를 하나 만들었기 때문에 브랜치는 main으로 해주었다.

Part 2

jobs:
  build-and-push-image:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      ... 

최소 한개 이상의 job을 정의해야 한다고 한다. 최신 버전의(latest) ubuntu 환경에서 실행되도록 해주고 actions/checkout@v2 부분은 Workflow에서 접근할 수 있도록 checkout 해주기 위한 부분이다.

Part 3

- name: Set up JDK 1.8
  uses: actions/setup-java@v1
  with:
    java-version: 1.8

자바 버전을 설정해 주는 부분이다. 1.8은 Java 8버전을 뜻한다. (11이후로는 그대로 11을 써준다고 한다.)

Part 4

- name: Grant execute permission for gradlew
  run: chmod +x gradlew

  - name: Build with Gradle
  run: ./gradlew clean build -x test

Part 5

- 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에 따로 설정해준다.

Part 6

- 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 를 덧붙여 설정해 준다.

Part 7

- name: Get current time
  uses: 1466587594/get-current-time@v2
  id: current-time
  with:
    format: YYYYMMDD_HH-mm-ss
    utcOffset: "+09:00"

이 부분은 우리나라 시간으로 설정해 주기 위한 부분이다.

Part 8

- 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
    }
  ]
}

Part 9

- 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는 수업 때 실습한 이후로 설정이 너무 복잡하고 아키텍처 흐름도 잘 이해되지 않아서 손을 놓고 있었다. 그런데 이번에 깃헙을 통한 무중단 배포와 연결해서 실습해 보니 프로젝트가 어떤 식으로 배포되는지 조금 더 잘 이해할 수 있었다.

✔️ 참고

profile
re:START

0개의 댓글