Github Actions으로 AWS EC2에 CI/CD 구축하기

참고, 참고


한이음 공모전에서 진행하는 trading app을 개발하기 전에 자동화를 구축하려고 한다.

준비물

  1. Dockerfile
  2. Github
  3. AWS EC2(ubuntu 18.04)

1. Github Access Token 발급 && Secret 등록

Github Access Token은 Packages의 권한을 가진다.
Github Container Registry로 docker image를 배포하고 EC2(runner) 실행 할 때 docker login에 사용된다.

Github 계정의 Settings -> Developer settings -> Personal access tokens에서 새로운 token을 만들어준다.

위 사진처럼 4개의 scopes를 선택해주고 생성한 뒤에 생성된 토큰을 복사해 Repository의 secret에 등록해서 사용한다.(실제 계정 토큰이므로 노출되어서는 안됨)

Repository의 Settings -> Actions에서 New repository secret을 눌러 만들어준다.


참고


요기서 Feature preview를 눌러서 Enable을 눌러줘야 build and push가 가능하다고 한다.

2. Workflow 작성

Repository의 Actions 탭에서 set up a workflow yourself 버튼을 눌러 yml 파일을 작성한다.

name: CI/CD Docker

on:
  push:
    branches: [ master ]

env:
  DOCKER_IMAGE: ghcr.io/${{ github.actor }}/trading
  VERSION: ${{ github.sha }}
  NAME: go_cicd

jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
      - name: Check out source code
        uses: actions/checkout@v2
      - name: Set up docker buildx
        id: buildx
        uses: docker/setup-buildx-action@v1
      - name: Cache docker layers
        uses: actions/cache@v2
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ env.VERSION }} # runner 설정에서 읽어들일거에요.
          restore-keys: |
            ${{ runner.os }}-buildx-
      - name: Login to ghcr
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GHCR_TOKEN }}
      - name: Build and push
        id: docker_build
        uses: docker/build-push-action@v2
        with:
          builder: ${{ steps.buildx.outputs.name }}
          push: true
          tags: ${{ env.DOCKER_IMAGE }}:latest

  deploy:
    needs: build
    name: Deploy
    runs-on: [ self-hosted, label-go ]
    steps:
      - name: Login to ghcr
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GHCR_TOKEN }}
      - name: Docker run
        run: |
          docker stop ${{ env.NAME }} && docker rm ${{ env.NAME }} && docker rmi ${{ env.DOCKER_IMAGE }}:latest
          docker run -d -p 8080:5000 --name go_cicd --restart always ${{ env.DOCKER_IMAGE }}:latest

yml 파일 설명 참고

on:
  push:
    branches: [ master ]
    
env:
  DOCKER_IMAGE: ghcr.io/${{ github.actor }}/trading
  VERSION: ${{ github.sha }}
  NAME: go_cicd
  • 여러 브랜치에서 개발 후 master 브랜치에 push or 병합 될 때만 실행되도록 설정하고 Docker image 이름과 version, name을 미리 환경변수로 지정한다.
jobs:
  build:
    name: Build
    runs-on: ubuntu-latest
    steps:
  • Workflow는 다양한 job으로 구성되고 위 yml은 build와 deploy라는 job을 생성한다. build는 5개의 step이 존재하고 deploy는 2개의 step이 존재한다.
  • name은 각 단계에 실행할 것을 의미한다.
  • runs-on은 어떤 OS에서 실행될지를 지정한다.
      - name: Check out source code
        uses: actions/checkout@v2
  • build의 step 첫 번째는 현재 상태의 소스콬드를 가상의 컨테이너 안으로 checkout해주는 역할
      - name: Set up docker buildx
        id: buildx
        uses: docker/setup-buildx-action@v1
  • build의 step 두 번째는 가상의 컨테이너 안에 docker가 돌아갈 수 있는 환경을 설치하는 역할
      - name: Login to ghcr
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GHCR_TOKEN }}
  • build의 step 세 번째는 2번에서 생성한 토큰을 이용해 GHCR에 로그인하는 역할
      - name: Build and push
        id: docker_build
        uses: docker/build-push-action@v2
        with:
          builder: ${{ steps.buildx.outputs.name }}
          push: true
          tags: ${{ env.DOCKER_IMAGE }}:latest
  • build의 step 네 번째는 해당 GHCR로 Docker image를 만들고 push하는 역할
  deploy:
    needs: build
    name: Deploy
    runs-on: [ self-hosted, label-go ]
    steps:
      - name: Login to ghcr
        uses: docker/login-action@v1
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GHCR_TOKEN }}
      - name: Docker run
        run: |
          docker stop ${{ env.NAME }} && docker rm ${{ env.NAME }} && docker rmi ${{ env.DOCKER_IMAGE }}:latest
          docker run -d -p 8080:5000 --name go_cicd --restart always ${{ env.DOCKER_IMAGE }}:latest
  • Deploy는 GHCR에 로그인 후 저장되어 있는 Docker image를 이용해 컨테이너를 실행시키는 역할
  • Docker run은 실행 중인 도커 컨테이너를 중지하고 이전 버전인 컨테이너와 이미지를 삭제 후 새로운 이미지로 컨테이너를 run하는 방식이다.
  • runs-on 중 self-hosted는 필수로 써야한다.(이 값을 설정해야 서버에 등록한 runner가 실행된다.)
  • 이 부분에서 어느 Runner(EC2)로 실행할지 지정해줘야 한다.

3. Runner 설정

Repository의 Settings -> Actions -> Runners로 가서 Add Runner를 누르고
자신의 서버에 맞은 OS와 아키텍처를 선택하고 사진과 같이 configure까지 코드를 EC2 서버에 접속해 입력하여 runner를 달아줘야 한다.

Configure의 첫 번째 코드까지를 입력하게 되면
이 두 개를 입력해야하는 상황이 발생하는데

첫 번째에 대한 답은 복수개의 runner를 등록할 때 github 상에서 구분할 수 있는 runner의 이름을 지정하면 되고(나는 trading으로 지었다.)
두 번째에 대한 답은 실행되는 runner를 구분하기 위한 것이므로 yml 파일의 Deploy에서 runs-on에 설정해주었던 label-go를 입력하면 된다.
-> 둘 다 임의로 변경 가능

이렇게 설정한 이름은 Repository의 Settings -> Actions에서 확인할 수 있다.

마지막으로 ./run.sh를 실행하면
다음과 같은 결과를 볼 수 있다.

./run.sh은 다른 작업을 하지 못하므로 nohup ./run.sh &를 이용해 백그라운드로 runner를 실행시킨다.

이제 서버에서는 Job을 Listening하고 지정한 branch에 push가 되면 자동으로 EC2에 이미지가 실행되고 자동으로 배포된다.


나는 Repository가 Organization에 있어서 buildx call failed라는 오류를 만났는데 문서를 참고하여 오류를 해결했다.
Organization의 Settings에서 Packages의 Enable improved container support를 체크해주면 된다.

좋은 웹페이지 즐겨찾기