[Docker] 멀티 아키텍처 플랫폼 - Buildx (Docker Multi-Archtecture image)

멀티 아키텍처 플랫폼

나의 경우 맥북 환경에서 fastAPI 프로젝트를 도커로 이미지화 시킨 후 윈도우에서 해당 도커 이미지를 받아와 실행시키니 아래와 같은 에러 로그가 컨테이너 로그에 출력되었다.

$ docker logs app
exec user process caused “exec format error” 

원인은 운영체제 차이인데 멀티 플랫폼 빌드를 사용하여 쉽게 해결할 수 있다.


이미지의 실행 환경(CPU Archtecture)가 다르기 때문에 발생하는 에러이기 때문에(Mac m1 : ARM) 맥북에서 빌드한 이미지가 다양한 플랫폼에서 지원될 수 있도록 빌드 시 옵션을 지정해주어야 한다.
image


Buildx

Docker는 Multi-Archtecture 빌드 등 다양한 빌드 옵션을 지원하는 CLI 플러그인을 제공하고 있다.

Buildx의 경우 Docker 19.03 버전 이후부터 사용이 가능하다고 하니 멀티 아키텍처 빌드 전 도커의 버전을 확인해봐야 한다.

Docker Desktop을 사용하는 윈도우나 MacOS 사용자 혹은 DEB,RPM 패키지로 도커를 설치한 사용자들은 자동으로 Buildx 플러그인이 내장되어 있다.


사용 가능한지 체크

docker buildx 명령어를 터미널에 입력했을 때 아래와 같은 buildx 사용법이 제대로 출력된다면 buildx를 사용할 수 있는 것이다.

$ docker buildx
Usage:  docker buildx [OPTIONS] COMMAND

Extended build capabilities with BuildKit

Options:
      --builder string   Override the configured builder instance

Management Commands:
  imagetools  Commands to work on images in registry

Commands:
  bake        Build from a file
  build       Start a build
  create      Create a new builder instance
  du          Disk usage
  inspect     Inspect current builder instance
  ls          List builder instances
  prune       Remove build cache
  rm          Remove a builder instance
  stop        Stop builder instance
  use         Set the current builder instance
  version     Show buildx version information

Run 'docker buildx COMMAND --help' for more information on a command.

일부 하위 버전에서 buildx 플러그인을 사용하려면 ~/.docker/config.json 파일에 아래의 옵션을 추가해주어야 한다.

$ cat ~/.docker/config.json
{
    ...
    "experimental": "enabled"
}

플랫폼 종류 확인

나는 M1 맥북에서 Docker Desktop을 사용하고 있는데, Docker Desktop에서는 이미 자주 사용되는 플랫폼의 환경설정이 되어있다.

터미널에서 docker buildx ls로 Docke Desktop에서 이미 제공하는 플랫폼들의 종류를 확인할 수 있다

$ docker buildx ls
NAME/NODE             DRIVER/ENDPOINT  STATUS  BUILDKIT PLATFORMS
awesome_goldwasser *  docker-container
  awesome_goldwasser0 desktop-linux    running v0.12.2  linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6
default               docker
  default             default          running 20.10.22 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.22 linux/arm64, linux/amd64, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/arm/v7, linux/arm/v6

Builder 생성 및 사용 설정

$ docker buildx create --name [builder instance 명] --driver [드라이버 이름] --use
# multi-arch-builder로 사용 설정
$ docker buildx create --name multi-arch-builder --driver docker-container --use
multi-arch-builder

# 현재 Builder Instance 정보
$ docker buildx inspect --bootstrap
Name:          awesome_goldwasser
Driver:        docker-container
Last Activity: 2023-10-05 22:15:58 +0000 UTC

Nodes:
Name:      awesome_goldwasser0
Endpoint:  desktop-linux
Status:    running
Buildkit:  v0.12.2
Platforms: linux/arm64, linux/amd64, linux/amd64/v2, linux/riscv64, linux/ppc64le, linux/s390x, linux/386, linux/mips64le, linux/mips64, linux/arm/v7, linux/arm/v6

Buildx로 이미지 빌드하기

Buildx를 사용하여 멀티 플랫폼 이미지를 만들어보자.

Example

$ docker buildx build --platform=linux/amd64,linux/arm64

fastapi 프로젝트를 amd64 플랫폼 이미지로 빌드

$ docker buildx build --platform linux/amd64 --load --tag yshrim12/app:latest .
[+] Building 19.0s (11/11) FINISHED
 => [internal] load build definition from Dockerfile                                                0.0s
 => => transferring dockerfile: 267B                                                                0.0s
 => [internal] load metadata for docker.io/library/python:3.10                                      0.9s
 => [internal] load .dockerignore                                                                   0.0s
 => => transferring context: 2B                                                                     0.0s
 => [1/5] FROM docker.io/library/python:3.10@sha256:1e5e9ee5b5d12ec9c803eb6166ae4862641d21ed259d08  0.0s
 => => resolve docker.io/library/python:3.10@sha256:1e5e9ee5b5d12ec9c803eb6166ae4862641d21ed259d08  0.0s
 => [internal] load build context                                                                   0.0s
 => => transferring context: 141B                                                                   0.0s
 => CACHED [2/5] WORKDIR /usr/src/app                                                               0.0s
 => CACHED [3/5] COPY ./requirements/*.txt ./requirements.txt                                       0.0s
 => CACHED [4/5] RUN pip install --upgrade pip && pip install -r requirements.txt                   0.0s
 => CACHED [5/5] COPY ./ ./                                                                         0.0s
 => exporting to docker image format                                                               18.0s
 => => exporting layers                                                                             0.0s
 => => exporting manifest sha256:742645be226bfb66783ca6c087834bce6d264a3d548bce21eb6fb036d043fa36   0.0s
 => => exporting config sha256:7305650367e00c5711ae8a09e199d4b2b9b19dec271de82819e462d966b4318e     0.0s
 => => sending tarball                                                                             18.0s
 => importing to docker

--platform=linux/amd64,linux/arm64 : amd64arm64를 모두 지원하는 이미지로 빌드

--load : 이미지를 만들고 호스트의 docker image에 저장

--push : –load 옵션과 반대로 docker registry로 바로 Push 함.

이미지 실행 및 확인

# 도커 이미지 확인
$ docker images | grep 'fastapi'
yshrim12/app                             latest            7305650367e0   39 minutes ago   1.03GB

# 이미지 컨테이너로 실행
$ docker run -d -it --name fastapi -p 80:8080 yshrim12/app 

# 아키텍처 확인
$ docker exec -it fastapi dpkg -s libc6 | grep 'Arch'
Architecture: amd64
Multi-Arch: same

관련 글

지식 공유2분 읽기

[Docker] 컨테이너(Container)에 할당되는 CPU 제한하기

개요 이번 게시글에서는 도커 컨테이너에서 CPU를 최적으로 활용하는 방법에 대해서 기록해보려고 한다. 호스트 CPU Core 정보 확인 먼저 컨테이너에 CPU를 최적으로 할당하기 위해서는, 현재 호스트 시스템의 CPU 정보에 대해서...

도커
지식 공유1분 읽기

[Docker] 배그 최고급 꾸러기 시뮬레이터 배포

개요 최고급 꾸러미에 대한 확률 체감을 위한 시뮬레이터 프로그램을 구현하고 도커로 배포하였음. 배포 로직은 AWS EC2 인스턴스에 도커를 사용하여 nginx proxy manager를 배포하고 리버스 프록시로 홈 서버에 있는 시뮬레...

도커