ローファイ日記

出てくるコード片、ぼくが書いたものは断りがない場合 MIT License としています http://udzura.mit-license.org/

suEXEC セキュリティモデルをベースにしたコンテナ起動時のバリデーションの提案

本稿は、第2回WSA研究会で発表した内容の予稿である。末尾に当日の質疑応答を追記している。

websystemarchitecture.hatenablog.jp

発表スライド

speakerdeck.com


著者: 近藤宇智朗 (GMOペパボ株式会社 / udzura !at! udzura.jp)

研究のあらまし

多くのコンテナランタイム[1]は、コンテナを作成するときにスーパーユーザ権限を必要とする。これはコンテナを作成する作業者がそもそも管理者である(=誰が操作できるか管理できる)場合と比べ、ホスティング環境のようにユーザにコンテナ環境を提供する場合には一層の注意が必要となる。

FastContainer[2]のような場合、ユーザのリクエストに応じて対応するコンテナを立ち上げる。したがって、Nginxなどのウェブサーバがコンテナを起動することになるので、Nginx自体が一定の権限を持っていることが求められる。万が一、不正なクエリなどにより権限を持ったNginxから任意のコンテナを立ち上げ可能となった場合、危ない。

DockerdのようにコンテナランタイムのためのHTTP APIを提供している場合でも、そのAPIデーモンをrootで動かしている場合などでは、同様の問題は考えられる。例えばパターンとしては、稀であろうがDocker HTTP API自体のバグや運用上のパスワード忘れなどのミスが考えられる。

一般にUser Namespaceを用いることで非特権ユーザでコンテナを作成することは可能であるが、非特権ユーザを使う場合であっても後述のsuexecプログラム同様にset-user-id rootされたバイナリが必要となる[3]。

ここで、いわゆる仮想ホスト方式を採用したWebホスティングの基盤の場合、suEXECを利用することで利用者ごとの独立性(この場合、あるユーザの領域が他のユーザからアクセスできない、などの性質)や、ホストのシステム領域へのアクセスができないことを担保することができる[4]。具体的には、ある仮想ホストに紐づくアクセスから実行されるCGIが、apacheのシステムユーザとは別かつドキュメントルートごとに別々のユーザとなって実行されるようになる。こうすることで(sshで別々のユーザとしてログインしているように)プログラムから他のユーザのドキュメントルートや、システム領域への操作ができなくなる。

一方、そのような挙動を実現するために、suexecプログラムはset-user-id rootがされている。これはsetuid/gidを内部で呼び出すために必要な権限であるが、同時に多くの権限を実行バイナリに与えてしまう結果となる。

そのためsuexecプログラムを実行するために様々な制約が課せられている[5]。suexecプログラムはこれらのチェックリストのうち、一つでも満たさないものがある条件においては起動せず、システムに監査ログを吐き出す。

このように仮想ホスト方式において一定の運用実績があるsuEXECセキュリティモデルを、コンテナの実行時の制約に転用できないかということを提案する。

前提(1) - コンテナ環境をユーザに提供するにあたり、望ましくない操作について

作成したコンテナ環境をユーザに提供するような場面(ホスティングサービスの提供)を考える。例えばsshdなどのデーモンをコンテナ内部に立ち上げてログインを許可する、APIを用いてアタッチを可能にする、といった形が考えられる。この場合利用者は、アプリケーションのデプロイメントやその他の作業などを実施するために一定の操作の権限が与えられるはずである。その一定の操作の権限の中で、望ましくない操作ができてしまうとホスティングサービスの提供者としては問題となる。望ましくない操作の種別を4つにまとめ、それぞれを課題1.〜課題4.とする。

  1. コンテナの内部から、コンテナをホストしている親のOSに「脱獄」ができる場合
  2. コンテナの内部から、コンテナの「外」が見えたり操作できる場合。コンテナをホストしているOSの情報、同一LANにある秘匿したいホストの情報など
  3. コンテナの内部について、サービス提供者が意図しない設定変更やファイルの操作ができる場合
  4. コンテナの起動時に、サービス提供者が意図しないコマンド、引数、権限での起動をされる場合

課題1.に関しては利用・提供形態に限らず、コンテナがコンテナとして独立環境を提供されていると言えるために、そもそも守られるべき点であると考えることもできる。

