Chapter 05

アプローチのパターン

ほげさん
ほげさん
2021.12.05に更新

エラーのパターンをざっと見たので、肝心のアプローチを整理します

問題をどうやって調べるか

異常なコンテナと直接箇所を特定する

docker build / docker run の場合は、まずターミナルの出力をちゃんと読みましょう

🤔 ちゃんとです

イメージが焼けないなら Dockerfile を読む

docker build が失敗するなら、Dockerfile を調べます

大抵の場合は Dockerfile の命令は

RUN ... && ... && ...

のように1行が長いので、次のように書き崩して範囲を絞るのも有効です

RUN ...
RUN ...
RUN ...

ベースイメージだけ持ってきて自分で Dockerfile の作業を再現するのも有効です

$ docker run -it centos:latest bash

# yum install ...
# ...
# ...
# ...

🤔 直接原因を可能な限り具体的に把握しましょう

コンテナが起動するなら手でいろいろ叩く

docker run が失敗するなら、実際に実行されたコマンドを調べます

Dockerfile が手元にあるなら CMDENTRYPOINT を確認します
Docker Hub で調べたり、image inspect でも良いでしょう

$ docker image inspect php:8.0 | jq '.[] | .Config | .Cmd'
[
  "php",
  "-a"
]

直接コマンドがわかったら、そのコンテナの bash などを起動して手でいろいろ試してみます

$ docker run -it php:8.0 bash

# php -v
PHP 8.0.13 (cli) (built: Nov 19 2021 21:47:48) ( NTS )

CMD の上書きが無視されてしまう場合は、

$ docker run -it mailhog/mailhog:latest sh
2021/12/05 13:00:43 Using in-memory storage
2021/12/05 13:00:43 [SMTP] Binding to address: 0.0.0.0:1025
[HTTP] Binding to address: 0.0.0.0:8025
2021/12/05 13:00:43 Serving under http://0.0.0.0:8025/
Creating API v1 with WebPath:
Creating API v2 with WebPath:

ENTRYPOINT を上書きしましょう

$ docker run --entrypoint sh -it mailhog/mailhog:latest

#

🤔 直接原因を可能な限り具体的に把握しましょう

Docker Compose の場合は

docker compose up -d --build みたいな呪文の意味を理解しましょう

docker compose xxx が失敗した場合は直接失敗した docker xxx を把握しなければなりません

image

image

🤔 やってくれてることがとても多いので、可能な限り直接の問題を正確に把握しましょう

Docker のログを見る

とにかくログを見ましょう、ログを見る方法はいくつもあります

コンテナ ID を調べて docker logs でも良いし

$ docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED         STATUS         PORTS                NAMES
89574b14572c   jboss/keycloak:15.0.0   "/opt/jboss/tools/do…"   5 minutes ago   Up 5 minutes   8080/tcp, 8443/tcp   busy_feistel

image

Docker Desktop でも良いです

image

🤔 ターミナルと Docker のログは情報の宝庫です、読みましょう

アプリケーションのログを見る

コンテナは起動したけど開発サーバが落ちてるなんてときは、コンテナ内のログを見ましょう

たとえば Keycloak のログが出る場所は、調べればわかります

$ docker exec -it 89574b14572c bash

# ls /opt/jboss/keycloak/standalone/log/
audit.log  server.log

🤔 エラーのパターンによって、適切なログを読みましょう

どうしよっかなフローチャート

ARM イメージがない場合は、僕は大体こんな感じで対応しています

さらっと個別に見てみましょう

強引に起動すれば動く

たとえば mysql:5.7 は ARM イメージがなく

image

起動しようとしても相手をしてくれません

$ docker run -e MYSQL_ROOT_PASSWORD=secret -p 3306:3306 -it mysql:5.7
docker: no matching manifest for linux/arm64/v8 in the manifest list entries.

$

Mac が ARM なので自動で ARM イメージを docker pull しようとしているからです

強引に --platform で Intel イメージを明示すると...

$ docker run --platform linux/amd64 -e MYSQL_ROOT_PASSWORD=secret -p 3306:3306 -it mysql:5.7

$ mysql -h 127.0.0.1 -P 3306 -u root -psecret

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

稀にこの方法であっさり解決することがあります[1]

🤔 とりあえず試してみる価値は大いにあります

バージョンを上げてもいい

あるバージョンを境に ARM イメージが用意されることがそこそこあります

たとえば mysql/mysql-server:5.7 は Intel イメージしかありませんが

image

mysql/mysql-server:8.0 は ARM イメージもあります

image

🤔 実案件だと難しいかもしれませんが、とりあえず動けば良いみたいな場合は結構アリです

別のリポジトリがある

たとえば mysql:8.0.0 は Intel イメージしかありませんが

image

( さっき見た通り ) mysql/mysql-server:8.0 は ARM イメージもあります

image

Optimized MySQL Server Docker images.
Created, maintained and supported by the MySQL team at Oracle

と書いてあり Pulls もすごいので、これになら安心して乗り換えても良さそうです

🤔 信頼できそうなリポジトリであれば、結構アリです

個人リポジトリでもいい

jboss/keycloak:15.0.0 も Intel イメージしかありません

image

だめもとで Docker Hub を keycloak で検索すると、そこそこの数の個人リポジトリがあります

image

🤔 リスクを自分で判断できるのであれば、まぁアリです

バージョンが一致しないかもしれない

