개요

노트북이 노후되어 최근 MacBook을 새로 하나 장만했습니다. M2 칩이 탑재된 MacBook Air 모델로 구매하였는대요. 지금까지 상당히 만족하면서 사용하고 있습니다.

M1이나 M2와 같은 애플 칩이 탑재된 MacBook 사용시 ARM64 아키텍처 호환 이슈를 가끔 겪게 되는대요. Docker 사용시에도 마찬가지로 아키텍처 호환 이슈를 신경써야 합니다.

제가 겪었던 이슈를 한마디로 정리하면 Docker 이미지 빌드 환경과 배포 환경간 아키텍처 미호환 이슈 입니다. Docker 이미지 빌드 환경은 제 노트북 (M2 Mac, arm64)이었고, 이미지를 배포하여 실행하는 환경은 클라우드 (Intel VM, x86_64)가 되면서 문제가 발생했습니다. M1/M2 MacBook을 사용하면서 기존 Intel MacBook과 차이점을 느끼지 못할정도로 프로그램들이 스무스하게 잘 돌아가서 내가 사용 중인 노트북이 ARM64 머신이라는 것을 종종 잊어먹습니다. ARM 머신에 각종 소프트웨어 포팅을 하던 임베디드 개발자 출신으로서 감회가 새롭네요. (라떼는 말이야…)

문제의 원인을 파악 하였으면 해결 방법은 간단합니다. docker buildx로 컨테이너 빌드시 멀티 아키텍처 지원 가능한 이미지를 빌드하여 배포하시면 됩니다.

Docker Buildx

Docker Buildx은 멀티 플랫폼 빌드 기능을 지원하는 docker CLI 확장 플러그인 입니다. Docker 19.03 이후 버전부터 사용할 수 있습니다.

이후 내용은 모두 M2 MacBook Air에서 Docker Desktop을 설치하여 실행 한 것 입니다. (ver. 4.12.0)

docker buildx ls로 빌더 목록과 정보를 확인 합니다. 현재 사용 중인 빌더에 * 표시가 되어 있습니다.

$ docker buildx ls
NAME/NODE       DRIVER/ENDPOINT STATUS  BUILDKIT PLATFORMS
default *       docker
  default       default         running 20.10.17 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6
desktop-linux   docker
  desktop-linux desktop-linux   running 20.10.17 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

docker-container 드라이버를 사용하는 새로운 빌더를 생성 합니다. (Why? default 빌더의 docker 드라이버는 멀티 플랫폼 기능이 지원되지 않습니다.)

$ docker buildx create --name multi-arch-builder --driver docker-container --bootstrap --use
[+] Building 3.3s (1/1) FINISHED
 => [internal] booting buildkit                                                         3.3s
 => => pulling image moby/buildkit:buildx-stable-1                                      2.7s
 => => creating container buildx_buildkit_multi-arch-builder0                           0.5s
multi-arch-builder
  • --driver: 사용할 드라이버 설정
  • --bootstrap: 빌더 생성이 끝나면 자동 초기화 합니다.
  • --use: 새로 생성한 빌더를 사용하도록 자동 설정 합니다.

샘플 Dockerfile

FROM alpine:3.16
RUN apk add curl

M1/M2 MacBook과 Intel VM을 두 플랫폼을 지원하는 멀티 플랫폼 이미지를 빌드 합니다.

$ docker buildx build --platform linux/arm64,linux/amd64 -t buildx-test .
[+] Building 8.8s (8/8) FINISHED

  (...)

  => CACHED [linux/amd64 2/2] RUN apk add curl
  => CACHED [linux/arm64 2/2] RUN apk add curl

빌드후 docker images로 이미지 목록을 확인해보면, 빌드된 이미지가 없습니다. 왜냐하면 빌드된 플랫폼별 이미지는 캐싱되어 있어서 그렇습니다. 이미지를 어디로 내보낼지 설정해야 합니다.

로컬로 가져오기 (테스트용)

--load 옵션을 사용하여 이미지를 로컬로 가져 올 수 있습니다. 현재 로컬 플랫폼만 지원하도록 빌드가 되어서 docker build와 별반 차이가 없습니다. docker buildx build로 빌드가 되는지 여부와 빌드된 컨테이너 이미지를 로컬에서 테스트하는 목적으로 사용합니다.

$ docker buildx build --load -t buildx-test .
[+] Building 1.2s (7/7) FINISHED
  (...)

$  docker images
REPOSITORY      TAG               IMAGE ID       CREATED          SIZE
buildx-test     latest            ff1af71a52f1   19 minutes ago   9.83MB

컨테이너 레지스트리에 올리기

--push 옵션을 사용하여 멀티 플랫폼 이미지 빌드와 동시에 컨테이너 레지스트리 (Docker Hub, ECR, GCR, ACR)에 push 합니다. 이때는 -t 옵션에 올바른 컨테이너 레지스트리 URI를 사용해야 합니다. docker login으로 사용할 컨테이너 레지스트리에 로그인이 되어 있어야 합니다.

$ docker buildx build --platform linux/arm64,linux/amd64 -t <Container Registry URI>/buildx-test --push .

이렇게 컨테이너 레지스트리에 멀티 플랫폼 이미지를 올려두면, docker pull로 컨테이너 이미지를 가져올때 플랫폼에 해당하는 이미지만 가져옵니다. 즉, M1/M2 MacBook에서 docker pull을 하면 ARM64 컨테이너 이미지를 가져오고, Intel VM에서 docker pull을 하면 x86_64 컨테이너 이미지를 가져 옵니다.

On M2 MacBook

$ docker pull briankim/buildx-test
Using default tag: latest
latest: Pulling from briankim/buildx-test
9b18e9b68314: Already exists
14acd24d0487: Pull complete
Digest: sha256:31f4e41656c9c3ac009e90628244f71068b7572d7303187cf41c0c62b722837a
Status: Downloaded newer image for briankim/buildx-test:latest
docker.io/briankim/buildx-test:latest

$ docker run --rm -it briankim/buildx-test
/ # arch
aarch64

On Intel VM

$ docker pull briankim/buildx-test
Using default tag: latest
latest: Pulling from briankim/buildx-test
9b18e9b68314: Already exists
14acd24d0487: Pull complete
Digest: sha256:31f4e41656c9c3ac009e90628244f71068b7572d7303187cf41c0c62b722837a
Status: Downloaded newer image for briankim/buildx-test:latest
docker.io/briankim/buildx-test:latest

$ docker run --rm -it briankim/buildx-test
/ # arch
x86_64

요약

  • 팀 중에 M1/M2 MacBook 사용자가 있으면 docker buildx로 멀티 플랫폼을 지원하도록 빌드 합시다.