次に2.と3.に関しては、特にホスティングサービスの提供において、「操作・閲覧できるべき内容」と「操作・閲覧できてはならない内容」の切り分けをしなければならないため、問題となる。この判断基準は、PaaSのようにウェブアプリケーションをホストするのみの場合、VPSに近い環境を提供したい場合、など異なってくる部分もあるが、いずれにせよサービス提供者が意図した切り分けの基準を確実に適用でき、抜け道を作ってしまわないような技術的な仕組みが求められる。

また4.に関しては、FastContainerアーキテクチャを利用する場合や、FaaS[6]であったりCIサービス[7]でコンテナを作成するような場合のように、必要に応じて起動するようなコンテナでは重要になってくると考える。すなわち、ユーザの何かしらの操作にコンテナの起動というシステムのイベントが強く結びついており、管理者の範囲外でのコントロールができるため、その部分に瑕疵があると望ましくない結果につながるであろう。

ところでホスティングサービスでない、一般のウェブサービスなどにおいても、例えばOSコマンドインジェクションであったり、Webシェルのアップロードであるような脆弱性を契機とした攻撃が考えられる。そのような攻撃が成功した場合、コンテナに対するユーザの操作権限はホスティングssh環境を提供しているような場合とほぼ同等となる。したがって本原稿の問題意識はホスティングサービス以外の条件であってもにも通じる。

前提(2) - コンテナにおけるセキュリティ強化の仕組みの整理

前提(1)に関連して、それぞれの課題との関係を示しつつ、現在のコンテナランタイム、あるいはコンテナオーケストレーションのレベルで採用されているセキュリティ機構をまとめる。

a) Kernel User Namespace

Linuxカーネルには名前空間という仕組みがあり、これはホスト名などのように本来OSグローバルに存在するリソースについて、OS内部で名前空間を作成し、複数を存在させ使い分けできるようにする機能である[8]。これはコンテナにおける基本技術と言える。その中で、OSのユーザとグループIDをホストに対して独立に管理することが可能なUser Namespaceが存在する。

具体的には、ホストから見た特定の1以上のユーザIDを、その名前空間から見たユーザID=0、rootユーザーとして扱うことができる(UID Mapping)。当該名前空間の中では、そのrootユーザはrootユーザとしての権限を持ち、コンテナ内部の操作が自由にできる。さらにホストから見た特定の範囲のユーザIDを、そのまま名前空間の中でシフトして利用することができる。

なお、ホストから見て指定された範囲の外側にあるユーザIDは、 nobody として扱われる。その名前空間の中では nobody の所有するファイルのオウナーになる事は何人たりとも出来ない。

また同等の仕様がグループIDについても存在する。

img-uid-mapping.png

図1: UID Mappingの図示

本機構は、コンテナ内部のrootと外部の本物のrootを分離することができるので 課題1.,2. に有効である。一方で原則としてコンテナの中ではrootであるので、3.に関しての効果は小さい。ただし、操作されたくないファイルの所有者をnobodyにし、UNIXパーミッションとしてothersに対してREAD権限のみを与える等の事はできる(そうすると、rootが読めるけど書き込みできないファイルが作成できる)。

b) Kernel Capability

Linuxには、スーパーユーザ権限を分割し、その一部を付与あるいは剥奪することができる機構がある[9]。その分割されたそれぞれをKernel Capabilityと呼ぶ。現在のカーネル 4.16.5 においてはスーパユーザ権限は 0 ~ 37 の38権限に分割されている(https://elixir.bootlin.com/linux/v4.16.5/source/include/uapi/linux/capability.h)。

コンテナにおいては、例えばDockerにおいてrootユーザーに与えられている権限が非常に限定されていることが知られている[10]。特にchrootなどの実行を禁止できるため、課題1.の対策となるし、例えばtcpdumpを実行する権限を剥奪したり、ファイルオウナーを変更する権限を剥奪することもできるので、課題2.、課題3.への対策にも応用することができる。

逆に、コンテナの特定のバイナリに、システムに必要な一部のFile capability(こと通常ユーザで特権ポートを利用する CAP_NET_BIND_SERVICE )を付与することで、コンテナのinitプロセスの所有者をrootでなくすことも可能である。ただしファイルシステムによりFile capabilityをサポートしない点は留意したい。

c) Seccomp

