파이문

github action 알아보기 (docker 예시 포함) 본문

TIL

github action 알아보기 (docker 예시 포함)

민Z 2022. 6. 17. 21:35

github action 이란?

github action 은 github 가 제공하는 CI/CD 플랫폼이라고 볼 수 있다. 보통 현업에서 빌드/배포를 진행할 때 별도의 서버를 두고 작업을 하곤 한다. (이 때 두는 서버는 물리 서버일 수도 있고 가상 서버일 수도 있다.)

 

github action 이 다른 CI/CD (예를 들면 젠킨스) 와 다른 강력한 장점은 바로 트리거 기능이라고 생각한다. (어디까지나 주관적인 의견입니다.) github 에 hook 을 걸어, push event 를 다른 툴에서 체킹을 하고 빌드가 자동으로 이루어지는데 github action 을 사용하면 yml 로 간편하게 이러한 작업을 할 수 있다.

 

또한 여러가지 action 들을 사용하여 CI/CD 작업 (이를 Workflow 라고 한다.) 시 필요한 기능(빌드 시 특정 인자 값을 넣는다던지, 작업 성공 시 메시지를 보낸다던지 하는 등의 서드파티 작업)들을 손쉽게 추가할 수 있다는 장점도 있다.  

 

단점은 github 를 사용해야만 쓸 수 있다는 점이 있고, 회사에서 github enterprise server 를 사용한다고 하더라도 devops 에서 추가해주지 않으면 사용할 수 없다.

 

github action 찍먹하기

github action 은, 정확히는 runner 라는 머신 위에서 여러 action 작업들이 하나의 workflow 형식으로 진행된다. 지금은 여기까지만 보고 일단 실습을 통해 github action 을 내 저장소에 설정해보도록 하자.

github action workflow yml 추가하기

github 저장소의 상단에 Actions 를 눌러 손쉽게 workflow yml 을 추가할 수 있다.

Simple workflow 를 클릭하면 가장 기본 설정만 들어있는 yml 템플릿이 나타나게 된다. 일단 아래 yml 변경 없이 commit 해보자

yml 만 추가한다고 바로 해당 repository 의 github action workflow 가 동작하지 않는다.

github action 은 runner 라고 불리는 머신이 필요하다. yml 에서는 runs-on: ubuntu-latest 라는 설정이 있는데 이는 ubuntu-latest 라는 이름을 가진 runner 에서 해당 workflow 를 실행하겠다는 의미이다.

github action runner 설정하기

runner 는 가상 머신이라고 보면 된다. 가상 머신이라고 해서 무언가를 설치하거나 설정해야할 것 같지만 github 는 self-hosted runner 라는 개념으로 로컬에서도 runner 를 만들 수 있다. (이름은 따로 정의할 수 있다.)

 

다시 github 저장소로 가서 Settings 를 클릭한 후 좌측의 Actions -> Runners 를 눌러본다. 그러면 아래 처럼 New self-hosted runner 버튼이 나오게 된다.

그럼 해당 버튼을 클릭하면 OS에 맞게 설정해야하는 내용을 github 에서 가이드해주고 있다.

참고로 내 로컬은 MacOS 이기 때문에 Mac 설정을 진행하였다. (여기선 로컬이지만, 당연하게도 개인 서버가 있다면 거기서도 진행해도 된다. 현업에서는 주로 도커로 구성된다.)

config.sh 를 실행하면 아래와 같이 설정하는 화면이 나올 것이다.

어떠한 값도 넣지 않고 엔터키만 쳤기 때문에 가장 기본 값으로 설정이 된다. configure 는 나중에도 변경할 수 있기 때문에 부담없이 진행해도 된다.

 

설정 중 This runner will have the following labels: 'self-hosted', 'macOS', 'X64' 이라는 걸 볼 수 있는데 이는 내 runner 의 label 을 붙여주는 작업이다. 여기서는 가장 기본 값이 붙었는데, 이 값을 어디서 사용하냐면 runs-on: self-hosted 으로 workflow yml 파일에서 사용하는 것이다.

 

내 workflow 에 작성되어있는 job 을 어느 runner 에서 실행 시킬 것인지 label 로 설정하는 것이다.

 

