buildx 멀티 아키텍처 빌드 완전 정복

docker buildx로 amd64, arm64, arm/v7 등 여러 플랫폼을 동시에 빌드하는 방법, manifest list, QEMU 에뮬레이션, GitHub Actions CI 연동, TARGETARCH 활용을 정리합니다.

· 5 min read · PALDYN Team

지난 글에서 빌드 ARG의 고급 활용을 살펴봤다. 이번에는 하나의 이미지로 x86 서버, Apple Silicon, ARM 기기를 모두 지원하는 멀티 아키텍처 빌드를 정리한다.

왜 멀티 아키텍처인가

Apple M1/M2/M3 맥북의 보급, AWS Graviton(arm64) 인스턴스의 비용 효율성, Raspberry Pi 등 IoT 기기의 증가로 amd64 단독 이미지로는 부족해졌다. docker pull myapp:latest가 자동으로 해당 플랫폼에 맞는 레이어를 선택하려면 manifest list(이미지 인덱스)가 필요하다.

멀티 아키텍처 이미지 빌드 흐름

docker buildx란

docker buildx는 BuildKit 기반의 확장 빌드 CLI다. 기존 docker build와 달리 멀티 플랫폼 빌드, 빌더 인스턴스 관리, 다양한 캐시/출력 형식을 지원한다.

# 현재 빌더 목록 확인
docker buildx ls

# 기본 빌더는 단일 플랫폼만 지원
# NAME/NODE  DRIVER/ENDPOINT  STATUS  PLATFORMS
# default *  docker           running linux/amd64

멀티 플랫폼 빌더 설정

buildx 설정 및 빌드 명령

# 1. QEMU 에뮬레이터 등록 (x86 호스트에서 arm 빌드 가능)
docker run --rm --privileged \
  multiarch/qemu-user-static --reset -p yes

# 2. docker-container 드라이버로 빌더 생성
docker buildx create \
  --name multiarch \
  --driver docker-container \
  --use

# 3. 빌더 초기화 및 지원 플랫폼 확인
docker buildx inspect --bootstrap

멀티 플랫폼 빌드 및 푸시

docker buildx build \
  --platform linux/amd64,linux/arm64,linux/arm/v7 \
  --push \
  -t myregistry/myapp:latest \
  .

--push를 반드시 지정해야 한다. 멀티 플랫폼 이미지는 로컬 Docker 데몬에 로드할 수 없고(단일 플랫폼만 가능), 레지스트리에만 manifest list로 저장된다.

# 단일 플랫폼을 로컬에 로드 (테스트용)
docker buildx build \
  --platform linux/amd64 \
  --load \
  -t myapp:test .

# manifest 내용 확인
docker buildx imagetools inspect myregistry/myapp:latest

Dockerfile에서 플랫폼 분기

BuildKit은 빌드 시 BUILDPLATFORM, TARGETPLATFORM, TARGETOS, TARGETARCH 등의 내장 ARG를 제공한다.

# syntax=docker/dockerfile:1
FROM --platform=$BUILDPLATFORM golang:1.22 AS builder
ARG TARGETOS
ARG TARGETARCH
RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \
    go build -o /app .

FROM alpine:3.19
COPY --from=builder /app /app
CMD ["/app"]

--platform=$BUILDPLATFORM은 빌더 호스트 플랫폼(amd64)에서 Go 컴파일러를 실행하고, GOOS/GOARCH로 타겟 플랫폼 바이너리를 크로스 컴파일한다. QEMU 에뮬레이션보다 훨씬 빠르다.

GitHub Actions에서 멀티 아키텍처 빌드

name: Build and Push

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          platforms: linux/amd64,linux/arm64
          push: true
          tags: myuser/myapp:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max

플랫폼 지정 풀

# 특정 플랫폼 이미지 강제 풀
docker pull --platform linux/arm64 myapp:latest

# 현재 시스템 플랫폼 확인
docker info | grep Architecture

# 실행 중인 컨테이너 플랫폼 확인
docker inspect mycontainer | grep -i arch

베이스 이미지 플랫폼 호환성 확인

# 이미지가 지원하는 플랫폼 목록
docker buildx imagetools inspect node:20-alpine
# Image Index: ...
#   linux/amd64, linux/arm64/v8, linux/arm/v7, ...

공식 이미지 대부분은 멀티 아키텍처를 지원한다. 서드파티 이미지는 확인이 필요하다.

핵심 정리

  • docker buildx build --platform 으로 여러 아키텍처를 한 번에 빌드
  • 결과물은 manifest list로 레지스트리에 저장, docker pull이 자동으로 맞는 레이어 선택
  • QEMU 에뮬레이션 vs 크로스 컴파일: Go/Rust 등 정적 컴파일 언어는 크로스 컴파일이 훨씬 빠름
  • BUILDPLATFORM, TARGETARCH 내장 ARG로 플랫폼별 빌드 분기 가능
  • GitHub Actions: setup-qemu-action + setup-buildx-action + build-push-action

지난 글: 빌드 ARG 고급 활용

다음 글: Dockerfile 모범 사례 총정리


읽어주셔서 감사합니다. 😊