[Docker] CPU 아키텍처에 따른 Docker Multi Architecture 구성하기 with Amazon ECR

ondacloud·2026년 4월 15일

Docker

목록 보기
1/1
post-thumbnail

Overview

Docker 이미지는 기본적으로 특정 CPU 아키텍처에 따라 만들어지기 때문에(ex: x86_64, ARM64 등) 서로 다른 환경에서 동일한 이미지를 실행하려고 하면 아키텍처 호환성 문제가 생길 수 있습니다. 최근에는 클라우드 환경, IoT 디바이스, 그리고 Apple Silicon처럼 여러 가지 플랫폼이 함께 사용되는 시대여서 이런 제약이 더욱 뚜렷하게 드러납니다.

이 글에서는 이러한 문제를 해결할 수 있도록 Docker의 멀티 아키텍처 이미지 구성 방법을 설명합니다. buildx를 사용해 여러 플랫폼용 이미지를 빌드하는 방법부터 manifest를 활용한 통합 이미지 관리 방법까지, 실제 따라 해볼 수 있는 예제를 중심으로 다룰 예정입니다. 이를 통해 하나의 이미지 태그만으로 다양한 아키텍처를 지원하는 과정을 이해하는 것이 목표입니다.

즉, 하나의 이미지를 여러 아키텍처 환경에서 그대로 사용하기 위해서는 멀티 아키텍처 이미지 구성이 필요합니다.


Setup

Application

package main

import (
	"fmt"
	"log"
	"net/http"
	"runtime"
)

func arch(w http.ResponseWriter, req *http.Request) {
	fmt.Fprintf(w, "Application Running\nARCH=%s\n", runtime.GOARCH)
}

func healthcheck(w http.ResponseWriter, req *http.Request) {
	fmt.Fprint(w, "OK")
}

func main() {
	http.HandleFunc("/arch", arch)
	http.HandleFunc("/healthcheck", healthcheck)
	log.Fatal(http.ListenAndServe(":8080", nil))
}

해당 애플리케이션은 실행 중인 컨테이너의 CPU 아키텍처를 확인하기 위한 테스트용 코드입니다.


Dockerfile

FROM --platform=$BUILDPLATFORM golang:1.22-alpine AS builder

WORKDIR /build

ARG TARGETOS
ARG TARGETARCH
ENV CGO_ENABLED=0

COPY ./main.go ./

RUN go mod init noah.io/ark/rest && go mod tidy

RUN --mount=type=cache,target=/root/.cache/go-build \
    GOOS=$TARGETOS \
    GOARCH=$TARGETARCH \
    go build -trimpath -buildvcs=false -ldflags="-s -w" -o main main.go

FROM alpine:3.20

WORKDIR /app

RUN apk add --no-cache curl

COPY --from=builder /build/main .

EXPOSE 8080
ENTRYPOINT ["/app/main"]
  • --platform=$BUILDPLATFORM : 빌드 환경 기준으로 builder 이미지 선택
  • TARGETOS, TARGETARCH : buildx가 자동으로 전달하는 타겟 플랫폼 정보
  • GOOS, GOARCH : 크로스 컴파일을 통해 다른 아키텍처용 바이너리 생성

Practice

ECR에 업로드 하는 Layer는 하나의 ECR Repository에서만 동작합니다.

Amazon ECR Registry를 생성합니다.


buildx Package를 설치합니다.

  • Amazon Linux 사용 시 buildx Package 설치를 안해도 무방합니다.
# AMD64
mkdir -p ~/.docker/cli-plugins
curl -L https://github.com/docker/buildx/releases/download/v0.33.0/buildx-v0.33.0.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx
chmod +x ~/.docker/cli-plugins/docker-buildx

# ARM64
mkdir -p ~/.docker/cli-plugins
curl -L https://github.com/docker/buildx/releases/download/v0.33.0/buildx-v0.33.0.linux-arm64 -o ~/.docker/cli-plugins/docker-buildx
chmod +x ~/.docker/cli-plugins/docker-buildx

buildx Version을 확인합니다.

docker buildx version