Linuxには、特定のシステムコールの呼び出しを制限したり、ホワイトリスト形式で許可するものを絞ったり、あるいはトレース/ログ出力(カーネル4.15よりログ出力も可能になった)の契機とすることが可能である。この機構はseccomp(seccomp mode 2)と呼ばれる[11]。

本機構は概ねKernel Capabilityのように利用でき、Dockerにおいてchrootをはじめとした課題1.,2.,3.に有効である。

d) Mandatory Access Control(AppArmor)

Mandatory Access Controlは、UNIXの古典的なファイル/プロセスのオウナーに基づいた権限制御のさらに上層から、特定のファイルなどの操作権限をコントロールする機構である。

幾つか実装・手法があるが、プロセス単位でのポリシー適用となるAppArmorはコンテナとの相性が良いと考えられる。今回はAppArmor[12]の機能に絞って紹介する。

AppArmorはプログラムのファイル単位、もしくはプロセス単位でセキュリティプロファイルを適用することができる。セキュリティプロファイルの中では、そのプロセスに対して指定したファイルへの読み書き実行、ソケットやネットワークアクセス、Capabilityの発動などを禁止、または監査の指定をすることができる。

AppArmorのそれぞれのプロファイルには二つのモードがある。一つはenforceモードで、実際にプロファイル通り禁止操作を行う。もう一つはcomplainモードであり、禁止された操作をチェックしログに出力するが、禁止自体は行わないモードとなる。

#include <tunables/global>

