Chapter 07

Docker について

ほげさん
ほげさん
2021.08.14に更新

この章の操作は Intel Mac もしくは ARM Mac で行なっています。

ARM Mac のターミナルは明示しない限り ARM64 ターミナルとします。

イメージ取得の動作を比較するときは、適宜イメージ削除を行っています。

ARM Mac の Docker 対応について

発表当初は「M1 Mac では Docker が動かないらしい」と言われていましたが、少し前に対応されました。
( 実際は Go の ARM 対応に依存していたとかなんとか? )

Rosetta の章で紹介した確認サイト でも M1 optimized ✅ になっています。

インストールしてコンテナの挙動を確認してみます。

イメージとコンテナについて

コンテナのアーキテクチャ

適当なコンテナでアーキテクチャを確認してみます。

Intel Mac
$ docker run -it alpine:latest uname -m
x86_64
ARM Mac
$ docker run -it alpine:latest uname -m
aarch64

同じコマンドを実行したのに、コンテナのアーキテクチャが異なっています。

イメージを確認すると、ID が違います。

Intel Mac
$ docker image ls
REPOSITORY    TAG       IMAGE ID        CREATED        SIZE
alpine        latest    d4ff818577bc    5 weeks ago    5.6MB
ARM Mac
$ docker image ls
REPOSITORY    TAG       IMAGE ID        CREATED        SIZE
alpine        latest    b0e47758dc53    5 weeks ago    5.6MB

イメージを詳しく調べると、Architecture が違うことが確認できます。

Intel Mac
$ docker inspect d4ff818577bc | jq -r '.[] | .Architecture'
amd64
ARM Mac
$ docker inspect b0e47758dc53 | jq -r '.[] | .Architecture'
arm64

コンテナのアーキテクチャが異なれば、違うイメージということですね。

使うイメージの決まり方

ARM Mac の x86_64 ターミナル の x86_64 シェルで同じコマンドを実行してみると、ARM コンテナが動きました。

ARM Mac ( x86_64 ターミナル )
$ uname -m
x86_64

$ docker run -it alpine:latest uname -m
aarch64

コンテナのアーキテクチャの自動選択は、ホストマシンのアーキテクチャに依存していると考えて良さそうです。 ( つまり常に ARM64 が選ばれます。)

イメージのアーキテクチャを指定する

docker pulldocker run には --platform というオプションがあります。

これを利用すれば ARM Mac で x86_64 のコンテナを使うことも可能です。

ARM Mac
$ uname -m
arm64

$ docker run -it --platform linux/x86_64 alpine:latest uname -m
x86_64

イメージ ID も Intel Mac と同じものになりました。

ARM Mac
$ docker image ls
REPOSITORY    TAG       IMAGE ID        CREATED        SIZE
alpine        latest    d4ff818577bc    5 weeks ago    5.6MB

$ docker inspect d4ff818577bc | jq -r '.[] | .Architecture'
amd64

こういうことですね。

イメージのアーキテクチャ一覧を確認する方法

方法の 1 つめは Docker Hub で確認する方法です。

イメージごとの OS/ARCH の項目で確認できます。

2 つめは docker manifest inspect を実行する方法です。

$ DOCKER_CLI_EXPERIMENTAL=enabled

$ docker manifest inspect alpine:latest

出力が少し多いので適当に整形します。

$ docker manifest inspect alpine:latest | jq -r '.manifests[].platform | if .variant == null then .os + "/" + .architecture else .os + "/" + .architecture + "/" + .variant end' | sort
linux/386
linux/amd64
linux/arm/v6
linux/arm/v7
linux/arm64/v8
linux/ppc64le
linux/s390x

同じ結果ですね。

ARM Mac で Docker を使う際の課題

Docker Desktop の ARM 対応が完了し、x86_64 コンテナも ARM64 コンテナも使い分けることが確認できました。

ARM Mac で Docker という仕組みを利用することの課題はあまり感じられません。

が、コンテナ 1 つ 1 つに注目した場合はかなり印象が変わります。

ARM64 イメージが必ず用意されているとは限らない

例えば Haskell のコンテナを使おうと思って docker pull をすると、ARM64 イメージが見つからないと言われました。

ARM Mac
$ docker pull haskell:latest
no matching manifest for linux/arm64/v8 in the manifest list entries

確かに提供されていないみたいです。

ARM Mac
$ docker manifest inspect haskell:latest | jq -r '.manifests[].platform | if .variant == null then .os + "/" + .architecture else .os + "/" + .architecture + "/" + .variant end' | sort
linux/amd64

ARM Mac に x86_64 イメージを持ってきても動くとは限らない

それならと x86_64 イメージを指定すると、期待した通りイメージは取得できます。

ARM Mac
$ docker pull haskell:latest --platform linux/x86_64

$ docker image ls
REPOSITORY    TAG       IMAGE ID        CREATED        SIZE
haskell       latest    02006a905c71    12 days ago    1.5GB

$ docker inspect 02006a905c71 | jq -r '.[] | .Architecture'
amd64

が、このコンテナを起動しても Haskell のビルドツール stack は動きませんでした。
( ホストマシンのアーキテクチャとイメージのアーキテクチャが違うという警告も出ています。)

ARM Mac
$ docker run -it haskell:latest bash
WARNING: The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested

> uname -m
x86_64

> stack -h
Killed

ARM コンテナに x86_64 と同じ構築をしても動くとは限らない

ARM コンテナの上で自分でインストールしても、いろいろ動きません。

ARM Mac
$ docker run -it ubuntu:latest /bin/bash

> uname -m
aarch64

> apt install haskell-stack
bla bla bla

> stack upgrade --binary-only
Control.Exception.Safe.throwString called with:
Binary upgrade not yet supported on arch: AArch64

一度コンテナを破棄して別の方法で入れ直そうとしてもインストールに失敗します。

ARM Mac
> curl -sSL https://get.haskellstack.org/ | sh
Detected Linux distribution: ubuntu
Sorry, currently only 64-bit (x86_64) Linux binary is available.

Haskell の ARM64 対応が進むのを待たなければならないようです。
( Haskell は Intel Mac を使っていた頃から Mac 自体にインストールしていたので、とりあえずは ARM Mac に x86_64 Haskell をインストールしました。)

整理

ARM Mac の上で動かす全ての x86_64 コンテナがうまく動かないのかはわかりません。
現に uname -m 程度なら動くことは先ほど確認できています。

ARM Mac
$ docker run -it --platform linux/x86_64 alpine:latest uname -m
x86_64

とはいえ、ARM64 向けのイメージが提供されていない場合は、それなりの茨の道を覚悟する必要がありそうです。

まとめ

  • Docker という仕組み自体は問題なく動く
  • ターミナルやシェルに関わらず、イメージは ARM64 のものが選ばれる
    • 明示的に x86_64 イメージを使う場合のみ --platform を使う
  • ARM64 のイメージがない場合は、困る

参考にした記事

https://dev.classmethod.jp/articles/docker-multi-architecture-image/