最近、コンテナをメンテすることがあるので、どのように考えているかを整理して書きました。
tl;dr
- readme に
make command
と記載がある場合はMakefile
を見る Makefile
内にdocker-compose
またはdocker compose
と記載がある場合はdocker-compose.yml
を見るdocker-compose.yml
の中にbuild
と書いてある場合はDockerfile
を見るDockerfile
を見る場合は、FROM
の定義とコマンドを見る- ログを見る。ログを見る。とにかくログを見る。
コンテナを扱ううえで最低限知っとかないといけない概念
古い言い方かもしれませんが、コンテナとは、コンテナを実行するPCから見れば、ただのプロセスであり、実行プログラムです。それは、 nodejs
でも nginx
でもいいです。 gcc
でもいいです。何かしらの入力を受け付け、何かしらの出力を行うプロセスです。
443 ポートに HTTPS 接続を行い、 GET
を行えばHTML文書を返してくれるし、あるファイル群をマウントしているディレクトリでビルドを実行すれば、コンパイル結果を記録してくれます。
あるプログラムに何か仕事をさせたい場合は、接続を行うポートや、読み込ませたいファイルが必要となります。
ポート
プロセスの中では、コンテナを起動したPCのカーネルを利用して、いわゆるOSが動いています。この辺の仕組みはどうでもいいので、コンテナの中ではOS、例えばLinuxディストリビューションが動いていると思ってもらえばいいです。
OSが動いているので、コンテナ内のOSは、コンテナ内のアプリケーションの動作のためにポートを管理しています。 nginx
を起動すればコンテナ内のOSは 443 ポートで待ち受けます。
ここで、PCを動かしているOSと、コンテナ内のOSで、別々のポート管理の仕組みが働いていることがわかります。この2つの橋渡しをするのが docker-compose.yml
の ports
であり、 docker コマンドであれば -p
オプションです。
docker-compose.yml
の ports に8443:443
とし、PCのブラウザで https://localhost:8443/
とアクセスすれば、コンテナ内の https://localhost
に接続したものと同等になります。
マウント
コンテナ内のOSは、アプリケーションを実行するための最低限のファイルだけが置かれることが多いです。
実際は、例えばコンパイルしたい場合は、PCのあるディレクトリをコンテナ内のどこかにマウントしたくなります。これが volumes
とかで書かれていることです。これはPCのディレクトリをコンテナ内のここでアクセスできるというだけのことです。
細かい設定はありますが、本当にこれだけのことです。信じてください
これらのポートを接続する、PCのファイルをマウントする、という概念さえわかれば十分です。実装は iptables
で行われているとか考えなくていいです。
とにかく、PCとコンテナ内はポート、およびマウントした場所を通じてやり取りをする、ということがわかればOKです。
リポジトリで見るファイル
Makefile
、 docker-compose.yml
、 Dockerfile
を見ます。
Makefile
環境によっては、 docker compose
コマンドなどを make start
などと定義し、開発を容易に行うためのコマンドが用意されていることがあります。
この謎のコマンド定義は、 Makefile
ファイル内に記載されています。
Makefile
とは何か知らなくても、あなたが最低限、コマンドラインを実行する方法を知っていれば、読めば何となくわかります。
気合で読んでください。読めばわかります。
例えば make start
などと書いてある場合は、どこかに start
という記述があり、そこから docker compose up
といった記述が見つかるかもしれません。
そこまでわかれば、「ああ、make start
というものは、実はこれらのコマンドを実行しているだけなんだな」というのがわかります。
怖がらず、Makefile
を一行一行読んでください。 make
は、 Makefile
に書いてあるコマンドしか実行していません。
docker-compose.yml
雰囲気で読めます。頑張ったら読めます。変数っぽいものは変数だし、名前っぽいのは名前です。
ただし、 build
と書かれている部分だけは注意が必要です。相対パスで指定されている Dockerfile
を読み込んでコンテナを作るってわかれば100点です。つまりは docker build
と同じです。
Dockerfile
ここまでくれば、あとはもう怖いものは無いです。 Dockerfile
には、あるイメージから実行したいコマンドがつらつらと書かれているだけです。愚直に上から読んでいきましょう。何も特別なことはありません。
FROM
が書かれている部分だけは、Dockerfile
の内容の外に実行内容が書かれているので、 "docker (FROMの内容)" とかで検索しましょう。ただし、そこまで必要になることはほぼないです。
ログ
ここまでで何となくコンテナのやりたいことが理解できたので、 make start
して見ましょう。この文書を見ているあなたは、何かしらコンテナで不調が起こっていることの原因を知りたいはずです。
その答えは、ログに全て書かれているはずです。コンテナ内のWebサイトにアクセスしてエラーが出る場合は、ログが出力されるはずです。もし、 docker-compose.yml
に docker compose up -d
のように -d
オプションがついているなら、 docker compose logs -f
などでログを出力させるか、一時的に -d
オプションを削除して実行しなおしてみましょう。
それでもログが出力されない場合は、 Dockerfile をコミットした人に聞きましょう。もしくは、標準出力を抑制するような記述がないか、 Dockerfile 内をくまなく探しましょう。
ログを見つけられたら、Google でエラーメッセージで検索しましょう。だいたい、あなたの直面したエラーは、だいたい人が答えを書いています。
不運にも答えが見つからない場合は、GitHub で検索してみましょう。そして 3 days や 2 week ぐらいの issue が見つかったあなたは幸運です。コンテナ内で使われているアプリケーションが、更新によって、直近で breaking change が発生してることを見つけられた英雄になれます。 issue に記載のワークアラウンドなどを頼りに Dockerfile の内容を修正し、コンテナ環境を直していきましょう。
参考文献
https://docs.docker.jp/compose/reference/up.html
https://docs.docker.com/engine/reference/commandline/compose_logs/