第 6 章 Docker が切り開くソフトウェア開発の未来 131
6.7 Docker を活かすソフトウェア設計
Docker
コンテナを使用することで、実現できることの幅が広がる筆者のようなアプリケーションもあれば、そうでないアプリケーションもあります。
サーバサイドのソフトウェアの中でも、一度の「インストール」によって全体が
1
ホスト(もしくはすべてがシングルボトルネックの少数ホスト)に密結合される形で設計がなされる ことがあります。ここではこれを「モノリシック(一枚岩)*11な設計」と呼ぶことにします。
*11 英語でMonolithic。名詞形がモノリス(Monolith)です。『2001年宇宙の旅』との絡みで謎めいた黒い板のイ
サービス全体が
1
つのモノリシックな設計のもとに成り立っている場合、VM
を用いてそれ を管理するのは自然ですし、今後もこの方式のほうが一般的なままでしょう。VM
とIaaS
(Infrastructure as a Service
)と呼ばれる形態のクラウドサービスとの相性は 抜群です。現在のIaaS
はVM
を経由したハードウェアリソースの間貸しであり、モノリシッ ク設計と単一の仮想的なコンピュータはより親しい間柄にあります。水平スケーリングが難 しく垂直スケーリングに親和的、ともいえるかもしれません。そういったソフトはまたしばし ば管理者権限(root
)を期待するものですが、一方Docker
コンテナ内ではroot
はあまり喜ば れません*12。この「モノリシックなサービスを提供する、1
つの安定した実行環境」という発 想に、今後もソフトウェア業界が引っ張られ続けることは間違いありません。しかし、
Docker
コンテナを含む最近のソフトウェアを取り巻くツールの変化は、異なるアプローチによるソフトウェア設計の可能性を示唆しているように筆者には感じます。
具体的には、ソフトウェアを一枚岩として設計するのではなく、それを構成する各コンポー ネントを「マイクロサービス」というより粒度の細かいアプリケーションプロセスに分解し、
それらのマイクロサービス間をプライベートネットワークを用いた通信によって結合するこ とで、個別のサービスの提供主体の生存性や数の制約を乗り越える、という考え方です。
これまでも、関数やライブラリというコンポーネント化は一般的でした。小さいソフトを結 合させるという発想は、特に
Unix OS
では当たり前のように語られてきたトピックです。Docker
コンテナは、この考え方にこれまで実現できなかった柔軟性を提供します。ソフトウェア開発の発想が基本的な面で変わることはありませんが、「ソフトウェア自体を保持する 環境」についての考え方を見直すことで、分離と水平スケーリングをより自在に行えるように なります。
個別のコンテナでは、アプリケーションが依存するユーザ空間に属するライブラリを、自由 に選択することができます。連携するコンテナ間の
OS
やライブラリバージョンがずれてい ても問題にはなりません。通信するインターフェースさえ揃っていれば「ライブラリ呼び出 し」のように相手を呼び出せます。コンテナを相手の気づかない間に再起動させたり、バー ジョン間でインターフェースの互換性がある範囲でアップデートさせたりすることもできる はずです。コンテナ分離によって、個別のコンポーネントをより気軽に更新できます。単一のコンテナ がクラッシュしても、それを再起動させるコストはそれほどでもありません。最新版のコンテ
メージもあるのですが、元々は「分離しようのない1つのでっかい岩」のようなニュアンスのようです。
*12 前掲したhttp://www.slideshare.net/jpetazzo/docker-linux-containers-lxc-and-security
ナのどこかに不具合があれば、コンテナ上のソフトウェアを「ロールバック」すれば、サービ ス全体がダウンすることはありません。ソフトウェアスタックの動的な
A/B
テストをシステ ムに組み込み、統計的に結合テストをするといった発想も容易にできるようになるかもしれま せん。「アジャイル開発」といった表現に代表されるように、最近のソフトウェア開発は時間軸に 対して細粒度化しているため、その速度を落とさない設計開発が喜ばれます。マイクロサービ スに分けたコンテナを用いた開発の場合、それぞれのコンテナ毎に独立したイテレーション が可能になります。各コンポーネント(コンテナ)間のインターフェースが明確になることか ら、コンテナ毎のシステムテストを関数のユニットテストと同レベルの容易さで実装できま す。コンテナとマイクロサービスに基づく設計では、バグ発見時の問題の局所化と予防は一層 容易になるでしょう*13。
外部に公開する
IP
アドレスとポートが変わらなければ、バックエンドとなるコンテナの数 を増減させることで個別の部品(マイクロサービス)に大して水平スケーリングを適用できる 余地もあります。既存のコンテナ型アプローチと
Docker
を分けた要因の一つに、Docker Hub
と呼ばれるコ ンテナイメージの中央レポジトリの存在を挙げました。ここで述べてた世界観に基づいた場合、
Docker Hub
はマイクロサービスの配布を一手に引受け、サービスの再利用性と、集中化した人々の視線によるマイクロサービス選別のための見本市です。
Docker Hub
は、ソースコードと開発サイクルを掌握する、コンテナの世界におけるGitHub
のような存在と言ってもよいでしょう。
GitHub
がgit
を包含するのと同様、Docker
はコンテ ナを包含します。完成させたい「マクロ」*14なサービスのための「マイクロ」なコンポーネントを
Docker Hub
から取ってくる、というアプローチが考えられます。モノリシックなアプローチで、上記のような「柔軟」なソフトウェア設計を行うことは事実 上できません。少なくとも、その性質を手に入れるためにメリットに見合わないコストを払う 必要があります。
OS
ディストリビューションはライブラリにしばしば1
つのバージョンと セキュリティ修正を加えて依存関係も含めて管理しており、アプリケーション毎に自由にライ*13 ただしインターフェース設計が雑な場合でのデバッグは、場合によっては逆に難しくなります。境界を跨ぐ シームレスなデバッグ機構がないためです。
*14 「マクロ(Macro)」は英語で「大規模な」「巨視的な」を意味し、「マイクロ(Micro、ミクロ)」は「極小の」
です。「マイクロサービス」を組み合わせて大きなものを作るということで、ここでは「マクロサービス」と称 しています。「マイクロサービス」は流行用語(http://martinfowler.com/articles/microservices.html)ですが
「マクロサービス」は本章の独自表現と考えてください。「マイクロ(ミクロ)」と「マクロ」の対比は、IT以外 ではたとえば「ミクロ経済学」「マクロ経済学」といった形で登場します。
ブラリを選択できるわけではありません。
Ruby
のRVM
やPython
のpyvenv
を用いること で、特定のスクリプト言語の範囲内でバージョン管理を行えるようになっているものの、特に それぞれの言語を越えるライブラリを用いたりする場合、同じ課題に行き着きます。Docker
というソフトウェアが介在することで、アプリケーションサービスの分解点に考慮するべき新たな側面が生まれたのです。