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. 빌드 결과 확인 및 레지스트리 접근 권한 설정
- GitHub 레포지토리 메인 페이지 우측의 Packages 섹션에서 빌드 완료된 도커 이미지를 확인할 수 있습니다.
- 기본 권한이 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가 완료됩니다.