Skip to content

1-6. ランタイムのレイヤとエコシステム

コンテナランタイムの実用化

コンテナランタイムに求められる役割

コンテナを便利で実用的に扱いたいとなると、

  • どんなコンテナが立っているのか、外部から知りたい
    • プロセスを闇雲に探しても不可能/効率が悪い
  • 変更する先のルートディレクトリの中身を共通化して、同じ環境を再現したい
  • コンテナ (プロセス) は再起動で消えるので、再起動したら同じ設定でコンテナを立て直したい
  • 複数コンテナにまたがるネットワークが組みたい
  • もっと少ない設定項目で便利に扱いたい

などなど... 様々な要望が出てきます。

これらの要望があらかた叶い、コンテナが「使いやすい技術」になったのは、Dockerの登場が大きな転換点だったと言えるでしょう。

Dockerが成し遂げたこと

皆さんの中には、Dockerが世界初のコンテナランタイムだと思っている人も多いでしょう。しかし、それは大きな間違いです。

JailLXC等、2000年代までにある程度しっかりしたコンテナランタイムは誕生していました。
ただこれらはプロセスを隔離環境で動かすツールという扱いであり、セキュリティ面の長所はあれど、今のように大規模なデプロイに使うにはピースが欠けた状態でした。

その穴を埋めたのがDockerです。
Dockerが発表された当時、Dockerの中で実際にコンテナを作っていたのはLXCという前世代のコンテナランタイムでした。コンテナの作成に対して新しいことはしていなかったのです。
彼らが提供したのはコンテナの便利なAPIコンテナイメージという概念。
コンテナのルートディレクトリに配置したいファイル群をまとめて配布することにより、同じ環境軽量かつ大量に起動するための最後のピースが埋まったのでした。

コンテナランタイムの細分化

最終的にDockerは、libcontainerという独自のコンテナ作成機構を作り、それをデフォルトとしました。
Dockerはイメージの作成・管理から実際のコンテナ作成までを担う、巨大プロジェクトになったのです。

しかし、他社が次々とコンテナランタイムを出す中で、コンテナイメージコンテナ作成機構標準仕様を策定するOCI (Open Container Initiative) という団体ができ、libcontainerは切り出されruncになりました。

さらに、はじめDockerしかサポートしていなかったKubernetesが他のランタイムもサポートしようとする中、CRI (Container Runtime Interface) という仕様が導入されました。
CRIプラグインはruncのようなコンテナ作成ソフトウェアを使役し、デーモンとして便利なAPIを提供することが求められます。
Dockerもこれを受け、CRIプラグインに必要な機能を抜き出してcontainerdとして分離し、残った部分をmobyとして管理し始めたのです。

このような経緯で、現在のDockerは

  • moby (containerdより高レイヤーだった部分)
  • containerd (コンテナ管理デーモン)
  • runc (コンテナ作成ソフトウェア)

の3つを合わせて提供する形になりました。

ランタイムのレイヤ

以上の経緯でコンテナランタイムはレイヤ分割がされており、それぞれ以下のような名前と役割を持っています。

コンテナエンジン

  • Docker(moby)/Podmanなど
  • ランタイム全体を束ね、ユーザーが使いやすい機能を提供
  • コンテナイメージの作成が統合されていることもある
    • 作成はこれより下のレイヤには無い

Docker

Podman

高レベルランタイム (CRIプラグイン)

  • containerd/CRI-Oなど
  • デーモンとしてソケット通信ベースのAPIを提供
  • コンテナイメージを解釈し、低レベルランタイム用のファイルを用意
  • 複数コンテナにまたがるネットワークの管理
  • 低レベルコンテナランタイムに指令を出す

containerd

CRI-O

低レベルコンテナランタイム (OCIランタイム)

  • runc/youki/crunなど
  • 実際のコンテナ作成を担当

youkicrun

各レイヤの繋がり

これらのエコシステムは、全体として以下のような連関で成り立っています。

エコシステム

ここまでのことを踏まえ、このワークショップの冒頭に書いた「『docker run』コマンドを実行してからアプリケーションのプロセスが動き始めるまでにどんなソフトウェアがどんな役割を果たしているか」という質問への答えは以下です。

  • docker runが実行される
  • Dockerがcontainerdにコンテナ作成を指令
  • containerdがイメージをダウンロード
  • containerdがイメージを解凍
  • containerdがruncにコンテナ作成を指令
  • runcがプロセスを立て、コンテナに仕立て上げる

さあ、コンテナについてある程度理解できましたか?
いよいよここから実装パートに入っていきましょう!