Dockerのしくみ
それでは、Dockerがどのようなしくみで動いているのかを簡単に説明します。Dockerの開発は非常に活発で、新しい機能が速いスピードで追加されていますが、まずはDockerのベースとなる部分のしくみをみていきます。
Dockerイメージを作る機能
Dockerは、アプリケーションの実行に必要になるプログラム本体/ライブラリ/ミドルウエアや、OSやネットワークの設定などを1つにまとめた「Dockerイメージ」を作ります。イメージをつくるには、Dockerのコマンドを使って作ることもできますし、Dockerfileというプログラムを作ってそれをもとに自動でイメージを作ることもできます。出来上がったDockerイメージは、実行環境で動くコンテナのもとになります。Dockerイメージの正体は、アプリケーションの実行に必要なファイル群が格納されたディレクトリです。Dockerコマンドを使うとイメージをtarファイルに出力できます。
また、Dockerイメージは積み重ねて使うことができます。たとえば、OS用のイメージにWebアプリケーションサーバ用のイメージを重ねて、別の新しいイメージを作成できます。Dockerでは構成に変更があった部分を差分として管理します。
今回の連載では、コードでインフラを作成する方法をご紹介したいので、コマンドによる手作業ではなく、Dockerfileをもとに自動でDockerイメージを作る方法を説明します。
Dockerコンテナを動かす機能
Dockerは、Linux上で、コンテナ単位でサーバ機能を動かします。このコンテナのもとになるのが、Dockerイメージです。Dockerイメージさえあれば、Linux上にDockerがインストールされた環境であればどこでもコンテナを動かすことができます。また、Dockerイメージから複数のコンテナを起動することもできます。コンテナの起動/停止/破棄は、Dockerのコマンドを使います。他の仮想化技術でサーバ機能を起動するためにはOSを起動させるところから始まりますが、Dockerの場合は、すでに動いているOS上でプロセスを実行するのとほぼ同じ速さで起動します。
Dockerは、1つのLinuxカーネルを複数のコンテナで共有しています。コンテナ内で動作するプロセスを1つのグループとして管理し、グループごとにそれぞれファイルシステムやホスト名/ネットワークなどを割り当てています。グループが異なればプロセスやファイルへのアクセスが出来ません。このしくみを使って、コンテナを独立した空間として管理しています。これらを実現するためLinuxカーネル機能(namespace/cgroupsなど)の技術が使われています。Linuxカーネルとは、LinuxのOSの基本となる、ファイルシステムやプロセスやメモリを管理し、デバイスやネットワークを制御するコア機能のことです。
Dockerイメージを公開/共有する機能
DockerのイメージはDockerレジストリで一元管理できます。たとえば、公式のDockerレジストリであるDocker HubではUbuntuやCentOSなどのLinuxディストリビューションの基本機能を提供するベースイメージが配布されています。これらのベースイメージにミドルウエアやライブラリ/デプロイするアプリケーションなどを入れたイメージを積み重ねて独自のDockerイメージを作っていきます。
また公式のイメージ以外にも、個人が作成したイメージをDocker Hubで公開/共有することができます。すでにたくさんのDockerイメージが公開されていますので、要件に合うものがあればそれをダウンロードして使うことができます。
Dockerコマンドをつかうと、Docker Hubにログインして、レジストリ上のイメージの検索やアップロード/ダウンロードができます。
また、Docker Hubは、GitHubやBitbucketと連携することもできます。たとえばGitHub上でDockerfileを管理し、そこからDockerイメージを生成しDocker Hubで公開するなどということも可能です。
また、Docker社は2014年12月に「Docker Hub Enterprise」を発表しました。これにより、企業内だけのクローズ環境でDockerイメージを共有できる環境を構築できるようになります。業務システムに導入するときは、セキュリティの観点から、不特定多数にDockerイメージを公開できないため、Docker Hub Enterpriseは必須の機能になるとおもわれます。
Dockerは一度コンテナのイメージを作ったらどこででも動くという特徴があります。そのため、業務アプリケーション開発者の皆さんであれば、「Write Once. Run Anywhere」という言葉が思いうかぶ人も多いのではないでしょうか。
そこでJavaのアプリケーションとDockerを比べてみます。JavaではプログラムをJavaソース(=Dockerfile)に書き、それをコンパイルするとクラスファイル(=Dockerイメージ)が生成されます。生成されたクラスは、必要に応じてコードの中でインスタンス化(=Dockerコンテナ)して使います。もちろん、クラスから複数のインスタンスを生成することができます。そして、クラスファイルとJavaVM(=Docker)さえあれば、どこでもJavaのプログラムが動作します。そして、作ったアプリは各種リポジトリサービス(=Docker Hub)で共有すれば、世界中の開発者が利用できますよね。
もちろん、内部の技術的な部分はまったく異なるものですので、くれぐれもDockerの概要をつかむときのおおまかなイメージだけを参考にしてくださいね。