반응형

애플리케이션을 개발하면서 원하는 시점에 자동으로 Docker image 를 build 하고 이를 docker hub 저장소에 push 할 수 있는 방법을 소개한다. 보통은 이를 CI 로 구축하는데 CI 시스템을 따로 구축하기에는 시간과 비용이 들고 이를 유지보수 하기에도 귀찮은 면이 있다. 만약 Github 을 사용하고 있다면 10분 만에 Github Action 으로 이를 쉽게 구현할 수 있다.

 

1. Dockerfile 만들기

가장 먼저 해야할 일은 도커 이미지 빌드를 위한 Dockerfile 을 만드는 것이다. golang 으로 개발하고 있다면 아래와 같이 만들 수 있을 것이다. 어느 정도 최적화를 고려했지만 완전히 최적화한 부분은 아니니 자신의 환경에 맞게 변경해야 한다. Dockerfile 의 위치는 $PROJECT_HOME 디렉토리 바로 아래이다.

FROM golang:1.16.3-stretch AS builder
LABEL AUTHOR Seungkyu Ahn (seungkyua@gmail.com)

RUN mkdir -p /build
WORKDIR /build

COPY . .
RUN go mod tidy && go mod vendor
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/server ./cmd/server

RUN mkdir -p /dist
WORKDIR /dist
RUN cp /build/bin/server ./server


FROM golang:alpine3.13

RUN mkdir -p /app
WORKDIR /app

COPY --chown=0:0 --from=builder /dist /app/
EXPOSE 9111

ENTRYPOINT ["/app/server"]
CMD ["-port", "9110"]

 

2. Github Action 파일 만들기

Github Action 은 규칙에 맞게 yaml 을 파일은 정해진 위치에 넣으면 Github 에서 알아서 실행시켜 준다. Action 을 실행시키는 시점은 소스가 github 에 push 되는 순간이며, 어느 branch 에 push 되었는지, Pull Request 를 했을 때 등의 실행 조건을 정의 할 수 있다.

$PROJECT_HOME 디렉토리에서 다음과 같이 디렉토리를 만든다.

$ mkdir -p .github/workflows

 

github action yaml 은 아래와 같다.

$ vi .github/workflows/deploy-image.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 Docker Buildx
      uses: docker/setup-buildx-action@v1

    - name: Login to DockerHub
      uses: docker/login-action@v1
      with:
        username: ${{ secrets.DOCKERHUB_USERNAME }}
        password: ${{ secrets.DOCKERHUB_TOKEN }}

    - name: Build and push
      id: docker_build
      uses: docker/build-push-action@v2
      with:
        push: true
        tags: seungkyua/tks-contract:latest

처음의 on 은 해당 action 이 수행될 조건을 의미한다. push - branches - main 은 main branch 에 push 가 일어나면 수행된다는 의미이다. 그렇기 때문에 요청된 PR 을 merge 하거나 main branch 에 직접 push 하면 해당 action 이 trigger 된다.

모든 branch 의 push 에 대해서 동작하게 하려면 '*' 로 하면 된다.

 

job 은 pipeline 을 구성하는 부분이다. steps 처음을 보면 "name: Checkout" 부분에 uses: actions/checkout@v2 로 되어 있는데 이는 github action 으로 정의된 모듈이다. 실체 소스는 https://github.com/actions/checkout 으로 접속하면 볼 수 있으며 해당 기능은 디폴트로 action 이 수행되는 github repository 의 소스 (현재 project 의 소스)를 내려받는 기능이다. 내려 받을 repository 를 바꿀려면 변경 가능하다. (action/checkout 에 접속하여 사용법을 확인하자)

 

"name: Set up Docker Buildx" 부분은 builder driver 나 platform 등을 세팅하는 부분이다. 역시 자세한 부분은 https://github.com/docker/setup-buildx-action 를 확인하자.

 

"name: Login to DockerHub" 는 docker hub 에 접근하기 위해서 id 와 password 를 지정하는 부분이다. 이를 위해서는 github repository 의 settings 로 들어가서 좌측 하단의 secrets >> Actions 에서 Action 용 secret 을 만들어야 한다.

 

 

 

 

 

 

 

docker hub 에 접속할 id 와 password 에 대한 secret 을 만들고 이를 github action 에서 ${{ secrets.DOCKERHUB_USERNAME }} 와 같이 변수로 가져다 쓰는 방식이다.

 

마지막으로 "name: Build and push" 부분은 docker image 를 build 하고 push 하는 부분이다. 이미지 name 과 tag 는 tags 로 지정했다. Dockerfile 의 위치 및 파일명은 file 키로 변경할 수 있다. 아무런 지정을 하지 않으면 해당 프로젝트 디렉토리에 있는 Dockerfile 을 찾는다. 자세한 내용은 https://github.com/docker/build-push-action 를 참조하자.

 

최종적으로 파일들은 아래와 같이 존재하게 된다.

 

 

 

보너스로 한가지 더.

 

main branch 로 merge 될 때 외에도 PR 을 할 때 docker image 를 build 하고 push 할 수 는 없을까? 이미지의 tag 는 latest 가 아니라 PR 을 요청한 source 의 branch 명으로 만들고 싶을 수 있다.

 

이럴 때는 새로운 파일을 만들고 github 의 내장 환경 변수를 사용하면 된다. 앞부분의 on 부분과 마지막 Build and push 부분의 tags 를 다음과 같이 수정하면 된다.

$ vi .github/workflows/deploy-image-with-branch.yml

name: Create and publish a package
on:
  pull_request:
    branches:
      - main
...
...
  - name: Build and push
      id: docker_build
      uses: docker/build-push-action@v2
      with:
        push: true
        tags: seungkyua/tks-contract:${{ github.head_ref }}
반응형
Posted by seungkyua@gmail.com
,