멀티 아키텍처 플랫폼
나의 경우 맥북 환경에서 fastAPI 프로젝트를 도커로 이미지화 시킨 후 윈도우에서 해당 도커 이미지를 받아와 실행시키니 아래와 같은 에러 로그가 컨테이너 로그에 출력되었다.
$ docker logs app
exec user process caused “exec format error”
원인은 운영체제 차이인데 멀티 플랫폼 빌드를 사용하여 쉽게 해결할 수 있다.
이미지의 실행 환경(CPU Archtecture)가 다르기 때문에 발생하는 에러이기 때문에(Mac m1 : ARM) 맥북에서 빌드한 이미지가 다양한 플랫폼에서 지원될 수 있도록 빌드 시 옵션을 지정해주어야 한다.
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
:amd64
와arm64
를 모두 지원하는 이미지로 빌드
--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