DEV/Infrastructure

[NCP, Docker, Github Actions] 를 활용한 CI / CD 구축

Bi3a 2024. 1. 9. 02:32

목차
반응형

이전 포스팅에서 이어집니다.

 

[NCP, 도커] 서버 생성부터 배포까지 (4 / 4)

이전 포스팅에서 이어집니다. [NCP, 도커] 서버 생성부터 배포까지 (야매판, 3 / 4) 이전 포스팅에서 이어집니다. [NCP, 도커] 서버 생성부터 배포까지 (야매판, 2 / 4) 이전 포스팅에서 이어집니다. [NCP

doinitright.tistory.com

 

Github Actions를 통한 스마트한 배포
Github Action을 통해 스마트한 배포를 진행해봅시다.


Github Actions

Github에서 제공하는 CI / CD 통합 도구이다.
Github Actions은 대다수의 개발자가 프로젝트를 빌딩하고 형상관리를 하는 데 사용하는
Github의 플랫폼 내에서 모든 CI / CD 과정을 해결할 수 있다는 장점이 있다.

 

Github Actions에서의 CI / CD

  • CI (지속적 통합) : 여러 개발자들이 코드를 지속적으로 통합해 빌드하고 테스트하는 프로세스이다.
    • 주로 Github 등의 형상 관리 환경에서 이뤄지는 작업으로, 코드의 일관성과 품질을 검증할 수 있다.
  • CD (지속적 배포) : CI 과정을 통해 지속적으로 통합된 코드를 자동으로 배포하는 프로세스이다.
    • 수동으로 이뤄지는 배포를 자동화하여 빠르고 안정적인 배포 작업이 가능해진다.
  • 즉, Github Actions은 Github에서의 코드 통합, Github Actions을 통한 빌드 및 배포로 CI/ CD를 가능케 한다.

 

Github Actions 시작하기

Github Repository 세팅하기

[repository → Settings → Actions → General   Workflow permissions]

Github Repository 세팅

 

Workflow permissions 에서 Read and write permissions를 활성화한 후 Save 한다.

 

 

workflow.yml 세팅하기

Github Action 은 workflow 를 기반으로 동작한다. 
이 단계에서는 workflow 의 동작을 설정하는 workflow.yml의 작성 예시를 서술한다.
* workflow 의 작성은 개개인의 빌드 환경에 따라 커스텀 되어야 한다. (예시를 맹신하지 말 것)

workflow.yml 파일은 반드시 레포지토리의 루트 디렉토리 아래의. github/workflows/ 안에 위치해야만
Github에서 Workflow로 인식할 수 있다.

본 과정은 이전 포스팅 작업에서 후행되는 과정으로,
사용자의 프로젝트 파일과 도커파일이 모두 갖춰졌다는 전제 하에 작성되었다.

 

workflow 세팅
위와 같이 root 디렉토리 / .github / workflows 안에 workflow.yml 파일이 위치해야 한다.

 

[repository(root)/.github/workflows/"yourCustomWorkflow.yml"]

name: workflow-server-1 # name : workflow의 이름을 지정한다.
on:
push: # 특정 경로의 파일이 변경되었을 때만, 특정 브랜치가 push 되었을 때만 워크플로우가 실행
paths: # 특정 경로를 지정
- '.github/workflows/**'
- 'src/**'
- 'build.gradle'
- 'Dockerfile'
branches: # 특정 브랜치를 지정
- ci_cd
jobs:
makeTagAndRelease: # 태그를 만들고 Release 하는 작업
runs-on: ubuntu-latest
outputs: # 해당 작업 완료 시 새로운 태그를 생성한다.
tag_name: ${{ steps.create_tag.outputs.new_tag }}
steps:
- uses: actions/checkout@v4
- name: Create Tag # 태그 생성
id: create_tag
uses: mathieudutour/github-tag-action@v6.1
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Create Release # 생성된 태그 Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ steps.create_tag.outputs.new_tag }}
release_name: Release ${{ steps.create_tag.outputs.new_tag }}
body: ${{ steps.create_tag.outputs.changelog }}
draft: false
prerelease: false
buildImageAndPush: # 이미지를 만드는 과정
permissions: #403 error 해결 위한 explicit permission 추가
contents: read
packages: write
name: 도커 이미지 빌드와 푸시 # Github Action workflow run 시 작업의 이름을 커스터마이징
needs: makeTagAndRelease
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Docker Buildx 설치
uses: docker/setup-buildx-action@v2
- name: 레지스트리 로그인
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: username 대문자 소문자로 변환 # Github Action username에 있는 대문자를 못 읽는 문제 해결
run: |
echo "OWNER_LC=${OWNER,,}" >> ${GITHUB_ENV}
env:
OWNER: '${{ github.repository_owner }}'
- name: application-secret.properties 생성
env:
ACTIONS_STEP_DEBUG: true
APPLICATION_SECRET: ${{ secrets.APPLICATION_SECRET_PROPERTIES }}
run: echo "$APPLICATION_SECRET" > ./src/main/resources/application-secret.yml
- name: 빌드 앤 푸시(Server)
uses: docker/build-push-action@v3
with:
# 빌드시 사용할 도커파일 경로와 컨텍스트를 지정한다.
context: ./
file: ./Dockerfile
push: true
tags: | # 빌드 완료 시 패키지명을 지정한다.
ghcr.io/${{ env.OWNER_LC }}/gamedragons-server-deploy:${{ needs.makeTagAndRelease.outputs.tag_name }},
ghcr.io/${{ env.OWNER_LC }}/gamedragons-server-deploy:latest

 

상기 파일 내용에 의해 특정 원격 브랜치로 push가 일어날 때마다 특정 경로의 파일에 변경이 가해지면

  1. 자동적으로 해당 workflow 가 실행된다.
  2. * Releases 태그와 패키지가 생성된다. (후술)
  3. * DockerHub에 유저 / Organization 이름과 repository를 조합한 도커 이미지가 생성된다. (후술)

 

workflow.yml의 작업에는 여러 github actions 라이브러리가 사용된다. (uses로 기재되어 있는 것들)

이 중 actions/ 으로 명시된 것은 Github에서 정식으로 제공하는 Github Action 라이브러리이며,

 docker/ 는 Docker 와의 호환을 위해 Docker에서 정식으로 제공하는 Github Action 라이브러리이다.

그 외에도 태그 생성에 사용한 커스텀 유저의 라이브러리도 있다.

yml 코드에 활용가능한 라이브러리들은 아래 marketplace에서 사용 방법과 예시 코드를 확인할 수 있다.

 

GitHub Marketplace: actions to improve your workflow

Find the actions that help your team build better, together.

github.com

 

 

Github Actions의  workflows 동작 확인하기

[Github repository → Actions → workflows]

workflows 동작 확인

 

위와 같이 workflows에 들어가 workflow 실행 결과와 과정을 디버깅할 수 있다.

workflow 작업이 성공하면 빌드가 완료되었음을 의미한다.

 

 

Releases, Packages 확인하기

Releases, Packages는 상기 작성한 workflow.yml 파일의 설정에 따라 빌드가 실행되며 생성되는 것으로,
release 되게 설정할 수도 있고, 되지 않게 할 수도 있다.

 

packages 확인
Releases 태그와 Packages 생성 확인, 레포지토리의 메인의 우측 하단에서 확인할 수 있다.

 

 

패키지의 도커 이미지 파일 pull 하기

위의 과정을 통해 등재된 package 에는 도커 이미지를 받을 수 있는 주소가 명시되어 있다.
아래의 주소에서 도커 이미지를 pull 받아 run 한다.
도커를 통한 이미지 파일 생성을 경험해 보았다면
workflow.yml을 통한 Github Action이 제공하는 개선의 경험은 아래와 같다는 것을 알고 있을 것이다.

1. 일일이 프로젝트가 수정될 때마다 도커 호스트 내부에서 git pull을 받고 수동으로 이미지를 생성할 필요 없음
→ 도커 내부에 프로젝트 파일을 가지고 있을 필요도, 일일히 지우고 다시 생성할 필요 없음

2. Github에서 진행하는 형상관리를 통해 Pull Request, Push 발생과 동시에 지속적 배포가 발생함
→ 프로젝트 관리와 배포가 같은 환경에서 일어나므로 가시성 있는 배포와 작업 상황 공유와 추적에 용이

gamedragons client deploy

 

그러나 해당 명령어를 복사해 도커에서 실행하면 아래와 같은 오류를 확인할 수 있다.

bash
닫기
Error response from daemon:
Head "https://ghcr.io/v2/techno-dragons/gamedragons-client-deploy/manifests/latest": unauthorized

이는 해당 패키지를 받을 권한이 없음을 의미하는 오류로, 원인은 Package를 Private로 설정했기 때문이다.

 

 

 Private 패키지 설정과 그 이유

기존에 생성되는 Package는 초기에 Public으로 설정되어 있으나, 이는 대부분 Private으로 관리되어야 한다.
본 대목에서는 Package를 Private으로 설정하는 방법과 그 이유에 대해 서술한다.

 

Package를 Private으로 설정해야 하는 이유?
Package를 통해 만들어진 도커 이미지를 실행하면. jar과 같은 실행 파일이 생성된다. 
이렇게 생성된 실행파일은 github에 있는 소스코드는 물론. gitignore를 통해 github에 등재되지 않은 민감한 설정 파일(예 : application-secret.yml, 민감한 api-key 등)에 대한 정보 또한 빌드 과정에서 가지게 된다.

즉, 이미지 파일을 입수하게 된다면 해당 실행 파일로 접근해 디컴파일할 시
개발자가 숨기고자 했던 설정 파일과 그 내용에도 접근이 가능함을 의미한다.

따라서, Package 설정은 가급적 Private으로 설정해 접근 권한을 제한할 것을 권장한다.
* Private Repository의 경우에는 Github Actions 정책이 유료로 변경되므로 필요시에 적용한다.

 

[참고] Github Actions 요금 정책

 

GitHub Actions 요금 청구 정보 - GitHub Docs

계정에 포함된 스토리지 또는 시간(분)을 벗어나 GitHub Actions를 사용하면 추가 사용량에 대한 요금이 청구됩니다.

docs.github.com

github actions 요금 청구 정보
Github Actions는 Public 레포지토리에서는 무료, Private은 유료이다.

 

 

Package Private 설정을 위해 아래와 같이 들어간다.

[Root repository → Package → Package settings → 하단의 Change visibility]

private package 확인하기
danger zone visibility 활성화 하기

Change visibility를 눌러 설정 변경 후 왼쪽에서 "This package is currently private"으로 바뀐 걸 확인한다.

 

 

Private 패키지 이미지 파일에 접근 권한 얻는 방법

본 단계는 총 3가지의 단계로 진행된다.

1. 개인 인가 권한을 인증하기 위한 Github Access Token 발급
2. Package 설정에서 개인의 권한 부여
3. Github Access Token을 통한 도커 로그인하기

 

1. 인증수단인  Github Access Token 발급

아래의 링크로 접근한다.

https://github.com/settings/tokens/new

 

GitHub: Let’s build from here

GitHub is where over 100 million developers shape the future of software, together. Contribute to the open source community, manage your Git repositories, review code like a pro, track bugs and fea...

github.com

 

 

access token을 만든다.

  • Note : 해당 access token이 어떤 용도로 쓰일지 기재한다.
  • Expiration : 만료 일자를 설정한다. GitHub은 만료 일자를 설정하는 것을 권장하고 있다(탈취 및 분실 관련) 
  • scope : read:packages를 체크한 후 생성한다.

!! 주의 : 해당 토큰은 최초 생성 후 1회 열람이 가능하다.
해당 토큰의 키 값은 반드시 개인 보관해야 하며 이후의 창을 닫을 시 다시는 볼 수 없다.

personal access token

 

 

2. Packages에서 개인 권한 설정하기

다시 한번 Package Settings로 들어간다.

[Root repository → Package → Package settings → Inherited access]

inherited access

Inherited Access는 유저별 접근 권한을 설정하는 것으로, 개인의 권한을 최소 Read 이상 설정한다.

* 필자는 직접 workflow.yml로 패키지 빌드까지 작업해야 하기 때문에 Admin으로 설정했다. 만약 CI / CD 파트와 아닌 파트의 분리가 필요하면 권한 설정을 분리하는 것을 권장한다.

 

 

3. Github Access Token 활용 도커 로그인

서버 도커 호스트에 로그인하여 아래와 같은 명령어로 도커허브 인증을 진행한다.

bash
닫기
# 도커 ghcr.io 로그인 (이후 개행해 Github username, Github Access Token 값 입력)
$ docker login ghcr.io
# 한줄로 바로 입력하고 싶을 때
$ docker login -u <Github username> -p <발급받은 Github Access Token 값>

로그인 확인
로그인 성공

해당 Warning은 서버에 내 비밀번호가 평문으로 저장되고 있다는 뜻이다.
이는 docker credential helper를 설치와 설정을 통해 해결할 수 있다(이후 포스팅에서 다룰 예정)
실습용이니 무시하고 진행한다.

 

다시 패키지로 돌아가 아까의 인스톨 명령어를 붙여 넣기 해본다.

[Root repository → Package]

package 확인
docker compose 확인

 

이미지가 성공적으로 pull 되었음을 확인할 수 있다.

이후 도커 컨테이너에서의 run 작업은 도커와 동일하게 실행하면 된다.

 


 

반응형