たとえば1つめに見えている alemairebe/keycloak は、10 ~ 14 しかありませんでした

Intel イメージがない

見えている3つとも、ARM イメージしかありませんでした

Intel / ARM 混在のチームで使うことができなくなります

品質が不明

Dockerfile が公開されていればいいですが、そうでない場合は心理的に若干不安かもしれません

Dockerfile を大きく変えてもいい

自分でイメージを焼き直すのが最後の手段です

自分でいろいろ入れる

Intel / ARM 混在の状況であるなら、まず両対応のイメージをベースにします

image

これに必要なものを自分で入れていき Dockerfile を作り出せば良いです

e.g. Java を入れるための Yum リポジトリの追加に uname -m を使う

RUN echo "baseurl=https://adoptopenjdk.jfrog.io/adoptopenjdk/rpm/rhel/8/$(uname -m)" > /etc/yum.repos.d/adoptopenjdk.repo

e.g. Node の tar を取得する URL に uname -m を使う

RUN curl https://nodejs.org/dist/v16.12.0/node-v16.12.0-linux-$(uname -m | sed 's/aarch64/arm64/' | sed 's/x86_64/x64/').tar.gz --output node.tar.gz

要するにアーキテクチャに即したものを使うようにイメージを作れば良いのです

uname -m の結果がそのまま URL になるならそれで良いし

https://adoptopenjdk.jfrog.io/adoptopenjdk/rpm/rhel/8/$(uname -m)

image

調整が必要なら適当に sed でもすれば良いです

node-v16.12.0-linux-$(uname -m | sed 's/aarch64/arm64/' | sed 's/x86_64/x64/').tar.gz

image

自分でビルドしてしまうという手もあります[2]

git clone https://github.com/hashicorp/terraform-provider-aws.git
cd terraform-provider-aws
make

いずれにせよ、ssh 先に手動インストールをするのと同じ感覚です

🤔 この手段がスキル的にもチーム的にも可能なら、まぁこれが一番確実です

先行事例を探す

A と B ができるイメージを作りたい、けど両方全部自分で対応するのは大変だ

そんなときは Docker Hub で A や B の Dockerfile を探すのもアリです

e.g. このイメージどうやって作ったのか参考にしたいなぁ

image

なんてときは、GitHub を同じリポジトリ名で探してみると見つかったりします

image

本家 ( keycloak/keycloak-containers ) の Fork Repository のようですね

参考 Dockerfile を一気に2つゲットです

また、あるイメージのレイヤーを参考資料にしてみるのも良いでしょう[3]

$ docker image history php:8.0
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
26c812e2792f   2 weeks ago   /bin/sh -c #(nop)  CMD ["php" "-a"]             0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  ENTRYPOINT ["docker-php-e…   0B
<missing>      2 weeks ago   /bin/sh -c docker-php-ext-enable sodium         17B
<missing>      2 weeks ago   /bin/sh -c #(nop) COPY multi:a00980ff863125d…   6.86kB
<missing>      2 weeks ago   /bin/sh -c set -eux;   savedAptMark="$(apt-m…   107MB
<missing>      2 weeks ago   /bin/sh -c #(nop) COPY file:ce57c04b70896f77…   587B
<missing>      2 weeks ago   /bin/sh -c set -eux;   savedAptMark="$(apt-m…   11.2MB
<missing>      2 weeks ago   /bin/sh -c #(nop)  ENV PHP_SHA256=cd976805ec…   0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  ENV PHP_URL=https://www.p…   0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  ENV PHP_VERSION=8.0.13       0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  ENV GPG_KEYS=1729F83938DA…   0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  ENV PHP_LDFLAGS=-Wl,-O1 -…   0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  ENV PHP_CPPFLAGS=-fstack-…   0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  ENV PHP_CFLAGS=-fstack-pr…   0B
<missing>      2 weeks ago   /bin/sh -c set -eux;  mkdir -p "$PHP_INI_DIR…   0B
<missing>      2 weeks ago   /bin/sh -c #(nop)  ENV PHP_INI_DIR=/usr/loca…   0B
<missing>      2 weeks ago   /bin/sh -c set -eux;  apt-get update;  apt-g…   249MB
<missing>      2 weeks ago   /bin/sh -c #(nop)  ENV PHPIZE_DEPS=autoconf …   0B
<missing>      2 weeks ago   /bin/sh -c set -eux;  {   echo 'Package: php…   46B
<missing>      2 weeks ago   /bin/sh -c #(nop)  CMD ["bash"]                 0B
<missing>      2 weeks ago   /bin/sh -c #(nop) ADD file:4203242b2b09a6523…   74.3MB

🤔 狙いをつけていろいろ探してみましょう

ここまであがいてだめだったら、別々の道に進む

  • チームのみんなが使っている Intel イメージとは別に ARM イメージを作る
  • 自分だけ Docker を使わない

など、共通の資産を使わない選択肢もどうしてもあるとは思います

🤔 おすすめはしません、最終手段です

ぶっちゃけた話

Intel の Mac を持っている人はしばらくは手放さないのが一番の「対応」です

常に即時 ARM Mac でも動くように対応する時間が取れるわけでもありませんしね

脚注
  1. docker-compose.yml や Dockerfile でも明示可能です ↩︎

  2. コマンドは抜粋です see https://github.com/hashicorp/terraform/issues/27257 ↩︎

  3. --no-trunc オプションで横を切り捨てずに出力できます ↩︎