profile test /usr/lib/test/test_binary {
    #include <abstractions/base>

    # Main libraries and plugins
    /usr/share/TEST/** r,
    /usr/lib/TEST/** rm,

    # Configuration files and logs
    @{HOME}/.config/ r,
    @{HOME}/.config/TEST/** rw,
}

図2: AppArmorのプロファイルの例[13]

この機構を用いると、コンテナ内部にrootであっても操作できない・閲覧できないファイルを作成することができる。したがって課題2.と3.に対して有効である。特定のバイナリ以外を実行不可能にすることも可能なので、課題4.に生かせるかもしれない。

e) Service Meshにおけるセキュリティ担保

コンテナ単一ではなく、コンテナ同士の通信においてもセキュリティを考える必要がある。Kubernetes等のオーケストレーション基盤を利用する場合、コンテナ同士の通信とそのルールの操作にあたる概念をサービスメッシュと呼んで層分けし、負荷分散やルーティング、トレーシング、障害時の切り離しなどのオペレーション要件をそのレイヤで実施することが提唱されている[14]。

サービスメッシュの機能として、大きくは以下の3点はセキュリティに関わるものであろう。

  • コンテナ内部の通信経路の暗号化
  • コンテナ同士のアクセスの制御。例えばWebアプリケーションコンテナ以外からはDBへのアクセスは直接させない、等。いわゆるIaaSのセキュリティグループのようなものを想像されたい
  • コンテナ同士、またはコンテナと外界の通信のトレーシング・異常検知

サービスメッシュ自体コンテナの外が存在することが前提となる概念である。従って主に課題2.の対策である。

f) Rootless/Unprivileged containers(Docker/LXC)

コンテナランタイムを利用してコンテナを作成するには一般に特権が必要である。ただし、条件によっては特権がなくともコンテナを作成可能である。そもそも、コンテナプログラム自体にset-use-id root(単にsetuidとも呼ぶ)を行うことで、非特権ユーザによるコンテナ作成でも、フルの機能を持ったコンテナを作ることができる。ここではそれ以外のアプローチを紹介する。

LXCにおける非特権コンテナ[3]は知られた例である。LXCは、User Namespaceの作成には特権が不要であること、そのUser Namespaceでのrootはコンテナ内部での特権を持つことができることを利用して、非特権ユーザであってもコンテナを作成できる。

ただし、一部の操作はどうしても特権が必要となる。具体的にはユーザID/グループIDのマッピングの作成に関する操作と、ネットワークに関する操作であり、それらの操作を単一で実行するプログラムをそれぞれ用意し、バイナリにsetuidを行うことで安全な非特権ユーザでの操作を実現している[3]。逆に言うと、非特権とはいえsetuidされたバイナリが一部に必要となり、またコンテナ機能の進化やカーネルの変更により新たなsetuidバイナリが必要になる可能性がある。

また、Mobyプロジェクトなどのコミッタである須田氏により、特権がなくともruncやcontainerdを経由したコンテナ作成操作を可能にする実装が提案されている[15]。この実装には、Network Namespaceを分離する際にvethを使えずtapを利用せねばならないなどの課題があることが言及されている。

なお、これら非特権のコンテナ作成自体は、コンテナそのものの権限コントロールではなく、コンテナを起動するプログラムの権限コントロールと考えられる。コンテナを起動するプログラムやデーモンに不要な特権が付いている場合、コンテナあるいはコンテナ以外のプログラムを意図しない形で走らされるなど、攻撃への危険度が増大する。従って非特権コンテナ等の利用は課題4.の対策の一環と考えられる。

それぞれの位置付けと考察

上述した機構のうちa)〜d)はカーネルの機能を利用しており、コンテナのinitプロセスが何であるにもかかわらず汎用的に利用できるものであり、主に課題1.と3.をカバーする。

e)はコンテナがただ一つの場合は問題になりにくいが、コンテナを実際に利用する際は複数のコンテナの相互作用が必要であるため、課題2.への対応が必要となる。実際は相互作用そのもの(オーケストレーション層)のコード化の一部として、セキュリティに関するコードが組み込まれることとなるだろう。

課題4.は場面によっては問題とならないが、先述した通り「外部のユーザの操作によりコンテナの起動がコントロールできる場合」は考慮する必要がある。f)により一定の対応が可能である。

img-container-security-env.png

図3: コンテナにまつわるセキュリティ機構の位置付け

提案する内容

今回は特に前提(1)における課題4.への対策を強化する意味で、suEXECセキュリティモデル[5]をベースとしたコンテナ起動時のバリデーションを提案する。

suEXECセキュリティモデルとは、Apache HTTPサーバがCGIあるいはSSIを実行する際に、Apache自体のユーザ ID とは 異なるユーザ ID で実行する際に考慮しているモデルである。Apacheは、自身が立ち上がっているユーザと同じ権限でCGIプログラムなどを実行するのが通常であるが、一方で仮想ホストのように複数のユーザーにホスティング環境を提供する場合、あるユーザと別のユーザの権限が分離できていないと覗き見などの問題がある。そのため、仮想ホストに紐づくユーザごとの権限でプログラムを実施することで、それぞれの仮想ホストの独立性を担保する。なお、場合によりchroot操作なども組み合わせている。

ここで、一般ユーザでApacheを立ち上げた場合は、そのような操作を実行するにはset-user-id rootされたsuexecバイナリを経由しないと実行できない。set-user-id rootされたバイナリには必要以上の特権が付与された状態であるので、不要な越権操作を行わないよう幾つかの権限などのチェックが入り、全てを通過したプログラムのみが実行されるような仕組みがある。

コンテナの実行モデルにおけるコンテナランタイムの前段プログラムの扱い

コンテナの場合、実運用ではコンテナランタイムを実行する契機となるイベントを受け取るデーモンが存在することが多い。

例えばFastContainerにおいては、リクエストを受け取るためのHTTPDが必要で、そのHTTPDが内部でコンテナを起動するモデルが考えられる。具体的実装として、Nginxとngx_mruby、Haconiwaの組み合わせが存在する[2]。また、Dockerにおいてはruncに対するDockerdがその役割を行う。

img-container-front-prog.png

図4: FastContainerとDockerでの前段プログラムの比較

これらの前段のデーモンは本来rootユーザ以外で立ち上がることが望ましい。そのためコンテナは非特権コンテナを利用したいが、先述した通りいずれにせよどこかでsetuidされたバイナリを利用するか、一部機能を制限する形のコンテナを利用することになる。コンテナランタイム自体をsetuidして利用する場合は機能制限の問題は起こらないが、同時にsuEXECセキュリティモデルのような権限の検査を組み合わせることはセキュリティ強化の観点で有効であると考える。

なお、一部のバイナリのみをsetuidして利用する場合はランタイム自体の場合と比べ課題4.の危険は軽減されるが、稀ではあるが任意コード実行などの脆弱性をそのバイナリ自体が突かれる状況も考えられる。よって多重のセキュリティモデルを仕掛けることは有効である。

suEXECセキュリティモデルの一覧

suEXECセキュリティモデルの20項目について、Apacheの当該ドキュメント [5]より引用する。

  1. wrapper を実行しているユーザはこのシステムの正当なユーザか?
  2. wrapper が適切な数の引数で呼び出されたか?
  3. この正当なユーザは wrapper の実行を許可されているか?
  4. 対象の CGI、SSIプログラムが安全でない階層の参照をしているか?
  5. 対象となるユーザ名は正当なものか?
  6. 対象となるグループ名は正当なものか?
  7. 目的のユーザはスーパーユーザではないか?
  8. 対象となるユーザ ID は、最小の ID 番号よりも大きいか?
  9. 対象となるグループはスーパーユーザのグループでは ないか?
  10. 対象となるグループ ID は最小の ID 番号よりも大きいか?
  11. wrapper が正常に対象となるユーザとグループになれるか?
  12. CGI/SSI プログラムが置かれているディレクトリに移動 (change directory) できるか?
  13. ディレクトリが Apache のドキュメントツリー内にあるか?
  14. ディレクトリを他のユーザが書き込めるようになって いないか?
  15. 対象となる CGI/SSI プログラムは存在するか?
  16. 対象となる CGI/SSI プログラムファイルが他アカウントから 書き込めるようになっていないか?
  17. 対象となる CGI/SSI プログラムが setuid または setgid されていないか?
  18. 対象となるユーザ/グループがプログラムの ユーザ/グループと同じか?
  19. 安全な動作を保証するための環境変数クリアが可能か?
  20. 対象となる CGI/SSI プログラムを exec して実行できるか?

具体的なコンテナでのバリデーション等との対応

このセキュリティモデルをコンテナに適用するにあたり、CGI等とコンテナランタイムの性質の違いも鑑みて大きく3種類に分類し、対応付けた。また対応付けの際に、実装の都合を鑑みて近似するバリデーションをまとめてある。それぞれについて以下に掲示する。

バリデーションとして選択的に処理すべきもの

これらのバリデーションはコンテナランタイム自体がsetuidされていない時には、スキップしても構わないものとする。

バリデーション内容 対応するsuEXECモデルの番号
コンテナランタイムの設定ファイルと、コンテナランタイム自身のオウナーが一致するか(不正確認) 2.
コンテナランタイムの設定ファイルはホワイトリストで許可されたファイル名とマッチするか(不正確認) 2.
コンテナランタイムを実行するユーザがホワイトリストで許可されたユーザであるか 3.
rootfsやその内部が適切な権限運用となっているか。具体的には、initプログラムがrootfsの配下にあるか(symlinkであるかどうかも含め検査)、ディレクトリを他のユーザが書き込み可能になっていないか、initプログラムが他のユーザから書き込み可能になっていないか 4.、14.、16.
コンテナのinitプログラムを実行するユーザ/グループが正当であるか。無効の場合、コンテナ内部の/etc/passwdなどで名前引きできないIDのユーザになれる 5.、6.
initプログラムをスーパーユーザ/グループで実行していないか。 7.、9.
initプログラムを動かすユーザは最小のユーザID/グループIDよりも大きいか 8.、10.
rootfsが、指定したrootfs poolディレクトリの配下に存在するか。symlink含め検証する 13.
initプログラムはホワイトリストにない環境変数をセットされていないか 19.

エラーとして処理すべきもの

これらのバリデーションはオプションにかかわらずエラーとして処理するものとする。

バリデーション内容 対応するsuEXECモデルの番号
コンテナランタイムを実行するユーザ/グループが正当であるか 1.
コンテナランタイムを用いてコンテナのinit実行者として指定したユーザー/グループになれるか。具体的にはランタイムがsetuidされているかなど 11.
rootfsが存在しているか、chrootで移動できるか 12.
initプログラムは存在するか 15.
initプログラムに実行権限はあるか 20.

コンテナの運用の性質上、実装すべきかどうか検討が必要なもの

以下の2条件については運用上の問題が考えられるため、今回の提案では対応すべきものから除外する。

バリデーション内容の候補 検討の内容 対応するsuEXECモデルの番号
initプログラムがsetuid/setgidされていないか 現実的には「initプログラムが他のユーザから書き込み可能になっていないか」で防げるであろうこと、そもそもシェルのようなプログラムがinitとなる場合があるので厳密に防ぐのが難しいであろうと考えられる 17.
PID=1のプログラムの所有者とPID=1のプログラムのファイルの所有者が一致するか これをコンテナの実行上に厳密に適用すると、例えばデーモンは特権ポートを使うため、通常プログラムのファイルがroot所有となっているなど、齟齬が起こる。通常ユーザの所有としてCAP_NET_BINDだけ与えるか?など検討する必要があり、アプリケーションやrootfsの制約が大きいだろう 18.

以上について、suEXECセキュリティモデルをベースとしたコンテナの起動時バリデーションの バージョン 0.2 とする。

実装の詳細方針

上記のように実装すべき分類を示したが、それ以外周辺を含む、詳細な実装の方針を示す。

まず、エラーとして処理すべきものに関しては、そもそもデフォルトでバリデーション通過しないと実行できないようにし、適切なエラーメッセージを表示する。

一方、「選択的に処理すべきもの」に関しては必要なビルド時オプションを指定するとその機構が有効になる。オプションが多いほど、そのコンテナランタイムで作るコンテナはセキュアになるし、少ない場合はコンテナランタイムで立ち上げ可能なコンテナの自由度が上がる。

運用の要件に応じて何を有効にするかについては組み合わせが可能であるべきだが、ビルド段階での組み合わせの指定という形をとる。これは、コンテナランタイムのプログラムに組み込まれ、外部から調整できないパラメータとすることで設定の抜け道を防ぐ意図がある。また、ホスティングサービスで利用するコンテナであれば作成されるコンテナの設定・用途はある程度の範囲内に収まると考えられるので、セキュリティに関する挙動の一部を組み込みにすることに大きな問題はないだろう。

進捗

Haconiwaというコンテナランタイムにおいて、先述したようなホスティング環境でのセキュリティ強化の目的でPull Request[16]を出している。

当該プルリクエストでの実装は「コンテナランタイムの設定ファイルと、コンテナランタイム自身のオウナーが一致するか」である。この検査をすることで、例えばnginxユーザが所有するHacofileではコンテナは作成できないので、nginxユーザの権限のみでは任意のコンテナを作成できる状況には陥らなくなる。実装の難易度に比べ堅牢性が大きく高まるので最初のサポートとした。

Haconiwaにおける実装の場合、ビルド環境がmrubyであるので、ビルドオプションをDSLで記述でき、十分記述性を高くすることが可能である点はメリットである。他実装であればYAMLなどの形式でも構わないだろう。

MRuby::Build.new do |conf|
  MRBGEMS_ROOT = "/usr/local/mrblib"
  toolchain :clang
  conf.cc.defines += %w(ENABLE_READLINE)
  conf.cc.include_paths << %w(/usr/local/include)
  conf.linker.library_paths << %w(/usr/local/lib)
  conf.linker.libraries << ['pthread']
  conf.gembox 'default'
  conf.gem File.dirname(__FILE__)
end

図5: mrubyにおけるビルドオプションDSL。定数のdefineなどを簡潔・動的に記述できる。Haconiwaも同等のものを利用する

今後の課題と展開

最初の課題としてそもそも具体的実装を作ることが必要であろう。本提案を元に、コンテナランタイムHaconiwaのビルドオプションとして実装に落とし込むことを考えている。同時に、「実装すべきかどうか検討が必要なもの」として今回の提案対象から除外した2条件についても考察が必要である。

その後は、Haconiwaを利用したホスティングサービスで順次導入していくことを考えている。実際の攻撃を防げるか、要件を想定より狭めるなど運用上問題がないか、あるいはパフォーマンスなどへの影響がないかなどを検証できればというところである。


参考文献


当日の質疑、意見、議論など

  • ハイパーバイザーについて、Kata ContainerやOSvなんかも関連していそう
    • Kata Containerは気になっていた。ただ、今回の手法はハイパーバイザーによる独立性の強化と両立しそう
  • 安全性の評価、どういうものがあるか、私気になります
  • Dockerの場合権限分離はUNIXユーザではなく、APIの認証とかそういう形だと思うので、ngx_mruby->haconiwaのような形のモデルと並べるのは誤解を生みそう
    • その通りで、単純に比較できるモデルではないと考えられそう
    • DockerのHTTPエンドポイントがイベント契機といいより、イベントを契機として汎用的なDocker APIが叩かれるイメージ。FastContainerをDockerでやる〜のような場合と比較するのが良いのではないか

第2回WSA研究会、そして研究とエンジニアリングのつながりについての所感は別エントリで。