Dockerを理解するための8つの軸
「Docker」というキーワードが、サーバーまわりのキーワードとして定着しつつある。その一方で、触ったことのある人以外からは、「Dockerってよくわからない」「コンテナーって昔からあるのでは?」という声も聞く。
Dockerは、それまでにあった要素技術を組み合わせることで、サーバーアプリケーションを実行する便利な方法を作り出したものだ。そのため、1つの要素技術を見ただけでは、新しさや全体像がわかりにくい。
そこでこの記事では、Dockerを触ったことのない人向けに、Dockerを8つの軸から説明する。なお、ここではDockerそのものを解説するわけではないので、ご了解願いたい。
1. コンテナー
Dockerはまず、コンテナー管理ツールだ。
コンテナーとは、1つのサーバーの上で、複数のサーバー環境をそれぞれ分離して実行する、一種の仮想化技術だ。「OSレベルの仮想化」とも呼ばれる。
複数のサーバー環境を動かす点ではハイパーバイザーによる仮想マシン技術に似ている。ただし、仕組みは大きく異なる。仮想マシンでは、物理マシンをエミュレートし、ゲストOSからはあたかも物理マシンで動いているかのように動作する。一方コンテナーは、1つのOSの中を複数の区画に分離する技術であり、1つのカーネルの上で複数のOS環境が動く。
現在のLinuxでは、カーネルに含まれる複数の技術の組み合わせによりコンテナーを実現している。これは、「Linuxコンテナー」(または「広義のLXC」)と呼ばれる。単一の技術によるものではないため、Linuxコンテナーを動かすソフトウェアは、Dockerを含め、「LXC」(「lxc-tools」「狭義のLXC」と呼ばれることもある)やsystemd-nspawn、rkt(旧名Rocket)、LXDなど、複数の実装がある。
Dockerは当初、lxc-toolsを用いたコンテナー管理ツールとして登場した。その後、LinuxカーネルのLinuxコンテナー機構を直接使うようになり、さらにそうしたコンテナー操作をlibcontainer(現在では「runC」プロジェクトに移行)というライブラリーで抽象化した。libcontainerでは複数のコンテナー実装をドライバーとして選択できるようになっている。次期Windows Serverではコンテナー機構を備えてDockerに対応するというのも、libcontainerで抽象化されているおかげだろう。
ちなみに、現在のLinuxコンテナーが登場する以前から、SWsoft社(現Parallels社)が開発したVirtuozzoや、そのオープンソース版であるOpenVZが存在し、VPS事業者に採用されてきた。Parallels社では、Linuxコンテナーは本家Linuxカーネルに統合したOpenVZの技術がベースになっていると主張している。
2. ファイルシステムの差分管理
Dockerのほかにも、以前からlxc-toolsなどLinuxコンテナー管理ツールはあった。そうしたこれまでのコンテナー管理ツールと比べて、Dockerの特徴のひとつといえるのが、ファイルシステムの差分管理の機能だ。
一般にコンテナー環境を動かすには、コンテナーごとにそれぞれディレクトリー階層を用意する必要がある。シンプルな実装では、コンテナーごとに全ディレクトリーとファイルをコピーすることになる。
Dockerでも、元となる雛形(Dockerでは「イメージ」と呼ばれる)に含まれたディレクトリーやファイルからコンテナーが作られる。ただし、雛形をコピーすることはない。Dockerではファイルシステムの差分管理の機能を利用して、雛形のディレクトリーとファイルの上に、書き込み用の領域を“重ねる”形をとる。そして、各コンテナーではイメージに重ねられた書き込み用領域の分、つまりイメージからの差分だけを持つ。
これにより、新しいコンテナーを一瞬で作れる。Dockerでコンテナーを作りながらコマンドを実行してみると、コンテナーを作るオーバーヘッドが人間の感覚ではわからないぐらいだ。差分しかディスク容量を消費しないことと合わせて、どんどんコンテナーを作って使い捨てにできる。
この特徴から、まっさらの環境を何度も作り、使い捨てにする用途にも使える。たとえば、ソースコードを変更するたびにテストを実行するような継続的インテグレーション(CI)などでもDockerが使われることがある。
Dockerではまた、イメージをDockerfileという設定ファイルから作成できる。Dockerfileでは、元イメージを指定したあと、「コマンドAを実行」「コマンドBを実行」……と処理を順番に記述する。実はこの処理1つごとに差分データが作られる。この差分はキャッシュされるため、Dockerfileの最後に処理を追加してイメージを作ると、(うまくいけば)キャッシュを元に追加した処理だけ実行してイメージが作られる。これらの特徴は、コンテナーのデータに対するgitのようなものといえる。
3. 公開されたイメージのライブラリー
Dockerを使ってみて「便利」や「楽」と思うこととして、既存のイメージを簡単に取得できる点がある。
Dockerのコンテナー管理ツールは、正式には「Docker Engine」という。そして、Dockerブランドの中で、Docker Engineを使うための管理ソフトウェアやサービスがDocker社により提供されている。
Docker Engineでは、1つのコマンドで既存のイメージの検索やダウンロードができる。このイメージが多数登録されているサービスが「Docker Hub」だ。Docker Hubには、公式なもののほか、ユーザーが自分の作ったDockerイメージも登録されている。いわば、DockerにおけるGitHubのようなものといえるだろう。
Dockerクライアントからは、1コマンドでDocker Hubからイメージを取得し、コンテナー作成のベースとすることができる。この感覚は、npmやRubyGemsなどからプログラミング言語用ライブラリーを入手するのに似ている。
ただし、たとえば「node」で検索すると、執筆時点で2000イメージ以上がヒットする。サードパーティ製イメージが多く集まってるため、どのイメージを使ったらいいかがわかりづらいとは言われている。
4. アプリケーションのポータビリティ
利用目的から見ると、Dockerは「アプリケーションのポータビリティ」のための仕組みである。
サーバーアプリケーションは一般に、アプリケーション本体だけではなく、ランタイムライブラリーや関連ファイルなどが組み合わさって動作する。そのため、同じアプリケーションを異なる環境で動かそうとすると、ライブラリーの有無やバージョン違い、デフォルト設定の違いなどにより、そのままでは動かないといったことがしばしば起こる。
そこで、アプリケーションといっしょに、必要な動作環境をコンテナーに閉じこめてしまうというのがDockerの解決策だ。これにより、アプリケーションを(原則的には)どこのDocker上でも同じように動かせる。プログラミングでいえば、Node.jsのnpmやRubyのbundler、Goの静的リンクなどに似た考えだ。あるいは、Windows環境に詳しい人は、App-Vを連想するかもしれない。
こうした考えがベースになっているため、Dockerは基本的に、1つのコンテナーで1つのプログラムだけを動かすように作られている。複数のプログラム(たとえばWebアプリケーションとデータベースなど)は、それぞれ別のコンテナーで動かす。このようなコンテナーの使い方は「アプリケーションコンテナー」と呼ばれる。
なお、Dockerのポータビリティと言うときには、2種類の意味がある。同じCPUアーキテクチャで動く同じOS上であれば、Dockerイメージをそのままポータブルに利用できる。一方、異なるCPUやOSの場合でも、OS固有の機能(たとえばパッケージインストールなど)を使わずにDockerファイルをうまく書いてあれば、同じDockerfileで同様のコンテナーを再現できる。
5. ホストOSの新しいモデル
さて、このようにアプリケーションがそれぞれ実行環境を持つというDockerのモデルをつき進めると、ホストOSの役割も変わる。
通常のOS環境では、1台のマシンの上で複数のアプリケーションを動かし、そのために必要なライブラリーやミドルウェアのバージョンを用意する。アプリケーションをアップデートするにはライブラリーの互換性に注意する必要があるし、その逆もいえる。また、インストールしたライブラリーが増えると、セキュリティアップデートなど注意しなくてはならない事項も増える。
そこで、アプリケーションはすべてそれぞれDockerコンテナーで動かすことにすれば、ホストOSでは最小限のシステムだけを管理すればよい。こうした考えのもとに登場したのが「CoreOS」や「RHEL Atomic Host」などだ(CoreOSは現在ではDockerからブランチしたrktを採用)。
CoreOSやRHEL Atomic Hostなどでは、通常のLinuxディストリビューションのように「ソフトをインストールする」という考え方はない。ホスト環境のソフトウェアをアップデートするには、ルートファイルシステムをまるごとアップデートする。CoreOSは「Chrome OS」のオープンソース版である「Chromium OS」が元になっており、そのことからもシステムの考え方がわかるだろう。
6. PaaS
Dockerは、PaaSとも近しい。
Dockerを開発するDocker社(旧名DotCloud社)は、もともとPaaSサービスの会社だ。PaaSの仕組みの一つとして、コンテナーを使った実行環境を開発していた。そのシステムをベースに、再実装してオープンソースとして公開したのが、Dockerの始まりだ。
DotCloudやHerokuなどのPaaSサービスでは、アプリケーションのファイル一式をサーバーに送るたびに、ほかと切り離された専用環境が作られてアプリケーションが実行される。似た環境をすばやく何度も作る仕組みとして、Dockerが開発されたわけだ。
Herokuでも類似の仕組みとして「Warden」を開発している。Pivotal Software社によるPaaS基盤ソフト「Cloud Foundry」では、このWardenをもとにした「Garden」を採用している。また、Cloud Foundryと同様のPaaS基盤ソフトであるRed Hat社の「OpenShift」では、最新の「v3」でDockerを採用した。
Dockerが登場したときにも、Dockerを使ったHeroku風簡易PaaS基盤ソフト「Dokku」がすぐに登場して、一つの利用法を示した。現在では、より発展したDockerベースのPaaS基盤ソフトとして、「Flynn」や「Deis」が開発されている。
7. クラウドネイティブなサーバー構築
Dockerは、クラウドネイティブなサーバー構築の考え方にマッチしたツールでもある。
通常のサーバーの構築運用では、一度構築したサーバーに対し、システムソフトをアップデートしたり、アプリケーションを更新したり、機能を追加したりしていく。それに対してクラウド環境では、同じ役割のサーバーの台数を即座に増やすなど、再現性が重視される。
サーバーを自動的に再現するには、人手や手順書ではなく、プログラムのような形で構築方法を記述する必要がある。ChefやPuppetといった構成管理ツールが利用されるのは、そのためだ。また、テキストファイルによる定義として構築方法を記述することで、プログラムのようにサーバーが構築できることや、プログラムをgitのようなバージョン管理ツールで管理できることなど、アプリケーションプログラマのメンタルモデルに近づく。Dockerも同様の性質を持っている。
クラウド型のサーバー構築の極端な形が、「Blue-Green deployment」と呼ばれる方法だ。サーバーに更新や変更などを加えるときに、既存のサーバーを変更するのではなく、新しいサーバーに新しい環境を作り、その後で新しいサーバーにトラフィックを向け変えるというやりかただ。必要なサーバー台数は倍に増えるが、サーバーの変更にともなうトラブルやダウンタイムを減らし、必要であればロールバック(切り戻し)もできる。
Blue-Green Deploymentでは、一度立てたサーバー環境には変更を加えず、新しいサーバーが正常に始動すれば破棄される。こうした手法を総称して「Immutable Infrastructure」と呼ぶ。言い方を変えれば「使い捨てインフラ」だ。
Dockerも、アプリケーションを終了するとその環境が捨てられ、次に起動するときにはまた新しいベース環境で実行される。また、前述のとおり、どのサーバーでアプリを動かしてもいいポータビリティがある。そのため、Immutable Infrastructureとの親和性が高い。
8. クラスター構築
Dockerの上のレイヤーとして、クラスター構築のシステムに各社が取り組んでいる。
Docker社では前述のように、Docker Engineを中心として、それを複数ノード間で管理するための各種ソフトウェア群まで開発している。同社のSteve Francia氏がLinuxCon Japan 2015で行なった講演では、「昔のOSは1つのマシンのリソースを管理していたが、今は複数のノードにまたがってコンポーネントをスケジュールしたり、ポータビリティを提供したりする必要がある」として、「Linux + DockerがOSの未来」と論じている。
前述したCoreOSも、最初からコンテナーのクラスター実行を想定した設計になっている。RHEL Atomic Hostも、OpenShiftやKubernetesから管理することを想定している。
Kubernetesは、Googleが公開した、Dockerによるクラスター構築ソフトウェアだ。複数(多数)のホストをプール化し、Dockerコンテナーをどこかに割り当てて実行する。Kubernetesについては、GoogleやDockerはもちろん、Microsoft、Red Hat、IBMといったメジャー企業が、呉越同舟といえる形でサポートを表明している。
このように、企業やプロジェクトではいまDockerについて、Dockerコンテナー間や複数ホスト間のオーケストレーションに開発リソースを注ぎ込んでいる。
まとめ
以上、Dockerを8つの軸から紹介した。
見てきてわかるように、Dockerは特定のユースケースに適合するように作られたツールであり、万能ではない。合う用途には合うが、合わない用途はそれ以上に多いといってよい。
Dockerがどのような用途に使え、どのような用途に使えないのかを理解するうえでも、この記事で紹介したようなポイントを押さえておこう。