「docker import」コマンドでDockerコンテナをゼロから作る

Docker向けのコンテナを公開するDocker Hubでは多数のコンテナが公開されており、これらをベースにして独自のコンテナを作成できる。しかし、新規に独自のコンテナを作成したい場合もあるだろう。今回は、Dockerコンテナにおけるファイル/ディレクトリ情報の格納方法について解説するとともに、新規にコンテナを作成するのに必要な作業手順を紹介する。
Dockerにおける一般的なコンテナ作成手順
Dockerではよく使われるOS環境を含むコンテナがあらかじめ用意されており、それをベースに独自のコンテナを作成できる。しかし、公開されているコンテナではなく、ゼロからコンテナを構築したいという場合もある。
たとえばコンテナを公開できるリポジトリサービス「Docker Hub」で提供されている公式のCent OSのコンテナでは、ファイル容量削減のためか一部のファイルが削除された状態になっており、それらのファイルを参照する処理を実行するとエラーが発生することがある。
また、公式には公開されていないようなOS環境のコンテナが必要というケースも考えられる。そこで今回は、Dockerで独自のコンテナを一から作成する手順を紹介する。
DockerにおけるコンテナとBase Image
Dockerでは「docker import」というコマンドが用意されている。このコマンドは、指定したtarファイルから「Base Image」を作成する処理を行うものだ。
「Base Image」という用語は聞き慣れないかもしれないが、これはその名の通りコンテナのベースとなるイメージファイルを指す言葉だ。DockerではUnion File Systemという機構を使い、複数のディスクイメージを組み合わせてコンテナが使用するルートディレクトリを用意している。
なお、一般的にはディスクイメージというとファイルシステムをその構造や制御情報までも含めてファイル化したものを指すが、DockerのImageは単にディレクトリおよびファイルだけを含むもので、厳密にはディスクイメージとは異なるものとなる。
Dockerコンテナでは、ファイルやディレクトリなどに対する変更はBase Imageに対する差分という形で記録される。Base Imageにはコンテナのルートディレクトリとなる完全なディレクトリツリーが含まれており、これにその差分を順次適用したものが、コンテナの実際のルートディレクトリになる仕組みだ(図1)。
Dockerではコンテナを終了するたびにコンテナに加えた変更が破棄され、もし加えた変更を恒久的に反映させたい場合はコミット処理を実行する必要がある。コミットを実行するとその差分が保存され、新たなID(Image ID)が割り振られる。こういった構造によって、Dockerではコンテナが変更されたあとも任意のコミット時の状態にすぐに復帰させることや、過去の任意のコミットの状態から別の状態に分岐さることが簡単にできるようになっている。
「docker import」コマンドでBase Imageを作成する
DockerでBase Imageを作成するには、「docker import」コマンドを使用する。詳しくはmanページを見てほしいが、docker importコマンドはtarでアーカイブ化されたディレクトリツリーをBase Imageに変換するツールだ。たとえば、「container_root」というディレクトリを用意し、これに対し次のように実行すると、このディレクトリをルートディレクトリとするBase Imageとコンテナが作成される。
# mkdir container_root : <ここでcontainer_rootディレクトリに必要なファイルやディレクトリをコピーする> : # cd container_root # tar -c . | docker import - <イメージ名>:<タグ名>
なお、このときタグ名は省略可能だ。
とはいえ、この説明だけでは実際にどういった手順で作業を行えば良いか分かりにくいだろう。そこで、続いては具体的にさまざまなディストリビューション向けのイメージを作成する実例を紹介しよう。
Debian系ディストリビューションのBase Imageを作成する
まずはDebianやUbuntuといった、Debian系ディストリビューションのBase Image作成方法について説明しよう。Debian系ディストリビューションでは、OSの稼動に最低限必要なファイルなどを指定したディレクトリにインストールする「debootstrap」というコマンドが用意されており、これを使ってOS環境を構築できる。まずはこのdebootstrapをインストールする。
# apt-get install debootstrap
debootstrapでは、引数としてインストールするディストリビューションのリリース名とインストール先ディレクトリ、そしてパッケージのダウンロード先を指定する。
たとえばDebian 7.0のBase Imageを作成したい場合、リリース名は「wheezy」となる。また、パッケージのダウンロード先はミラーサイトなどのURLを指定する。たとえばさくらインターネットが提供しているDebianのミラーサイトを使用する場合、そのURLは「http://debian-mirror.sakura.ne.jp/debian/」となる。この場合、実際に実行するコマンドは次のようになる。
# mkdir debian-wheezy ←インストールするディレクトリを作成する # debootstrap wheezy ./debian-wheezy http://debian-mirror.sakura.ne.jp/debian/ W: Cannot check Release signature; keyring file not available /usr/share/keyrings/debian-archive-keyring.gpg I: Retrieving Release I: Retrieving Packages g[:] g[:] I: Configuring tasksel-data... I: Base system installed successfully.
debootstrapコマンドを実行すると必要となるパッケージがダウンロードされ、続いて指定したディレクトリにインストールされる。
正しく環境が構築できているかは、chrootコマンドを使ってそのディレクトリをルートディレクトリとしたシェルを実行することで確認できる。
# chroot debian-wheezy /bin/bash # ls bin boot dev etc home lib lib64 media mnt opt proc root run sbin selinux srv sys tmp usr var # cat /etc/debian_version 7.6 # exit
最後に、Debian環境をインストールしたディレクトリに移動してdocker importコマンドを実行することで、Base Imageとそれを使用するコンテナが作成される。
# cd debian-wheezy # tar -c . | docker import - debian-wheezy 67221db56e0b3f031e999968eaf1a3220501b72e09413f46aa3634e6efab3438
ちなみに、docker importコマンドと似たコマンドとして「docker load」コマンドがある。このコマンドは「docker save」コマンドで作成した、タグやバージョン情報までも含んだコンテナイメージファイルを読み込むものだ。docker saveコマンドでコンテナをファイルに書き出した場合、Base Imageとコミットによって記録されたファイルシステムの差分がアーカイブ化されたものが出力される。
なお、Dockerではイメージをファイルに書き出す機能として「docker export」コマンドも用意されている。こちらはdocker importコマンドの挙動からも推測できるとおり、コンテナのファイルシステムだけをそのままtarコマンドでアーカイブ化したものを出力する。そのため、こちらは新たにBase Imageを作成する目的で使われる。
UbuntuのBase Imageを作成する
UbuntuはDebianから派生したディストリビューションであるため、ディストリビューションのリリース名とダウンロード先URLが異なるだけで、Debianとほぼ同じ流れでBase Imageを作成できる。たとえばUbuntu 14.04(Trusty Tahr)のBase Imageを作成したい場合、次のようにdebootstrapを実行すれば良い。
# mkdir ubuntu-trusty # debootstrap trusty ./ubuntu-trusty http://ftp.jaist.ac.jp/pub/Linux/ubuntu/ # cd ubuntu-trusty # tar -c . | docker import - ubuntu-trusty