이미 생성한 레포가 있기에 코드를 생성하는 과정은 생략 하겠습니다.
- 로컬 PC에서 개발을 한 후 Github에 Push를 합니다.
- Github Repository 특정 branch에 push가 되면 Github Action이 동작을 시작합니다.
- Github Actions가 Github Container Registry에 소스를 받은 후 Docker 이미지로 빌드를 합니다.
- 빌드된 이미지를 EC2에 등록된 Runner가 복사합니다.
- 기존 이미지를 삭제하고 새로운 이미지로 실행을 합니다.
추후 도커 이미지 생성 시 깃헙 저장소의 이름과 동일 하게 맞춰줘야 하기에 해당 레포의 이름을 잘 기억하자.
Docker 이미지를 만들기 위해 프로젝트 루트에 Dockerfile을 아래와 같이 생성합니다.
# 베이스 이미지
FROM node:16-alpine
WORKDIR /src
# 프로젝트 파일 복사
COPY package*.json ./
COPY .env ./
RUN npm install
COPY . .
CMD ["node", "app.js"]
EXPOSE 3001
FROM node:16-alpine : node:16-alpine 버전의 이미지를 받아서 docker image를 생성합니다.
WORKDIR /src : 작업 디렉토리를 /src로 설정하고 있으며, 이후의 모든 파일 복사, 의존성 설치, 애플리케이션 실행은 /src 디렉토리를 기준으로 수행
COPY 소스코드의 이미지 생성을 위한 필요한 파일을 복사하고 의존성을 설치합니다.
CMD ["node", "app.js"] : node app.js 명령을 실행합니다.
EXPOSE 3001 포트를 외부로 노출합니다.
docker build --tag mycafe:latest .
ref : https://codegear.tistory.com/84
name: CI/CD with Docker !!
# 트리거를 수행할 브랜치를 지정합니다.
on:
push:
branches: [main]
# 환경설정
env:
DOCKER_IMAGE: ghcr.io/${{ github.actor }}/mycafe
VERSION: ${{ github.sha }}
NAME: go_cicd
jobs:
# 빌드 Job
build:
name: Build
runs-on: ubuntu-latest
permissions:
packages: write
steps:
# github repository에서 checkout
- uses: actions/checkout@v2
# docker build 수행
- 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 }}
restore-keys: |
${{ runner.os }}-buildx-
# GitHub 컨테이너 레지스트리에 로그인 후 빌드 & 푸시
- name: Login to ghcr
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.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
context: ./src
platforms: linux/arm64
# 배포 Job
deploy:
needs: build # build 후에 실행되도록 정의
name: Deploy
runs-on: [self-hosted, label-go] # AWS ./configure에서 사용할 label명
steps:
- name: Login to ghcr
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
# 3001 -> 80 포트로 수행하도록 지정
- name: Docker run
run: |
docker stop ${{ env.NAME }} && docker rm ${{ env.NAME }} && docker rmi ${{ env.DOCKER_IMAGE }}:latest
docker run -d -p 80:3001 --name go_cicd --restart always ${{ env.DOCKER_IMAGE }}:latest
on:
push:
branches: [ master ]
env:
DOCKER_IMAGE: ghcr.io/${{ github.actor }}/trading
VERSION: ${{ github.sha }}
NAME: go_cicd
여러 브랜치에서 개발 후 master 브랜치에 push or merge 될 때 실행되도록 설정하고 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 세 번째는 위에서 생성한 토큰을 이용해 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하는 역할
# 배포 Job
deploy:
needs: build # build 후에 실행되도록 정의
name: Deploy
runs-on: [self-hosted, label-go] # AWS ./configure에서 사용할 label명
steps:
- name: Login to ghcr
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
# 3001 -> 80 포트로 수행하도록 지정
- name: Docker run
run: |
docker stop ${{ env.NAME }} && docker rm ${{ env.NAME }} && docker rmi ${{ env.DOCKER_IMAGE }}:latest
docker run -d -p 80:3001 --name go_cicd --restart always ${{ env.DOCKER_IMAGE }}:latest
Deploy는 GHCR에 로그인 후 저장되어 있는 Docker image를 이용해 컨테이너를 실행시키는 역할
Docker run은 실행 중인 도커 컨테이너를 중지하고 이전 버전인 컨테이너와 이미지를 삭제 후 새로운 이미지로 컨테이너를 run하는 방식이다.
runs-on 중 self-hosted는 필수로 써야한다.(이 값을 설정해야 서버에 등록한 runner가 실행된다.)
이 부분에서 어느 Runner(EC2)로 실행할지 지정해줘야 한다.
./config.sh 문을 실행하면 다음과 같이 입력을 요청합니다.
Enter the name of the runner group to add this runner to : 엔터
Enter the name of runner : 엔터
Enter any additional label : label-go (워크플로우 yml에 작성했던 라벨명)
Enter name of work folder : 엔터
nohup ./run.sh &
./run.sh는 다음과 같이 백그라운드로 실행을 합니다.
- tail -f nohup.out 명령을 실행하면 ec2상의 빌드 로그를 확인할 수 있습니다.
소스 수정 후 push 하기
ref
https://codegear.tistory.com/84
https://velog.io/@soosungp33/CICD-%EA%B5%AC%EC%B6%95%EA%B8%B0