멀티 아키텍처 이미지와 docker buildx

하나의 이미지 태그로 AMD64·ARM64 등 여러 CPU 아키텍처를 지원하는 멀티 아키텍처 이미지 구조, Manifest List 개념, docker buildx로 멀티 아키텍처 빌드하고 푸시하는 방법, QEMU 에뮬레이션을 설명합니다.

· 5 min read · PALDYN Team

지난 글에서 이미지를 정확히 식별하는 Digest를 살펴봤다. 이번에는 하나의 태그 아래에 여러 CPU 아키텍처용 이미지를 묶는 멀티 아키텍처 이미지를 다룬다. Apple M 시리즈 Mac, AWS Graviton, Raspberry Pi 등 ARM 기반 환경의 확산으로 멀티 아키텍처 지원은 이제 선택이 아닌 필수가 되고 있다.

왜 멀티 아키텍처가 필요한가

CPU 아키텍처(x86_64, ARM64, ARM v7 등)마다 실행 파일 형식이 다르다. 같은 컨테이너 이미지도 아키텍처에 맞는 바이너리를 포함해야 한다.

과거에는 아키텍처별로 다른 이미지를 관리했다.

myapp:latest-amd64
myapp:latest-arm64
myapp:latest-armv7

멀티 아키텍처 이미지(Manifest List / Image Index)를 사용하면 하나의 태그로 모든 플랫폼을 지원할 수 있다.

docker pull myapp:latest
# → 현재 호스트 아키텍처에 맞는 이미지 자동 선택

Manifest List 구조

Manifest List는 OCI 이미지 인덱스(Image Index) 스펙에 정의된 메타데이터 문서다. 각 플랫폼에 해당하는 이미지 Digest를 나열한다.

{
  "manifests": [
    {
      "digest": "sha256:aaa111...",
      "platform": {"os": "linux", "architecture": "amd64"}
    },
    {
      "digest": "sha256:bbb222...",
      "platform": {"os": "linux", "architecture": "arm64"}
    }
  ]
}

docker pull nginx:latest를 실행하면 Docker 데몬이 호스트 아키텍처를 감지해 해당 플랫폼의 이미지를 자동으로 선택한다.

Manifest List 구조

docker manifest 조회

# 멀티 아키텍처 지원 여부 확인
docker manifest inspect nginx:latest

# 특정 플랫폼 Digest 확인
docker manifest inspect nginx:latest \
  | jq '.manifests[] | {arch: .platform.architecture, digest}'

docker buildx — 멀티 아키텍처 빌드

docker build는 기본적으로 현재 호스트 아키텍처의 이미지만 만든다. docker buildx는 QEMU 에뮬레이션을 통해 다른 아키텍처용 이미지도 빌드할 수 있다.

# QEMU 지원 설정 (최초 1회)
docker run --privileged \
  --rm tonistiigi/binfmt --install all

# buildx builder 생성
docker buildx create \
  --name multiarch --use

# 멀티 아키텍처 빌드 + 레지스트리 푸시
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myrepo/myapp:latest \
  --push .

--push 없이 로컬에 저장하려면 단일 플랫폼만 가능하다 (--load 사용). Manifest List는 레지스트리에 푸시해야 완전히 동작한다.

buildx 빌드 명령

플랫폼 명시적 지정

특정 플랫폼용 이미지를 명시적으로 pull하거나 실행할 수 있다.

# 특정 아키텍처 이미지 강제 pull
docker pull --platform linux/arm64 nginx:latest

# 다른 아키텍처 컨테이너 실행 (QEMU 필요)
docker run --platform linux/arm64 nginx:latest

Dockerfile에서 플랫폼 변수 활용

멀티 아키텍처 빌드에서는 플랫폼에 따라 다른 바이너리나 패키지를 사용해야 할 수 있다.

# ARG로 플랫폼 정보 접근
FROM --platform=$BUILDPLATFORM golang:1.22 AS builder
ARG TARGETOS TARGETARCH
RUN GOOS=$TARGETOS GOARCH=$TARGETARCH \
    go build -o /app ./...

FROM --platform=$TARGETPLATFORM debian:slim
COPY --from=builder /app /app
CMD ["/app"]

BUILDPLATFORM은 빌드가 실행되는 호스트 플랫폼, TARGETPLATFORM은 최종 이미지 대상 플랫폼이다. Go나 Rust처럼 크로스 컴파일을 지원하는 언어는 QEMU 에뮬레이션 없이 네이티브 속도로 빌드할 수 있다.

AWS ECR, GHCR에서의 멀티 아키텍처

주요 레지스트리는 모두 멀티 아키텍처 이미지를 지원한다.

# Amazon ECR에 멀티 아키텍처 푸시
aws ecr get-login-password | docker login ...
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t 123456789.dkr.ecr.ap-northeast-2.amazonaws.com/myapp:v1 \
  --push .

AWS Graviton 인스턴스(arm64)에 배포하면 동일한 비용으로 더 높은 성능을 얻을 수 있다. Graviton3 기반 인스턴스는 같은 사양 x86 대비 약 40% 비용 절감이 보고된다.


지난 글: Docker 이미지 Digest — 불변 참조의 핵심

다음 글: Docker 이미지 네이밍과 태깅 전략


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