다시 github 저장소로 가보면 동일한 label 이름들로 runner 가 설정되어있는 걸 볼 수 있다.

runner 상태는 총 3가지로 Offline, Active, Idle 상태를 가지며 현재는 runner 를 실행시키지 않았기 때문에 (run.sh 를 실행하지 않았기 때문에) Offline 으로 보이게 된다.

 

runner 가 띄워져있지만 작업을 하지 않으면 Idle 로, Job 이 실행되고 있으면 Active 로 보여지게 된다.

github action workflow yml 수정하기

기본으로 들어가 있던 yml 은 (여기서는 blank.yml 이라는 이름을 가지고 있다.) runs-on 이 ubuntu-latest 이기 때문에 이 값을 self-hosted 로 변경하도록 한다. (github 에서 직접 파일을 수정해도 된다.)

만약 작업하고 있는 브랜치가 master 라면, 파일 변경 후 저장 (commit) 하면 바로 github actions runner 로 트리거 되서 runner 가 돌아가게 될 것이다. master 브랜치가 아니라면 trigger 룰을 수정해야 한다. 위의 예제와 동일하다면 push.branches 값을 추가하거나 수정하면 된다.

수정과 즉시 runner 가 Active 상태가 되고 작업이 완료 되면 Actions 탭에서 이를 확인할 수 있다.

여기까지 했으면 runner 는 이제 다 아는 거나 다름 없다. 개인 프로젝트로 할 경우 이 정도면 충분하고, 엔터프라이즈라면 아마 Devops 팀에서 runner 를 관리해줄 것이다. (이 때는 보통 도커/쿠버네티스를 많이 사용하며, 하나의 작업이 끝나면 runner 는 clean up 된다.)

 

위에서 build 아래의 각 내용 (Set up job, Run actions/checkout@v3... 등등) 이 github action 의 step 이라는 개념이다.

github action 사용하기

runner 설정도 끝났고 심플한 yml 도 추가하였으니 이제 실제로 빌드 하는 건 어떻게 하는지 살펴보도록 한다. 빌드는 자바, gradle, docker image 기준으로 한다.

 

머신에서 자바를 gradle로 빌드할 때 아래와 같은 명령어를 주로 사용한다.

$ ./gradlew build

이 명령어를 runner 에 그대로 넣으면 된다.

github action job

github action 은 job 을 기준으로 실행되고 각 job 은 step 여러개로 이루어진다. (step 은 하나일 수도 있다.)

job 은 순서가 구분 없이 병렬로 실행되지만, step 은 명시되어 있는 순서대로 실행된다.

github action gradle build 예시

아래 예시는 java 17 로 gradle build 를 하는 예시이다.

 

참고로 actions/checkout 은 무조건 처음에 명시해야 한다. 이 액션은 git pull 과 같은 의미로 프로젝트를 가져오겠다는 뜻을 갖고 있다.

 

