GitHub Actions를 사용하여 컨테이너 이미지를 빌드하고 **GHCR(GitHub Container Registry)**에 자동 배포할 때, Buildx와 **GitHub Actions 전용 빌드 캐시(type=gha)**를 적용하여 CI/CD 시간을 크게 단축하는 워크플로우 가이드입니다.


1. 주요 특징 및 이점

  • GHCR 활용: 별도의 Docker Hub 계정이나 외부 레지스트리 비번 설정 없이 GITHUB_TOKEN 인증만으로 안전하게 컨테이너 레지스트리에 푸시.
  • type=gha 캐시: 빌드 레이어 캐시를 GitHub Actions 백엔드에 저장하여 동일한 의존성 재빌드 시간을 극적으로 줄임 (최대 80%+ 속도 향상).
  • Multi-platform 지원: QEMU를 연동하여 linux/amd64와 linux/arm64 이미지를 단일 작업에서 동시 생성.

2. GitHub Actions 워크플로우 작성

.github/workflows/docker-build.yml 경로에 아래 내용을 작성합니다.

name: Build and Push Docker Image to GHCR

on:
  push:
    branches:
      - main
    tags:
      - 'v*.*.*'
  pull_request:
    branches:
      - main

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

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

    steps:
      # 1. 소스코드 체크아웃
      - name: Checkout repository
        uses: actions/checkout@v4

      # 2. QEMU 설정 (멀티 아키텍처 빌드용)
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      # 3. Docker Buildx 설정
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      # 4. GHCR 로그인 (GITHUB_TOKEN 사용)
      - name: Log in to GitHub Container Registry
        if: github.event_name != 'pull_request'
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      # 5. Docker 메타데이터(태그, 라벨) 추출
      - name: Extract Docker metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}
            type=semver,pattern={{version}}
            type=sha,format=short

      # 6. Docker 이미지 빌드 및 GHCR 푸시 (GHA 캐시 재사용)
      - name: Build and push Docker image
        uses: docker/build-push-action@v6
        with:
          context: .
          platforms: linux/amd64,linux/arm64
          push: ${{ github.event_name != 'pull_request' }}
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          # GitHub Actions 전용 캐시 사용 (Build Speedup의 핵심!)
          cache-from: type=gha
          cache-to: type=gha,mode=max

3. Dockerfile 작성 베스트 프랙티스 (캐시 효율 극대화)

Actions 워크플로우에 cache-from: type=gha를 설정했더라도, Dockerfile의 레이어 순서가 적절하지 않으면 캐시가 무효화됩니다.

FROM node:20-alpine AS builder

WORKDIR /app

# 1. 패키지 의존성 정의 파일만 먼저 복사
COPY package.json package-lock.json ./

# 2. 의존성 설치 (소스코드가 변경되어도 이 레이어까지는 캐시 유지됨)
RUN npm ci

# 3. 그 후 전체 소스코드 복사 및 빌드
COPY . .
RUN npm run build

# 실행용 경량 스테이지 (Multi-stage build)
FROM node:20-alpine AS runner
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules

EXPOSE 3000
CMD ["node", "dist/index.js"]

4. 빌드 결과 확인 및 레지스트리 접근 권한 설정

  1. GitHub 레포지토리 메인 페이지 우측의 Packages 섹션에서 빌드 완료된 도커 이미지를 확인할 수 있습니다.
  2. 기본 권한이 Private인 경우, 다른 서버에서 docker pull을 받기 위해 ghcr.io 로그인 후 사용하거나 Package Settings에서 접근 권한(Public / Private)을 조정할 수 있습니다.
# 로컬 또는 다른 서버에서 GHCR 이미지 다운로드 테스트
echo <PERSONAL_ACCESS_TOKEN> | docker login ghcr.io -u <GITHUB_USERNAME> --password-stdin
docker pull ghcr.io/your-username/your-repo:latest

마무리

Buildx와 type=gha 캐시 설정을 적용하면 이후 빌드 시 의존성이 변경되지 않은 레이어는 즉시 캐시 처리되어 매우 빠른 속도로 CI/CD가 완료됩니다.