GitHub Actions 도커 이미지 자동 빌드
코드베이스를 지속해서 업데이트하고 최신 버전을 유지하는 것은 프로젝트의 중요한 측면 중 하나입니다. GitHub Actions를 활용하여 다른 레포지토리의 업데이트를 주기적으로 확인하고 필요할 때마다 나의 레포지토리에 자동으로 업데이트하는 방법을 소개합니다. 본 예시에서는 제가 개인적으로 사용하기 위해 오픈소스 프로젝트 트래킹 Planka에 사용된 실제 코드를 기반으로 설명합니다.
TL;DR
name: Check for updates
on: schedule: - cron: '*/5 * * * *' workflow_dispatch:jobs: publish: runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v4 with: token: ${{ secrets.GH_PAT }} - run: | LOCAL_VER=$(git -c 'versionsort.suffix=-' \ ls-remote --exit-code --refs --sort='version:refname' --tags https://github.com/NavyStack/planka-ns.git \ | tail --lines=1 \ | cut --delimiter='/' --fields=3) RELEASE_VER=$(git -c 'versionsort.suffix=-' \ ls-remote --exit-code --refs --sort='version:refname' --tags https://github.com/plankanban/planka.git 'v*.*.*' \ | tail --lines=1 \ | cut --delimiter='/' --fields=3) if [[ $RELEASE_VER != $LOCAL_VER ]]; then echo "Local version: $LOCAL_VER" echo "Latest upstream version: $RELEASE_VER" echo "Updating to latest version..." git tag ${RELEASE_VER} git push origin ${RELEASE_VER} else echo "No updates available..." fi
name: Docker Image CI
on: push: tags: - 'v*.*.*' workflow_dispatch:
jobs: build: runs-on: ubuntu-latest steps: - name: Checkout Dockerfile uses: actions/checkout@v4
- name: Set version based on tag run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- name: Checkout planka Server uses: actions/checkout@v4 with: repository: plankanban/planka ref: ${{ env.RELEASE_VERSION }} path: planka
- name: Docker meta id: meta uses: docker/metadata-action@v5 with: images: navystack/planka tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} flavor: | latest=true
#- name: Set up QEMU # uses: docker/setup-qemu-action@v3
#- name: Set up Docker Buildx # uses: docker/setup-buildx-action@v3
- name: Set up SSH uses: MrSquaare/ssh-setup-action@v3 with: host: ${{ secrets.SSH_ARM64_RUNNER }} private-key: ${{ secrets.SSH_PRIVATE_KEY_ARM64_RUNNER }}
- name: Set up Buildx uses: docker/setup-buildx-action@v3 with: endpoint: ${{ secrets.AMD64_RUNNER_ENDPOINT }} append: | - endpoint: ${{ secrets.ARM64_RUNNER_ENDPOINT }} platforms: linux/arm64
- name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }}
#- name: Build and push # uses: docker/build-push-action@v5 # with: # context: ./planka/ # file: ./planka/Dockerfile # tags: ${{ steps.meta.outputs.tags }} # labels: ${{ steps.meta.outputs.labels }} # platforms: linux/amd64,linux/arm64,linux/arm/v7 # push: ${{ github.event_name != 'pull_request' }} - name: Build and push uses: docker/build-push-action@v5 with: file: Dockerfile tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} platforms: linux/amd64,linux/arm64,linux/arm/v7 push: ${{ github.event_name != 'pull_request' }}
1. GitHub Actions로 레포지토리 업데이트 자동화하기
1-1. Workflow 설정
먼저, 코드에서 사용된 GitHub Actions workflow에 대한 설정을 살펴봅시다. 아래의 코드 조각은 5분마다 또는 수동으로 실행될 수 있는 작업을 정의한 것입니다.
on: schedule: - cron: '*/5 * * * *' workflow_dispatch:
schedule
: 크론 표현식을 사용하여 주기적으로 workflow를 실행합니다. 현재 설정은 매 5분마다 실행하도록 되어있습니다.workflow_dispatch
: 수동으로 workflow를 실행할 수 있는 트리거입니다.
1-2. Jobs 및 Steps
아래 코드는 주요 작업(publish
)과 해당 작업이 실행될 때 수행되는 단계(steps
)를 정의합니다.
jobs: publish: runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v4 with: token: ${{ secrets.GH_PAT }}
publish
: 이 작업은 최신 업데이트를 확인하고 필요한 경우 나의 레포지토리를 업데이트합니다. Ubuntu 최신 버전에서 실행됩니다.Checkout Code
: 나의 레포지토리의 코드를 체크아웃하는 단계입니다. GitHub API 토큰(GH_PAT
)을 사용하여 인증합니다. (태그를 기록하기 때문에 관련된 권한 역시 필요합니다.)
- run: | LOCAL_VER=$(git -c 'versionsort.suffix=-' \ ls-remote --exit-code --refs --sort='version:refname' --tags https://github.com/NavyStack/planka-ns.git \ | tail --lines=1 \ | cut --delimiter='/' --fields=3) RELEASE_VER=$(git -c 'versionsort.suffix=-' \ ls-remote --exit-code --refs --sort='version:refname' --tags https://github.com/plankanban/planka.git 'v*.*.*' \ | tail --lines=1 \ | cut --delimiter='/' --fields=3) if [[ $RELEASE_VER != $LOCAL_VER ]]; then echo "Local version: $LOCAL_VER" echo "Latest upstream version: $RELEASE_VER" echo "Updating to latest version..." git tag ${RELEASE_VER} git push origin ${RELEASE_VER} else echo "No updates available..." fi
run
: 실제로 업데이트를 확인하고 적용하는 스크립트가 실행되는 단계입니다. 이 스크립트는 두 프로젝트의 최신 태그를 비교하여 업데이트가 필요한 경우 자동으로 레포지토리를 업데이트합니다.
현재 https://github.com/NavyStack/planka-ns.git
와 https://github.com/plankanban/planka.git
를 비교하고 있습니다.https://github.com/plankanban/planka.git
가 업데이트 되면, https://github.com/NavyStack/planka-ns.git
에 반영하는 구조입니다.
위의 설정에 따라서 https://github.com/NavyStack/planka-ns/tags 여기에 새로운 태그가 기록되고 아래의 설정을 통해서 Docker 이미지를 빌드하고 푸시 합니다.
2. GitHub Actions로 Docker 이미지 CI 설정하기
이 GitHub Actions workflow는 태그가 푸시되거나 수동으로 실행될 때 Docker 이미지를 빌드하고 푸시하는 작업을 수행합니다.
2-1. Workflow 설정
name: Docker Image CI
on: push: tags: - 'v*.*.*' workflow_dispatch:
push
: 태그가 푸시되면 workflow가 실행됩니다. 태그는 “v*..” 형식을 따라야 합니다.workflow_dispatch
: 수동으로 workflow를 실행할 수 있는 트리거입니다.
2-2. Jobs 및 Steps
jobs: build: runs-on: ubuntu-latest steps: - name: Checkout Dockerfile uses: actions/checkout@v4
- name: Set version based on tag run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
build
: Docker 이미지 빌드 작업을 정의합니다. Ubuntu 최신 버전에서 실행됩니다.Checkout Dockerfile
: Dockerfile을 체크아웃하는 단계입니다.Set version based on tag
: 현재 태그에서 버전을 추출하고$GITHUB_ENV
에 저장합니다.
- name: Checkout planka Server uses: actions/checkout@v4 with: repository: plankanban/planka ref: ${{ env.RELEASE_VERSION }} path: planka
Checkout planka Server
: 레포지토리의 특정 버전을 체크아웃하는 단계입니다.
- name: Docker meta id: meta uses: docker/metadata-action@v5 with: images: navystack/planka tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}} flavor: | latest=true
Docker meta
: Docker 이미지의 메타데이터를 생성하는 단계입니다. Semantic versioning 및 이미지 플레이버를 설정합니다.
- name: Set up SSH uses: MrSquaare/ssh-setup-action@v3 with: host: ${{ secrets.SSH_ARM64_RUNNER }} private-key: ${{ secrets.SSH_PRIVATE_KEY_ARM64_RUNNER }}
Set up SSH
: SSH 연결을 설정하여 원격 환경에서 빌드를 실행할 수 있도록 합니다.
SSH 연결을 하는 가장 큰 이유는 멀티 아키텍쳐용 이미지를 만들기 때문이고, 가끔 Qemu에서 컴파일 오류가 나기 때문에 node를 append 해서 빌드합니다.
- name: Set up Buildx uses: docker/setup-buildx-action@v3 with: endpoint: ${{ secrets.AMD64_RUNNER_ENDPOINT }} append: | - endpoint: ${{ secrets.ARM64_RUNNER_ENDPOINT }} platforms: linux/arm64
Set up Buildx
: Docker Buildx를 설정하여 여러 플랫폼에서 빌드할 수 있도록 합니다.
기본 endpoint
는 Github Runner입니다. append
는 SSH를 통해서 접속하는 Self-host Arm 인스턴스 입니다.
위의 설정으로 기본적으로 amd64용 그리고 arm64용 이미지가 만들어집니다.
- name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }}
Login to Docker Hub
: Docker Hub에 로그인합니다.
password: ${{ secrets.DOCKER_PASSWORD }}
라고 사용했지만 실제로는 토큰입니다. 코드를 재사용하다보니 DOCKER_PASSWORD
로 되어 있네요 ㅎㅎ..
- name: Build and push uses: docker/build-push-action@v5 with: file: Dockerfile tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} platforms: linux/amd64,linux/arm64,linux/arm/v7 push: ${{ github.event_name != 'pull_request' }}
Build and push
: Docker 이미지를 빌드하고 푸시하는 단계입니다. 여러 플랫폼에서 빌드하고 푸시하며, 풀 리퀘스트 이벤트가 아닐 때만 푸시합니다.
이제 이 GitHub Actions workflow를 사용하여 태그가 푸시될 때마다 Docker 이미지를 빌드하고 푸시할 수 있습니다. 필요한 경우 이 예시를 참고하여 자신의 프로젝트에 맞게 설정할 수 있습니다.
Dockerhub에서 바로 확인해 보실래요? 바로가기
수고 많으셨습니다. 감사합니다.
Askfront.com (에스크프론트)
에스크프론트
에서는 NavyStack 가이드뿐만 아니라, 궁금한 모든 질문을 환영합니다. 😊