환경변수를 입력합니다.

ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
REGION_CODE="ap-northeast-2"
ECR_NAME="demo-ecr"
ECR_URI="$ACCOUNT_ID.dkr.ecr.$REGION_CODE.amazonaws.com/$ECR_NAME"
IMAGE_TAG="v1.0.0"

서로 다른 CPU 아키텍처 이미지를 빌드하기 위해서 tonistiigi/binfmt 컨테이너를 실행합니다.

docker run --privileged --rm tonistiigi/binfmt --install all

멀티 아키텍처 이미지를 빌드하기 위한 전용 빌더 환경을 생성합니다.

docker buildx create --name multi-builder --driver docker-container --use --bootstrap

ECR Registry에 로그인합니다.

aws ecr get-login-password --region $REGION_CODE | docker login --username AWS --password-stdin "$ACCOUNT_ID.dkr.ecr.$REGION_CODE.amazonaws.com"

CPU 아키텍처별로 Docker 이미지를 각각 따로 빌드합니다.

docker buildx build --platform linux/amd64 -t $ECR_URI:$IMAGE_TAG-amd64 --load .
docker buildx build --platform linux/arm64 -t $ECR_URI:$IMAGE_TAG-arm64 --load .

Amazon ECR에 Docker 이미지를 Push합니다.

docker push $ECR_URI:$IMAGE_TAG-amd64
docker push $ECR_URI:$IMAGE_TAG-arm64

Amazon ECR에 업로드한 Docker 이미지를 조회합니다. 조회 시 CPU 아키텍처별로 이미지가 업로드된 것을 확인할 수 있습니다.

aws ecr describe-images --repository-name $ECR_NAME --region $REGION_CODE


CPU 아키텍처 이미지를 하나로 만들기 위해서 멀티 아키텍처 이미지로 묶습니다.

  • manifest는 실제 이미지를 합치는 것이 아니라, 각 아키텍처 이미지를 참조하는 메타데이터입니다.
docker manifest create $ECR_URI:$IMAGE_TAG $ECR_URI:$IMAGE_TAG-amd64 $ECR_URI:$IMAGE_TAG-arm64

manifest에 각 이미지의 정확한 플랫폼 정보(OS/아키텍처)를 명시해줍니다.

docker manifest annotate $ECR_URI:$IMAGE_TAG $ECR_URI:$IMAGE_TAG-amd64 --os linux --arch amd64
docker manifest annotate $ECR_URI:$IMAGE_TAG $ECR_URI:$IMAGE_TAG-arm64 --os linux --arch arm64

멀티 아키텍처 manifest 안에 어떤 이미지들이 들어있는지 확인합니다.

docker manifest inspect $ECR_URI:$IMAGE_TAG


로컬에서 만든 멀티 아키텍처 manifest를 Amazon ECR에 업로드합니다.

docker manifest push $ECR_URI:$IMAGE_TAG

Test

docker run --platform=linux/amd64 -d -p 8080:8080 $ECR_URI:$IMAGE_TAG


docker run --platform=linux/arm64 -d -p 8080:8080 $ECR_URI:$IMAGE_TAG

동일한 이미지 태그를 사용하더라도 --platform 옵션에 따라 서로 다른 아키텍처의 컨테이너가 실행되는 것을 확인할 수 있습니다.

Result

이번 실습을 통해 Docker에서 멀티 아키텍처 이미지를 구성하는 전체 과정을 확인할 수 있었습니다.
기존에는 CPU 아키텍처(x86, ARM 등)가 다른 환경에서는 동일한 이미지를 사용할 수 없었지만, buildx와 manifest를 활용하면 하나의 이미지 태그로 여러 플랫폼을 동시에 지원할 수 있습니다.

이러한 방식은 클라우드 환경, CI/CD 파이프라인, 그리고 다양한 디바이스를 대상으로 하는 서비스에서 매우 중요한 요소이며, 단일 이미지 태그로 다양한 실행 환경을 지원할 수 있다는 점에서 운영 효율성과 확장성을 크게 향상시킬 수 있습니다.

profile
Devops Engineer가 목표인 학생

0개의 댓글