Open5

docker のコンテナ実行の処理を読む

S. MiyataS. Miyata

前提

以下の条件で Dockerfile を用意する。

$ docker --version
Docker version 20.10.21, build baeda1f

$ cat Dockerfile
FROM ubuntu:16.04

COPY helloworld /usr/local/bin
RUN chmod +x /usr/local/bin/helloworld

CMD ["helloworld"]%

イメージのビルド

$ docker image build .

コンテナの実行

$ docker container run IMAGE_ID
Hello, World!
S. MiyataS. Miyata

コマンド実行内容は以下の関数を参照。

https://github.com/docker/cli/blob/f36e4b09497aa50b8e874172ce87e927f0c204a9/cli/command/container/run.go#L93

やっていることを箇条書きにすると

  1. イメージプルのオプションのバリデーション
  2. コンテナ作成時のオプションをビルド
  • ホスト OS の conifg を読み込む
  1. コンテナオプションをパースし、コンテナの設定を生成
  1. API クライアントのバージョンのバリデーション
  2. コンテナ実行
  • 一番肝要な実装だろう

次は 3. のパース処理、5. コンテナ実行の順に読む。

S. MiyataS. Miyata

パース処理

https://github.com/docker/cli/blob/88be16cb5bebac3451733ef4a0b003eefb1a4260/cli/command/container/opts.go#L320

こちらも順に処理を追う。

  1. MAC アドレスのバリデーション
  2. swappiness (スワップの優先度)のバリデーション
    • これはホスト OS の設定
    • /proc/sys/vm/swappiness 等で確認できる
      • mac で Docker 起動するときは HyperKit がホスト環境 になると思うがその設定が反映されるということだろうか?
  3. ボリュームのパース
    • この処理のテストを見てみたら、テストを実行するマシンの OS の種類によってボリュームの表記を変えていて面白かった。このあたり
    • strings.Cut という組み込みの関数を使って読み込んだボリュームを host とターゲットに分けている
      • strings.SplitN を使っていたが昨年置き換えたようだ。速度面でメリットがあるらしい: 参照
  4. tmpfs マウントの引数のマッピング ref
    • tmpfs マウントはコンテナ外部の一時的なファイルシステムにコンテナ実行時のデータを書き込むためのオプション
  5. エントリーポイントの上書き
    • エントリーポイントは Dockerfile で指定するコンテナで実行されるデフォルトのコマンドだが、docker run 実行時にオプションで指定することも可能で、ここではその上書きを行なっている
  6. publish オプションの取得
    • コンテナとホスト OS のポートをマッピングするオプション
  7. expose で指定されたポートを publish のポートにマージ
  8. デバイスマッピングのパース&バリデーション
    • コメントによるとデバイスのオプション指定のバリデーションが他のバリデーションと遅れてこの位置にくるのは、フラグをパースする際はまだホスト OS の種類が決定できていないからのようだ
    • OS のバリデーションは "linux" or "windows"見ている
  9. 環境変数の読み込み
  10. コンテナへのラベルの設定
    • ラベルを使うことでコンテナにメタデータを提供する
  11. PID, UTS の設定
  12. user, cgroup 名前空間の設定
  13. その他オプションのパース
    • 多すぎて省略してしまった...
  14. ヘルスチェック周りのオプションが指定されていた場合、設定を生成
  15. コンテナ設定の生成
S. MiyataS. Miyata

コンテナ実行

https://github.com/docker/cli/blob/f36e4b09497aa50b8e874172ce87e927f0c204a9/cli/command/container/run.go#L122

//nolint:gocyclo でサイクロマティック複雑度の警告を抑制していることから複雑度が高いと推測される。

コンテナ生成

ここまでに生成されたコンテナ設定、ホスト、ネットワークの設定を元にコンテナを生成する。

OOM キラー

Linux のメモリ管理機能で、メモリ不足になった場合に実行中のプロセスを強制終了させる。

WIP