본문 바로가기

운영체제 및 플랫폼/Docker(도커)

GitHub Actions로 도커 이미지 빌드·푸시하기 — GHCR 자동 업로드 파이프라인 만들기

728x90
반응형

한 줄 요약

GitHub Actions 워크플로를 만들면 코드를 push할 때마다 도커 이미지가 자동으로 빌드되어 GitHub Container Registry(GHCR)에 올라가요.

GitHub Actions


1. 핵심 개념

 

1.1 무엇을 자동화하나요

지금까지 손으로 하던 아래 과정을 GitHub Actions가 대신해요.

코드 push → 이미지 빌드 → 태그 부여 → GHCR 업로드

GitHub Actions의 기본 구성(워크플로, 잡, 스텝)은 이전 글에서, CI/CD 개념은 CI/CD란 무엇인가? 글에서 다뤘어요.

 

1.2 사용하는 공식 액션

공식 문서 예시는 Docker가 제공하는 액션을 사용해요.

액션 역할

actions/checkout 저장소 코드를 러너로 내려받아요
docker/login-action 레지스트리에 로그인해요
docker/metadata-action 이미지 태그와 라벨을 자동으로 만들어요
docker/build-push-action 이미지를 빌드하고 레지스트리에 올려요

라벨(label): 이미지에 붙이는 부가 정보예요. 소스 저장소 주소, 생성 시각 등을 기록해요.

 

1.3 왜 중요한가

  • 이미지를 만드는 사람과 환경에 따라 결과가 달라지는 문제를 줄여요.
  • 어떤 커밋으로 만든 이미지인지 기록이 남아요.
  • 레지스트리 로그인 정보를 개인 PC에 둘 필요가 줄어요.

2. 쉽게 이해하기

이 파이프라인은 빵집의 자동 포장 라인과 같아요.

  • 새 반죽(코드)이 들어오면
  • 오븐(빌드)을 거쳐
  • 날짜 스티커(태그)를 붙이고
  • 매장 진열대(레지스트리)로 자동으로 옮겨져요.

사람은 반죽만 넣으면 되고, 나머지 과정은 매번 같은 방식으로 진행돼요.


3. 준비물

  • GitHub 저장소
  • 저장소 최상위 폴더의 Dockerfile
  • 별도 토큰 발급은 필요 없어요. 워크플로에서 자동 생성되는 GITHUB_TOKEN을 사용해요.

4. 워크플로 작성

.github/workflows/docker-publish.yml 파일을 만들어요. 아래는 GitHub 공식 문서 예시를 기반으로 실행 조건을 조정한 내용이에요.

name: Build and Push Docker Image

on:
  push:
    branches: ['main']
    tags: ['v*']

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build-and-push-image:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      - name: Log in to the Container registry
        uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata (tags, labels)
        id: meta
        uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}

      - name: Build and push Docker image
        id: push
        uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

 

4.1 핵심 부분 설명

실행 조건 (on)

  • main 브랜치에 push하면 실행돼요.
  • v1.0.0처럼 v로 시작하는 Git 태그를 push해도 실행돼요.

환경 변수 (env)

  • REGISTRY: GHCR 주소예요.
  • IMAGE_NAME: 소유자/저장소 형식의 저장소 이름이에요.

권한 (permissions)

  • packages: write: GITHUB_TOKEN이 GHCR에 이미지를 올릴 수 있게 해요.
  • contents: read: 코드를 읽을 수 있게 해요.

로그인 (docker/login-action)

  • username: 워크플로를 실행한 사용자(github.actor)예요.
  • password: 자동 생성된 GITHUB_TOKEN이에요.

태그 생성 (docker/metadata-action)

  • id: meta로 이름을 붙여, 다음 스텝에서 결과를 참조해요.
  • 기본 설정에서는 브랜치 push 시 브랜치 이름이, Git 태그 push 시 태그 이름이 이미지 태그로 쓰여요. 세부 규칙은 metadata-action 문서에서 확인하세요.

빌드·업로드 (docker/build-push-action)

  • context: .: 저장소 최상위 폴더를 빌드 컨텍스트로 써요.
  • push: true: 빌드가 성공하면 이미지를 올려요.

 

4.2 액션 버전을 SHA로 적은 이유

공식 문서는 외부 액션을 커밋 SHA로 고정하도록 권장해요. 태그로 참조하면 예고 없이 내용이 바뀔 수 있기 때문이에요. 위 SHA 값은 작성 시점 공식 문서 예시 기준이에요. 새 버전을 쓰려면 SHA를 직접 갱신해야 해요.


5. 실행 결과 확인

  1. 파일을 main 브랜치에 push해요.
  2. 저장소의 Actions 탭에서 실행 상태를 확인해요.
  3. 성공하면 저장소 또는 계정의 Packages에서 이미지를 확인할 수 있어요.

서버에서는 이렇게 내려받아요.

docker pull ghcr.io/<소유자>/<저장소>:main

 

비공개 패키지라면 먼저 docker login ghcr.io가 필요해요.


6. 핵심 정리

  • GitHub Actions로 이미지 빌드부터 GHCR 업로드까지 자동화할 수 있어요.
  • GHCR 업로드에는 GITHUB_TOKEN과 packages: write 권한을 써요.
  • metadata-action이 브랜치·태그 기준으로 이미지 태그를 만들어요.
  • 공식 문서는 외부 액션을 커밋 SHA로 고정하도록 권장해요.
  • 결과는 Actions 탭과 Packages에서 확인해요.

7. 추가 정보

주의사항

  • 첫 업로드는 비공개: GHCR 패키지는 처음 올리면 기본 비공개예요.
  • 저장소 연결: 공식 문서에 따르면 같은 네임스페이스에 이전에 올린 패키지가 저장소와 연결되어 있지 않으면 GITHUB_TOKEN으로 push할 수 없어요. Dockerfile에 org.opencontainers.image.source 라벨을 추가하는 방법이 안내되어 있어요.
  • 이미지 이름은 소문자: 저장소 이름에 대문자가 있으면 이미지 이름 형식 오류가 날 수 있어요.
  • 아티팩트 증명(attestation): 공식 문서 예시에는 빌드 출처를 증명하는 actions/attest 스텝이 포함되어 있어요. 이 글에서는 단순화를 위해 제외했어요. 사용한다면 attestations: write, id-token: write 권한도 필요해요.

Docker Hub로 올리는 경우

공식 문서는 Docker Hub용 예시도 제공해요. 이때는 Docker Hub 사용자명과 비밀번호(또는 토큰)를 Secrets에 저장해 사용해요. 공식 문서에 따르면 GitHub 제공 러너는 GitHub과 Docker의 협약에 따라 Docker Hub 요청 횟수 제한을 적용받지 않아요. self-hosted runner는 제한의 영향을 받을 수 있어요.

관련 글

 

반응형