버젼의 경우 적당히, 환경에 맞게, 하지만 가능하면 최신버젼으로 사용하면 된다. (action 이름이 actions/checkout 이기 때문에 동일한 이름의 저장소가 있으므로 직접 가서 어떻게 액션을 만들었는지, 최신 버젼은 몇인지 볼 수 있다. https://github.com/actions/checkout)

name: CI test

on:
  push:
    branches:
      - 'master'

  workflow_dispatch:


jobs:
  build:
    runs-on: [ self-hosted ]
    steps:
      - uses: actions/checkout@v2
      - name: Set up java 17
        uses: actions/setup-java@v2
        with:
          java-version: '17'
          distribution: 'temurin'
      - name: Build project with gradle
      	# run 할 명령어를 입력한다.
        run: ./gradlew -x test build

jobs 뒤에 붙는 build 는 예약어가 아니기 때문에 원하는 값을 사용해도 된다.

 

앞에서 설명했지만 jobs 는 순서 보장이 안되기 때문에 아래 처럼 작성할 경우 job이 병렬적으로 실행된다. 아래 예시로는 build 라는 job 과 docker 라는 job 이 동시에 실행될 것이다. (동시는 아니더라도 순서 보장이 안됨)

jobs:
  build:
    runs-on: [ self-hosted ]
    steps:
      - uses: actions/checkout@v3

      - name: Run a one-line script
        run: echo Hello, world!

      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project.
  docker:
    runs-on: [ self-hosted ]
    steps:
      - name: Login a docker
        run: echo Hello, docker!

그래서 job 끼리 순서를 명시하고 싶으면 needs 옵션을 사용해야 한다. 

순서 보장 없이 실행 됨

needs 옵션을 사용하여서 build 후 docker job 이 실행되도록 설정해보자

  docker:
    runs-on: [ self-hosted ]
    # 아래 처럼 job 이름을 명시한다. 리스트 형식도 가능하다.
    needs: build
    steps:
      - name: Login a docker
        run: echo Hello, docker!

needs 를 사용하면 build job 이 끝나기 전까지 docker job 이 실행되지 않는다.

job 간에 의존성을 갖는 경우엔 이 처럼 사용하면 된다.

github action 예시

사실 여기까지만 보면 이제 github action 은 다 안다고 보면 된다. 나머지는 본인한테 필요한 설정들을 한다던가, 유용한 action 들을 찾아서 프로젝트에 맞게 사용한다던가 등등을 하는 과정이다.

 

예를 들면 위의 예시에는 Docker 라는 job 이 있지만 아무것도 하지 않는데, Docker 가 제공하는 action 들 (build, push, meta 등) 을 사용하여 내가 만든 jar 를 Docker image 로 다시 빌드한다던지 하는 등의 작업을 진행할 수 있다.

 

이런 Action 들은 직접 만들수도 있고 이미 있는 걸 가져다가 쓸 수도 있는데 github 는 Marketplace 라는 곳에서 사람들이 올린 action 들을 볼 수 있다. (오픈 소스를 가져다가 쓴다고 보면 되고 실제로도 오픈 소스이다.)

 

https://github.com/marketplace?type=actions

github action 으로 도커 빌드하기

docker 를 사용할 때 필요한 docker registry 로그인, docker build, docker push 등의 작업을 Docker github 가 제공하는 Action 들로 진행해보도록 한다. 

 

(굳이 아래 내용을 따라야할 필요는 없고, 본인의 action 을 쓴다던가 다른 사람이 만든 action 을 써도 된다.)

 

https://github.com/search?q=topic%3Agithub-actions+org%3Adocker+fork%3Atrue

Docker registry 로그인

env 의 경우엔 정의한 변수들을 사용하는 부분이고(파일에 추가해도 상관 없는 내용), secrets 같은 경우엔 보안 상 보여지면 안되는 비밀 값으로 github 에서 설정해야 한다. 키는 DOCKER_USER, DOCKER_PASSWORD 가 되고 값은 직접 입력하면 되는데

      - name: Login to d2hub
        uses: docker/login-action@v1
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASSWORD }}

github 에서 아래 화면에서 입력하면 된다. 우측 상단의 New repository secret 눌러서 설정하면 된다.

docker build, push 하기

registry 로그인 했으니까 이제 도커 이미지를 build하고 push 하도록 한다. 

 

Docker meta 는 도커 이미지를 빌드 할 때 어떤 tag 를 사용할 것인지를 정하는 것으로 Docker meta action 말고 다른 (태그를 추출하는) 액션을 사용해도 된다.

 

여기서 metadata-action 의 경우

  • branch 로 trigger 되면 raw 값에 따라 해당 브랜치 명이 그대로 들어가게 된다.
    • 예를 들면 docker-sample 라는 이름의 브랜치가 push 될 경우 / 그리고 push trigger 가 있을 경우
    • <docker image>:docker-sample 이라는 이름으로 태그가 이미지에 붙게 된다.
  • major, minor 의 경우 버젼으로 release(tag 생성) 로 trigger 가 발생되면 해당 버젼이 들어가게 된다.
    • v0.1.2 로 태그 (여기서는 git tag) 가 생성되면 v0, v0.1 의 태그 2개가 생성된다.

