0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Docker におけるCPUアーキテクチャ選定を理解する

Last updated at Posted at 2024-11-15

目的

Docker のアーキテクチャ選定をしっかり理解して、ビルドエラー/実行時エラーを回避する。

状況

Docker イメージを作成する際に、CPUアーキテクチャ依存のパッケージをインストールしなければいけないことがある。

「他の人は動いているように見えるのに、自分の環境だとビルド時のパッケージのインストールに失敗する...(あるいはビルドは通っても実行時に謎のエラーになる...)」みたいな時は、パッケージが依存しているアーキテクチャと異なるアーキテクチャでビルドしている可能性がある。

その場合、ビルド時に適切なアーキテクチャを指定する必要がある。

基本的にはベースイメージのアーキテクチャが引き継がれる

まず基本的な考え方として、ビルドしたイメージのアーキテクチャはベースイメージのものと同じになる。
つまり、FROM ~~~ で指定したベースイメージのアーキテクチャが AMD64 であればビルドしたイメージも AMD64 になる。

ビルド時のマシンのアーキテクチャが考慮される

Docker はデフォルトでビルド時のマシンのアーキテクチャに対して最適なイメージを pull してくる。

多くのメジャーなイメージは、マルチプラットフォームに対応している。
例えば ubuntu の公式イメージの「OS/ARCH」欄を見ると複数のプラットフォーム用のイメージがあることが分かる。

スクリーンショット 2024-11-16 1.37.41.png

さてそれでは、自分の macOS マシンでシンプルに ubuntu の latest を pull すると、一体なんのアーキテクチャに対応したイメージがやってくるのだろうか。

Apple Silicon の macOS のアーキテクチャは ARM64。
(Intel のチップが入っていた時代の macOS は AMD64)

$ docker pull ubuntu:latest

# イメージの情報を確認するコマンド
$ docker image inspect ubuntu:latest --format '{{.Architecture}}'
arm64

arm64 と出た。ホストマシンである macOS と同じアーキテクチャのイメージが自動で選ばれている。

つまり、マルチプラットフォームに対応したベースイメージを使って何の気無しに自分のマシンでビルドすると、自分のマシンのアーキテクチャのイメージがビルドされるということになる。

(当然、マルチプラットフォーム対応イメージだとしても、自分のマシンのアーキテクチャと同じものがなければ話は違う)

Dockerfile の中でインストールしているパッケージの依存アーキテクチャが自分のマシンと同じであれば特に問題はないが、違った場合には、ビルドがコケたり実行できなかったりするだろう。

明示的に指定することで pull を制御する

これを明示的に指定すると、別のイメージを pull することもできる。:arrow_down:

$ docker pull --platform linux/amd64 ubuntu:latest

# イメージの情報を確認するコマンド
$ docker image inspect ubuntu:latest --format '{{.Architecture}}'
amd64

イメージのリストには以下のように表示されており、アーキテクチャ違いのイメージが2個(arm64とamd64)あることが分かる。

$ docker images | grep ubuntu
ubuntu  <none>  f825f99d3d8a  5 weeks ago  101MB
ubuntu  latest  59ab366372d5  5 weeks ago  78.1MB

$ docker image inspect f825f99d3d8a --format '{{.Architecture}}'
arm64
$ docker image inspect ubuntu:latest --format '{{.Architecture}}'
amd64

pull せずに、build コマンドで指定しても良い。

# 一旦 ubuntu のイメージをローカルから全て消した上で

# ベースイメージだけを指定した Dockerfile を用意
$ cat Dockerfile
FROM ubuntu:latest

$ docker build --platform=linux/amd64 . -t test
# ベースイメージの pull が自動で走ってビルドが完了

$ docker image inspect test --format '{{.Architecture}}'
amd64

ちゃんと AMD64 のイメージがビルドされた。

ちなみにこの build 時の --platform の指定はあくまでもベースイメージを pull するときの指定であって、「ARM64 のベースイメージを AMD64 のイメージに変更する」みたいなアーキテクチャの変更をするわけではない。

例えば、以下のような AMD64 のみ対応のイメージをベースイメージにして、--platform=linux/arm64 (対応していないアーキテクチャ)を指定してビルドしてみる。

スクリーンショット 2024-11-16 2.19.02.png

$ cat Dockerfile
FROM buildkite/puppeteer:latest

$ docker build --platform=linux/arm64 . -t test
(中略)
1 warning found (use docker --debug to expand):
 - InvalidBaseImagePlatform: Base image buildkite/puppeteer:latest was pulled with platform "linux/amd64", expected "linux/arm64" for current build (line 1)

さて、ビルドは成功したが、何やら warning が出ている。

Base image buildkite/puppeteer:latest was pulled with platform "linux/amd64", expected "linux/arm64" for current build (line 1)

「linux/arm64 が指定されたけど、実際には linux/amd64 のイメージが pull されたよ。」とのこと。
arm64 を指定したところで、無いものを引っ張ってくることは出来ない。
上で書いた通りで、--platformはあくまでも pull の指定であり、アーキテクチャの変更を行うわけではないということが分かる(そんなことはそもそも出来ない)。

ベースイメージに、必要なアーキテクチャが無い場合

これは必要なアーキテクチャがあるイメージに変えるしかない。

まとめ

  • イメージのアーキテクチャはベースイメージのアーキテクチャで決まる。
  • pullbuild--platform では、ベースイメージを pull する際のアーキテクチャを指定できる。
    • あくまでも pull の指定なので、必ずそのアーキテクチャのイメージが作れるわけではない。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?