はじめに
システム開発において、Docker を利用している方は多いのではないでしょうか。
Docker イメージは可搬性に優れており、検証環境でビルドしたイメージを本番環境に持ち込むことで、同一のアプリケーション実行環境を再現できます。
これにより、「環境差異による不具合」を減らせる点が、コンテナ技術の大きな強みです。
ただし、この可搬性は万能ではありません。
CPUアーキテクチャ(例:x86_64 と arm64)によっては、同一イメージでも動作しない場合があります。
そのため、「イメージさえあればどこでも同じように動く」という理解ではなく、実行環境との整合性を意識した運用が重要になります。
2. 本記事の結論
CPUアーキテクチャが一致しないとコンテナは起動できないです。
対策は、アーキテクチャを揃える or マルチアーキテクチャ対応が必要です。
3. 検証環境
3.1 ビルド環境
- OS
- Amazon Linux 2
- インスタンスタイプ
- t3.micro
3.2. コンテナ起動環境
- OS
- Amazon Linux 2023
- インスタンスタイプ
- t4g.micro
4. Dockerイメージのビルドとpush
4.1. CPU アーキテクチャの確認
sh-4.2$ uname -m
x86_64
4.2. Docker から ECR にログインする
sh-4.2$ aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin xxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com
WARNING! Your password will be stored unencrypted in /home/ssm-user/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
4.3. ビルド実施
sh-4.2$ sudo docker build -t cpu-arch-test .
[+] Building 3.3s (5/5) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 125B 0.0s
=> [internal] load metadata for docker.io/library/
〜以下、略〜
4.4. イメージにタグを付与する
sh-4.2$ sudo docker tag cpu-arch-test:latest xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest
4.5. ECR にイメージをプッシュする
sh-4.2$ sudo docker push xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest
The push refers to repository [xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test]
3baf45fb4b5e: Pushed
538812a4b9bd: Pushed
latest: digest: sha256:84d1632a2780f1e78d0857d90ce20707cda6b0b7d817ed52fb25c09e8dfd6057 size: 742
5. 別環境でpullして実行
5.1. CPU アーキテクチャを確認
sh-5.2$ uname -m
aarch64
5.2. Docker から ECR にログインする
sh-5.2$ aws ecr get-login-password --region us-west-2 | \
sudo docker login \
--username AWS \
--password-stdin xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store
Login Succeeded
5.3. ECR からイメージを Pull する
sh-5.2$ sudo docker pull xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest
latest: Pulling from cpu-arch-test
2f7571f14c6f: Pull complete
04f0c7cfe47b: Pull complete
Digest: sha256:84d1632a2780f1e78d0857d90ce20707cda6b0b7d817ed52fb25c09e8dfd6057
Status: Downloaded newer image for xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest
xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest
5.4. コンテナを起動する
exec /bin/bash: exec format error というエラーが出力され、コンテナの起動ができない。
sh-5.2$ sudo docker run -it xxxxxxxxxxxxx.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested
exec /bin/bash: exec format error
6. 原因
コンテナの起動しようとすると exec /bin/bash: exec format error というエラーが出力されました。
2. 本記事の結論 で述べた通り、ビルド環境とコンテナ起動環境の「CPUアーキテクチャが一致しない」場合、exec /bin/bash: exec format error が発生します。
7. イメージの対応している CPU アーキテクチャ確認方法
docker inspect <イメージID> でイメージがビルドされた環境を確認することができます。
amd64 の CPU アーキテクチャでのみ利用できます。
sh-5.2$ sudo docker inspect 3857ffd955b8
[
{
"Id": "sha256:3857ffd955b84f26942b70dd3758f043e1eefeb3d328dad6decbb96c88751872",
"RepoTags": [
"730335414536.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test:latest"
],
"RepoDigests": [
"730335414536.dkr.ecr.us-west-2.amazonaws.com/cpu-arch-test@sha256:84d1632a2780f1e78d0857d90ce20707cda6b0b7d817ed52fb25c09e8dfd6057"
~~~~~~中略~~~~~~
"Architecture": "amd64", ★このイメージは、「amd64」でビルドされている。
"Os": "linux", ★このイメージは、「linix」でビルドされている。
"Size": 511986239,
~~~~~~中略~~~~~~
]
"Architecture": "amd64" と記述されているので、このイメージは、 amd64 の CPU アーキテクチャでのみ利用できるということになります。
8. マルチアーキテクチャ対応イメージについて
ここまで、Dockerイメージは対応したCPUアーキテクチャでのみ実行できると説明しました。
しかし、異なるアーキテクチャ環境でも同一のイメージタグでコンテナを実行できる仕組みが存在します。それが「マルチアーキテクチャ対応イメージ」です。
マルチアーキテクチャ対応のイメージは、イメージタグに複数のアーキテクチャのイメージが紐付いており、ホストの環境にあったイメージを自動的に利用します。
マルチアーキテクチャ対応のイメージであるか確認する方法は、docker manifest inspect <イメージ名> を利用することで確認することができます。
sh-5.2$ sudo docker manifest inspect nginx
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 2290,
"digest": "sha256:296499281873ebe2636681c6957776d29a31858d93c3e39b654b5aade87ed70a",
"platform": {
"architecture": "amd64", ★対応アーキテクチャ
"os": "linux"
}
},
~~~~~~中略~~~~~~
{
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 2290,
"digest": "sha256:39d28f84ac5f308718a9649e15df444cf7af254fab03018c614c615803eb308b",
"platform": {
"architecture": "s390x", ★対応アーキテクチャ
"os": "linux"
}
}
]
}
9. 解決方法
exec /bin/bash: exec format error が発生した場合の解決方法は以下のとおりです。
※ この記事ではマルチアーキテクチャビルド方法については割愛させていただきます。
9.1. 実行環境と同じアーキテクチャでイメージをビルドする
最もシンプルな方法は、イメージのビルド環境と実行環境のCPUアーキテクチャを揃えることです。
以下のコマンドでホストのアーキテクチャを確認できます。
uname -m
また、Dockerイメージのアーキテクチャは以下で確認可能です。
docker image inspect <image> --format '{{.Os}}/{{.Architecture}}'
両者が一致していることを確認してください。
9.2. ビルド時にアーキテクチャを明示的に指定する
ビルド環境と実行環境が異なる場合、–platform オプションを利用することで、ターゲットのアーキテクチャを指定してイメージを作成できます。
docker build --platform linux/amd64 -t cpu-arch-test .
10. まとめ
本記事では、Dockerコンテナ実行時に発生する exec format error の原因と対処方法について解説しました。
- DockerイメージはCPUアーキテクチャに依存する
- 実行環境とイメージのアーキテクチャが一致しない場合、コンテナは起動できない
- マルチアーキテクチャ対応イメージを利用することで、環境差異を吸収できる
Dockerは環境差異を減らす強力なツールですが、CPUアーキテクチャの違いまでは完全に抽象化できません。 そのため、イメージのビルド戦略や実行環境を意識した設計が重要になります。