이 밖에도 latest 라는 태그를 붙일 수 있고, enable 이라는 키에 true, false 값을 넣어서 특정 태그를 무조건 붙이게 할 수도 있다. 더 자세한 태그 생성 방식은 github 에서 확인하도록 하자 https://github.com/docker/metadata-action

      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: ${{ env.IMAGE_NAME }}
          tags: |
            type=ref,event=branch
            type=semver,pattern={{raw}}
            type=semver,pattern=v{{major}}
            type=semver,pattern=v{{major}}.{{minor}}

tag 생성을 했으면 해당 tag 를 도커 이미지에 붙이고 push 하도록 한다. (정확히는 build and push)

 

docker build 할 때 사용하는 옵션은 with 라는 값에 넣어서 쓸 수 있다. 

참고로 여기서 tags 에 들어가는 값은 위에 작성하였던 metadata-action 의 결과 값으로, 위의 step 에서 id 를 meta 라고 작성했기 때문에 결과를 그대로 가져다가 쓸 수 있는 것이다.

 

meta 에서 생성된 tag 개수 만큼 (종류 만큼) registry 에 push 된다.

      - name: Build and push
        uses: docker/build-push-action@v3
        with:
          context: .
          file: /path/to/Dockerfile
          no-cache: true
          push: true
          tags: ${{ steps.meta.outputs.tags }}

전체로 보자면 아래 처럼 사용할 수 있다.

name: CI test

on:
  push:
    branches:
      - 'master'
    tags:
      - 'v*'

  workflow_dispatch:

env:
  REGISTRY: REGISTRY_SAMPLE
  IMAGE_NAME: IMAGE_NAME_SAMPLE

jobs:
  docker:
    runs-on: self-hosted
    steps:
      - name: Login to d2hub
        uses: docker/login-action@v2
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_TOKEN }}
      - name: Docker meta
        id: meta
        uses: docker/metadata-action@v4
        with:
          images: ${{ env.IMAGE_NAME }}
          flavor: |
            latest=auto
            prefix=
            suffix=
          tags: |
            type=ref,event=branch
            type=semver,pattern={{raw}}
            type=semver,pattern=v{{major}}
            type=semver,pattern=v{{major}}.{{minor}}
      - name: Build and push
        uses: docker/build-push-action@v3
        with:
          context: .
          file: /path/to/Dockerfile
          push: true
          tags: ${{ steps.meta.outputs.tags }}

진짜 이제 여기까지만 보면 github action 으로 할 수 있는 기본은 다 했다고 볼 수 있다. 

기타 등등

github action workflow badge 로 노출하기

workflow 결과 상태를 badge 로도 보여줄 수 있다. workflow 로 가서 우측의 Create status badge 를 눌러준다.

그리고 나오는 link 를 복사해서 내 프로젝트의 markdown 으로 붙여주면 된다. 보통은 README.md 에 복붙할 것이다.

 

이제 진짜 github action 은 기본은 다 안다고 볼 수 있다.

 

나머지 목표는 이제 github action 이 제공하는 다양한 context 를 사용하여 좀 더 생산성 높은 CI/CD 환경을 구축하는 것이다. 무슨 말인가 하면 github action 은 커밋 메시지, 커밋 시각, job 상태 등등 다양한 값들을 변수로 제공하고 있기 때문에 이 값을 사용해서 상태 알람을 보낸다던지, 아님 cron job 비스무리 하게 스케쥴러 작업을 돌린다던지 등등을 할 수 있다는 것이다.

 

더 나아가서는 나만의 github custom action 을 만들 수 있는데, github action 을 직접 만들려면 자바스크립트(또는 타입스크립트) 아니면 도커 컨테이너로 만들어야 한다.

 

여기서부터는 응용편이라서 다음 게시글에 작성 도전을...!

참고

'TIL' 카테고리의 다른 글

[HBase] FilterList 에서 OR 조건 사용하기  (0) 2021.02.22
도커 컨테이너 로그 삭제  (0) 2021.02.18
gradle-ssh-plugin 사용하기  (0) 2021.02.18
gradle proxy 설정  (0) 2021.02.17
git rm 한 file 복구(reset, restore) 하기  (0) 2021.02.16
Comments