docker image build시 이런에러가 날 떄가 있습니다.
exec user process caused “exec format error”
원인 : 운영체제 차이
현재 m1의 과도기 상황에서 m1으로 빌드한 이미지를
서버가 arm 운영체제인 상황에서 돌리려고 할 떄 나는 에러입니다.
이 경우 이미지 빌드시 멀티 플랫폼 빌드로 이미지를 빌드하여 해결할 수 있습니다.
m1 맥북을 사용하다보면, 맥북에서 빌드한 이미지가, 서로 다른 CPU 아키텍처로 인해 서버 에러에서 실행할 수 없는 경우가 발생합니다.
다양한 플랫폼에서 지원되는 이미지를 빌드해야합니다.
Docker는 multi-architecture 빌드 등, 다양한 빌드 옵션을 지원하는 CLI 플러그인을 제공합니다.
Buildx는 19.03 이후 버전부터 사용이 가능하다고 하니 버전 확인이 필요합니다. 공식 문서에 따르면, Docker Desktop을 사용하는 Windows나 MacOS 사용자 혹은 DEB, RPM 패키지로 도커를 설치한 사용자들은 자동으로 Buildx 플러그인이 포함되어 있습니다.
docker 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
에 아래의 옵션을 추가해주어야 합니다. 아래 예제에서 사용할 docker manifest
와 같은 커맨드들을 사용하기 위해서도 아래의 옵션을 추가해야 합니다.
# ~/.docker/config.json
{
...
"experimental": "enabled"
}
저는 m1 맥북에서, Docker Desktop을 사용하고 있는데, Docker Desktop에서는 이미 자주 사용되는 플랫폼의 환경설정이 되어 있습니다. 터미널에서 docker buildx ls
명령어를 실행하면, Docker Desktop에서 이미 제공하는 플랫폼들의 종류를 확인할 수 있습니다.
$ docker buildx create --name [name] --driver [option] --use
—-name : builder name
—-driver : (available : [])
docker : docker daemon에 내장된 builder를 사용
docker-container : docker를 통해 생성된 buildkit container를 사용, 이 드라이버를 사용하면 multi-platform image를 내보내거나 캐싱이 가능(하지만 docker image에 자동으로 나타나지 않음)
kubernetes : kubernetes 포드를 사용, 포드를 스핀업 하여 사용가능(kubernetes를 잘 몰라서 모르겠습니다..)
—-use : 현재 builder를 기본사용으로 지정
$ docker buildx build --platform=linux/amd64,linux/arm64
> docker buildx build --platform linux/amd64 --load --tag registry/test_api:1.0.0 .
[+] Building 36.9s (10/10) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 32B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/python:3.9.2-slim 3.8s
=> [1/4] FROM docker.io/library/python:3.9.2-slim@sha256:ce367bb30b8928efb632c369e3bd4a8dbd7905417bd0a245087a82c250e54a24 14.3s
=> => resolve docker.io/library/python:3.9.2-slim@sha256:ce367bb30b8928efb632c369e3bd4a8dbd7905417bd0a245087a82c250e54a24 0.0s
=> => sha256:e083ad7cc3ca624f4e268a778cb4f8be0d7a258240144862390e0da39082ea60 2.45MB / 2.45MB 7.3s
=> => sha256:65d21ac50a56640b50d18bd6c9d52bb967bd63de2e5dcce551340eb9bca26418 234B / 234B 1.5s
=> => sha256:229daa3ebd94b66f007a1fce482e8f7ef6b8deaf7e75324332fdfae7a197c67c 10.89MB / 10.89MB 7.1s
=> => sha256:edf8b70d3cc4282c43b24efda071ccab93b989a5dccb108b2102b0c2198c6471 2.77MB / 2.77MB 4.8s
=> => sha256:75646c2fb4101d306585c9b106be1dfa7d82720baabe1c75b64d759ea8adf341 27.14MB / 27.14MB 12.9s
=> => extracting sha256:75646c2fb4101d306585c9b106be1dfa7d82720baabe1c75b64d759ea8adf341 0.8s
=> => extracting sha256:edf8b70d3cc4282c43b24efda071ccab93b989a5dccb108b2102b0c2198c6471 0.1s
=> => extracting sha256:229daa3ebd94b66f007a1fce482e8f7ef6b8deaf7e75324332fdfae7a197c67c 0.4s
=> => extracting sha256:65d21ac50a56640b50d18bd6c9d52bb967bd63de2e5dcce551340eb9bca26418 0.0s
=> => extracting sha256:e083ad7cc3ca624f4e268a778cb4f8be0d7a258240144862390e0da39082ea60 0.1s
=> [internal] load build context 0.0s
=> => transferring context: 93B 0.0s
=> [2/4] WORKDIR /home/app 0.0s
=> [3/4] ADD . . 0.0s
=> [4/4] RUN pip install -r requirements.txt 13.5s
=> exporting to oci image format 5.1s
=> => exporting layers 1.0s
=> => exporting manifest sha256:c64d4192989179c14f8e01a173e890e0856348f891db80a01c3ab9f7c124211b 0.0s
=> => exporting config sha256:5ee75a529f8732c11b102ef337073268f540f539781e2c2da5c10705090d2958 0.0s
=> => sending tarball
실행 시 자동으로 push 됩니다.
--platform=linux/amd64,linux/arm64 :
amd64
와arm64
를 모두 지원하는 이미지를 빌드
--load : 이미지를 만들고 호스트 docker image에 저장
--push : --load옵션과 반대로 docker registry로 바로 push 하는 옵션
참고 자료 : https://www.docker.com/blog/multi-platform-docker-builds/
> docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry/test_api 1.0.1 5ee75a529f87 3 minutes ago 125MB
registry/test_api 1.0.0 79f4125ee89c 2 hours ago 118MB
> docker run -it -d --name test_api_1.0.0 registry/test_api:1.0.0
> docker exec -it test_api_1.0.0 dpkg -s libc6 | grep Arch
Architecture: arm64
Multi-Arch: same
> docker run -it -d --name test_api_1.0.1 registry/test_api:1.0.1
> docker exec -it test_api_1.0.1 dpkg -s libc6 | grep Arch
Architecture: amd64
Multi-Arch: same