classmethod 若槻さんの記事 Dockerのマルチアーキテクチャイメージについて調べてみた を読んでマルチアーキテクチャなdockerコンテナを作ってみたくなったので、忘備録として記事を書きます。
ビルドの方法が分からなかったので、dockerの公式サイトを覗くと記載がありました。 Leverage multi-CPU architecture support
Docker Official Imagesの githubリポジトリ を覗くと、対応しているアーキテクチャは2020年4月12日時点で
- ARMv5 32bit (arm32v5) ※非公式
- ARMv6 32bit (arm32v6)
- ARMv7 32bit (arm32v7)
- ARMv8 64bit (arm32v8)
- Linux86-64 (amd64)
- Windows x86-64 (windows-amd64)
- IBM POWER8 (ppc64le) ※非公式
- IBM z Systems (s390x) ※非公式
- x86/i686 (i386) ※非公式
AWSが提供しているa1インスタンスのcpuinfoを見てみると
$ cat /proc/cpuinfo processor : 0 BogoMIPS : 166.66 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid CPU implementer : 0x41 CPU architecture: 8 CPU variant : 0x0 CPU part : 0xd08 CPU revision : 3
と表示されました。ARMのドキュメントを検索すると次のページがヒットしました
ARM Information Center
このページ書かれている内容から、
CPU implementer : 0x41 => ARM Limited. CPU part : 0xd08 => Cortex-A72 processor.
ということが分かりました。Cortex-A72はARMv8アーキテクチャを採用しているCPUなので、問題なくマルチアーキテクチャビルドのコンテナが動くはずです。検証環境が整うことがわかったので今回は、
を実施してみようと思います。
前準備
exprimental featureの有効化
マルチアーキテクチャのコンテナビルドのためには experimental feature(試験的な機能)を有効にする必要があります。Docker Desktopでは、
のように config.json
を記載するエリアがあるので、 Use the Docker command line | Docker Documentation に記載されているJSONを入力します。
もしくは、ホームディレクトリ直下の .docker
ディレクトリに config.json
があるので、同様の内容を記載すればおkです(Linuxでも同じです)。
buildKitのインストール
今回使用する buildx
というプラグインは Moby BuildKit の拡張であるため、BuildKitのインストールが必要になります。
Macであれば
$ brew install buildkit
でもいいですし、公式に則った形でバイナリを /usr/local/bin
配下に設置してもいいでしょう。 buildctl
コマンドが通ればインストール完了です。
$ buildctl NAME: buildctl - build utility USAGE: buildctl [global options] command [command options] [arguments...] VERSION: v0.7.0 COMMANDS: du disk usage prune clean up build cache build, b build debug debug utilities help, h Shows a list of commands or help for one command GLOBAL OPTIONS: --debug enable debug output in logs --addr value buildkitd address (default: "unix:///run/buildkit/buildkitd.sock") --tlsservername value buildkitd server name for certificate validation --tlscacert value CA certificate for validation --tlscert value client certificate --tlskey value client key --tlsdir value directory containing CA certificate, client certificate, and client key --timeout value timeout backend connection after value seconds (default: 5) --help, -h show help --version, -v print the version
buildxプラグインの追加
次に buildx
というプラグインが必要になるので、 リポジトリ から最新のバイナリをダウンロードします。
ホームディレクトリにある .docker
ディレクトリに cli-plugins
というディレクトリを作成し、先程ダウンロードしたバイナリ docker-buildx
という名前で保存します。
更に実行権限を付与します。
$ chmod a+x ~/.docker/cli-plugins/docker-buildx
以上が終わって、docker buildx
コマンドが通れば利用可能です。
$ docker buildx Usage: docker buildx COMMAND Build with BuildKit 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 inspect Inspect current builder instance ls List builder instances 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.
ビルド
今回は、rubyで実行したら実行マシンの現在時間を出力するコンテナを利用します。Dockerfileは以下の内容を利用します。
FROM ruby:2.6.3 CMD ruby -e "puts Time.now"
普通にビルド&実行をしてみると
$ docker build -t multi-arch-norm -f multi_arch_Dockerfile . Sending build context to Docker daemon 2.048kB Step 1/2 : FROM ruby:2.6.3 ---> d529acb9f124 Step 2/2 : CMD ruby -e "puts Time.now" ---> Running in f6ca4f8d0f5b Removing intermediate container f6ca4f8d0f5b ---> 7a130a088630 Successfully built 7a130a088630 Successfully tagged multi-arch-norm:latest $ docker run -it --rm multi-arch-norm 2020-04-12 12:15:34 +0000
と問題なく実行出来ること分かりました。
ではマルチアーキテクチャモードでビルドを実行してみます。
docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t doridoridoriand/multi-arch:latest . multiple platforms feature is currently not supported for docker driver. Please switch to a different driver (eg. "docker buildx create --use")
どうやら現在の docker driver
ではマルチアーキテクチャのコンテナをビルドできないようです。指示に書いてあるとおり、 docker buildx create --use
を実行します。
$ docker buildx create --use $ ecstatic_roentgen
ランダムな名前でビルド用のコンテナが作成されました。
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 8ce5fa2759e8 moby/buildkit:buildx-stable-1 "buildkitd" 6 minutes ago Up 6 minutes buildx_buildkit_ecstatic_roentgen0
確かにbuildkitのコンテナが起動していることが分かります。
再度ビルドコマンドを実行します。
$ docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t doridoridoriand/multi-arch:latest . WARN[0000] No output specified for docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load [+] Building 133.1s (9/9) FINISHED => [internal] booting buildkit 7.3s => => pulling image moby/buildkit:buildx-stable-1 6.5s => => creating container buildx_buildkit_ecstatic_roentgen0 0.7s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => [internal] load build definition from Dockerfile 出力が長いので省略
無事ビルドができたようです。ただ、WARNには、
No output specified for docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load
と書かれていることから、コンテナのビルド結果はキャッシュにしか残ってないようです。利用するには --push
オプションでdocker hubにpushするか、--load
オプションでローカルに持ってくるかが必要になるようです。今回は後で別マシンでpullしたいので、docker hubにpushすることにしました。
pushオプションを付けて再度実行したところ、無事にpushされ、単一のイメージタグで、複数のCPUアーキテクチャが利用出来るようになっています。
以下が実際にpushしたdocker imageになります。 multi-arch | Tags
pull&実行
実際に動くか試します。まずはx86-64(amd64)PCで実施します。cpuinfoは
processor : 5 vendor_id : GenuineIntel cpu family : 6 model : 158 model name : Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz 長いので省略
となっています。コンテナをpullして実行してみます。
$ docker pull doridoridoriand/multi-arch:latest $ docker run -it --rm doridoridoriand/multi-arch:latest 2020-04-12 13:54:31 +0000
無事動きました。
次にARM(arm32v8)マシンで実施します。cpuinfoは
$ cat /proc/cpuinfo processor : 0 BogoMIPS : 166.66 Features : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid CPU implementer : 0x41 CPU architecture: 8 CPU variant : 0x0 CPU part : 0xd08 CPU revision : 3
となっています。コンテナをpullして実行してみます。
$ sudo docker pull doridoridoriand/multi-arch:latest $ sudo docker run -it --rm doridoridoriand/multi-arch:latest 2020-04-12 14:06:47 +0000
無事実行できました。
まとめ
Dockerがマルチアーキテクチャをサポートしたことで、IntelやAMDのCPU以外でもDockerコンテナを動かす敷居が低くなりました。AWSで言えば、c系インスタンスとa系インスタンスのハイブリット構成でAPIサーバーを構築することも不可能ではなくなったので、実際に採用するかは別として、アーキテクティングの幅が広がったかと思います。
機会があれば、ミドルウェア等で試してみようと思います。