巷で話題のDockerとは?
最近、巷で注目を浴びているオープンソースの一つに「Docker」(ドッカー)があります。Dockerは、コンテナと呼ばれる隔離空間を管理するためのツールです。CentOS 7は、この「コンテナ」と呼ばれるアプリケーションとOSをパッケージ化した実行環境をサポートしています。一般的に、Linux OS上での隔離空間を「Linuxコンテナ」と呼びます。Linuxコンテナは、KVMやXenなどのハイパーバイザー型の仮想化技術に比べて、CPU、メモリ、ストレージ、ネットワーク等のハードウェア資源の消費やオーバーヘッドが小さいとう利点が挙げられます。Dockerは、Linuxコンテナの機能に加えて、API、イメージフォーマット、環境を配布する仕組みを持っています。しかし、このDockerが注目される理由は、ハードウェア資源の消費のオーバーヘッドが小さいだけではありません。Dockerが注目される背景には、アプリケーション開発者が最も嫌うであろう「ハードウェアの調達やメンテナンス」の隠蔽が挙げられます。ハードウェアに関する部分は、アプリケーション開発者にとってあまり重要ではありません。従来のKVM等による仮想化は、アプリケーション開発者にとってのメリットというよりもむしろ、システム管理者にとって大きなメリットがありました。一方、Dockerのような軽量なコンテナ技術の発達により、アプリケーション単位での隔離、開発環境の容易な作成と廃棄ができるようになり、アプリケーションのメンテナンスの簡素化がより一層進むことになります。これは、システム管理者よりもアプリケーション開発者にとってのメリットが非常に大きいことを意味します。また、Dockerの仕組みによって、アプリケーションの開発と実環境への素早い展開と運用の両立が見えてきました。これは、近年、開発者やIT部門の間で話題になっている「DevOps環境」の実現に他なりません。アプリケーション開発者やIT部門にとっては、アプリケーションの開発、運用、廃棄等を、ハードウェア資源を意識しない「雲」の上で迅速に行える環境がDockerを使って整備されつつあります。
図6:物理基盤、仮想化基盤、PaaS基盤の比較。PaaS基盤では、DevOpsのようなアプリケーション中心の考えで隔離空間毎に異なるOSバージョンとサービスを提供できる
CentOS 7でdockerを使う
以下では、CentOS 7で採用されているdockerのインストールと基本的な利用方法について説明します。CentOS 7では、dockerパッケージが標準で含まれています。yumコマンドでインストールします。
3 | docker-1.3.2-4.el7.centos.x86_64 |
docker pull centosでイメージをインターネット経由で入手しますが、もし企業内においてプロキシーサーバー経由でインターネットに接続する環境では、以下のように、/etc/sysconfig/dockerファイルにプロキシーサーバーを指定し、dockerサービスを再起動してください。
1 | # vi /etc/sysconfig/docker |
7 | # systemctl restart docker |
dockerサービスを起動します。
1 | # systemctl start docker |
2 | # systemctl enable docker |
3 | ln -s '/usr/lib/systemd/system/docker.service' '/etc/systemd/system/multi-user.target.wants/docker.service' |
これでDockerのインストールは完了です。Dockerでは、様々なOSとアプリケーションがパッケージ化された環境がDockerイメージとしてDockerリポジトリに用意されています。イメージファイルを一から作成することも可能ですが、すでにDockerリポジトリに用意されているイメージファイルを利用することができますので、コンテナへのOSやアプリケーションのインストール等の煩雑な作業をスキップすることができます。以下では、Dockerリポジトリに用意されているイメージファイルをDocker上で起動させてみます。
イメージファイルをDockerリポジトリから入手する前にSELinuxをdisableにしておきます。
イメージファイルをインターネット経由でDockerリポジトリから入手します。
01 | # docker pull centos:centos5 |
02 | Pulling repository centos |
03 | bac0c97c3010: Download complete |
04 | 511136ea3c5a: Download complete |
05 | 5b12ef8fd570: Download complete |
06 | Status: Downloaded newer image for centos:centos5 |
08 | # docker pull centos:centos6 |
09 | Pulling repository centos |
10 | 510cf09a7986: Download complete |
11 | 511136ea3c5a: Download complete |
12 | 5b12ef8fd570: Download complete |
13 | Status: Downloaded newer image for centos:centos6 |
15 | # docker pull centos:centos7 |
16 | Pulling repository centos |
17 | 8efe422e6104: Download complete |
18 | 511136ea3c5a: Download complete |
19 | 5b12ef8fd570: Download complete |
20 | Status: Downloaded newer image for centos:centos7 |
Dockerリポジトリから入手し、ローカルのCentOS 7サーバー上に保管されているイメージファイル一覧を確認します。
2 | REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE |
3 | centos 5 bac0c97c3010 7 days ago 466.9 MB |
4 | centos centos5 bac0c97c3010 7 days ago 466.9 MB |
5 | centos 6 510cf09a7986 7 days ago 215.8 MB |
6 | centos centos6 510cf09a7986 7 days ago 215.8 MB |
7 | centos latest 8efe422e6104 7 days ago 224 MB |
8 | centos 7 8efe422e6104 7 days ago 224 MB |
9 | centos centos7 8efe422e6104 7 days ago 224 MB |
上記のイメージファイル群のうち、centos6という名前の付いたタグの付いたイメージファイルから、コンテナを生成、起動し、そのコンテナ内で作業できるようにしてみましょう。Dockerのイメージファイルからコンテナを起動するには、docker runを実行します。--nameオプションに、コンテナの名前を指定します。今回は、test01という名前のコンテナを起動するように指定しました。-iオプションは、コンテナの標準入力を開いた状態にします。-tオプションを付与することにより、Dockerは、仮想端末を割り当てて、コンテナの標準入力にアタッチします。centos:centos6は、入手したイメージファイルのタグ付きのリポジトリ名です。最後に、/bin/bashを指定することで、コンテナ上のシェルを起動します。
1 | # docker run --name test01 -i -t centos:centos6 /bin/bash |
コンテナにログインし、作業してみます。コンテナのOSのバージョンを確認します。
1 | [root@d962dc3be270 /]# cat /etc/redhat-release |
2 | CentOS release 6.6 (Final) |
すると、CentOS 6.6であることがわかります。ホスト名を確認してみます。
1 | [root@d962dc3be270 /]# hostname |
ホスト名は自動的に「d962dc3be270」という名前で割り振られていることがわかります。さらにIPアドレスを確認し、ホストOSや外部と通信できるかを確認します。dockerでは、標準で、インタフェースdocker0を割り当てます。
01 | [root@d962dc3be270 /]# ifconfig eth0 |grep inet |
02 | inet addr:172.17.0.5 Bcast:0.0.0.0 Mask:255.255.0.0 |
03 | inet6 addr: fe80::42:acff:fe11:5/64 Scope:Link |
04 | [root@d962dc3be270 /]# ping -c 3 172.16.1.1 |
05 | PING 172.16.1.1 (172.16.1.1) 56(84) bytes of data. |
06 | 64 bytes from 172.16.1.1: icmp_seq=1 ttl=63 time=0.690 ms |
07 | 64 bytes from 172.16.1.1: icmp_seq=2 ttl=63 time=0.281 ms |
08 | 64 bytes from 172.16.1.1: icmp_seq=3 ttl=63 time=0.239 ms |
10 | --- 172.16.1.1 ping statistics --- |
11 | 3 packets transmitted, 3 received, 0% packet loss, time 2373ms |
12 | rtt min/avg/max/mdev = 0.239/0.403/0.690/0.204 ms |
dockerのイメージファイルの仕組みを理解するため、まず、試しいdockerコンテナー上の/rootディレクトリにファイルtestfileを作成しておきます。
1 | [root@d962dc3be270 /]# touch /root/testfile |
2 | [root@d962dc3be270 /]# ls /root/ |
dockerコンテナのOS環境から離脱します。
1 | [root@d962dc3be270 /]# exit |
ホストOS上で、過去に起動したコンテナ一覧を確認します。
2 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
3 | d962dc3be270 centos:6 "/bin/bash" 9 minutes ago Exited (0) About a minute ago test01 |
先程作業したコンテナを再利用できるように、コンテナのイメージ化を行います。コンテナをイメージ化するには、コンテナをコミットします。先程作業したコンテナのコンテナIDとイメージを指定してコミットを行います。
1 | # docker commit d962dc3be270 centos:centos6 |
2 | 5468f0e1072fbd5cdf0042efc76e3d0d8c778f235faf212bcbf9b2105ebdf30f |
再び、現在のイメージファイルの一覧を確認します。
2 | REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE |
3 | centos centos6 5468f0e1072f 24 seconds ago 215.8 MB |
4 | centos centos5 bac0c97c3010 7 days ago 466.9 MB |
5 | centos 5 bac0c97c3010 7 days ago 466.9 MB |
6 | centos 6 510cf09a7986 7 days ago 215.8 MB |
7 | centos centos7 8efe422e6104 7 days ago 224 MB |
8 | centos latest 8efe422e6104 7 days ago 224 MB |
9 | centos 7 8efe422e6104 7 days ago 224 MB |
先程コミットしたイメージファイル「centos:centos6」を使って、別のコンテナtest02を生成してみます。
1 | # docker run --name test02 -i -t centos:centos6 /bin/bash |
コンテナtest02上の/rootを確認してみます。
1 | [root@5b2ac9622d6f /]# ls /root/ |
コンテナtest02で、/root/testfile2を作成します。
01 | [root@5b2ac9622d6f /]# touch /root/testfile2 |
02 | [root@5b2ac9622d6f /]# exit |
05 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
06 | 5b2ac9622d6f centos:centos6 "/bin/bash" 2 minutes ago Exited (0) About a minute ago test02 |
07 | d962dc3be270 centos:6 "/bin/bash" 20 minutes ago Exited (0) 12 minutes ago test01 |
09 | # docker commit 5b2ac9622d6f centos:testfile2 |
10 | 4eac0fb23ec1d4a212b4aa289637f43da3049dd975d48a91fd9890ca6a368cdd |
12 | REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE |
13 | centos testfile2 4eac0fb23ec1 8 seconds ago 215.8 MB |
14 | centos centos6 5468f0e1072f 7 minutes ago 215.8 MB |
15 | centos 5 bac0c97c3010 7 days ago 466.9 MB |
16 | centos centos5 bac0c97c3010 7 days ago 466.9 MB |
17 | centos 6 510cf09a7986 7 days ago 215.8 MB |
18 | centos centos7 8efe422e6104 7 days ago 224 MB |
19 | centos latest 8efe422e6104 7 days ago 224 MB |
20 | centos 7 8efe422e6104 7 days ago 224 MB |
上記より、作業を行ったコンテナをコミットすることでその作業内容を反映したイメージファイルが生成でき、さらに作成したイメージファイルを再利用して、新たなコンテナを生成できていることがわかります。開発者は、アプリケーション毎に異なるコンテナを複数作成し、コミットしておけば、そのアプリケーションに特化したイメージファイルを持つことができ、すぐにアプリケーションが実行可能な環境をコンテナで利用することができます。
図7:ホストマシンに保管されたDockerイメージからdocker runでコンテナを起動する。起動したコンテナで作業を施し、アプリケーション等の構築をしたものをdocker commitでDockerイメージとして登録する
コンテナに含まれるファイルの確認方法
現在起動しているDockerコンテナのファイルシステム上にあるファイル等をホストマシンから確認したい場合があります。起動中のコンテナのファイルシステムは、/var/lib/docker/devicemapper/metadataディレクトリ配下にあるコンテナID の名前が付いたメタデータの情報を元に、Device Mapperを使ってアクセスできます。以下は、CentOS 6.6のDockerイメージからコンテナを起動し、そのコンテナのファイルシステムに存在する/etc/redhat-releaseファイルに記載されたCentOSのバージョンをホストマシンから確認する手順です。まず、Dockerに現在登録されているイメージファイルを確認します。今回、CentOS 6.6のDockerイメージ「centos:centos6.6」は、事前にCentOS 6のDockerイメージを入手し、yum updateによりパッケージを最新に更新することにより作成しました。
02 | REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE |
03 | centos centos6.6 6e80aa2dad3a 23 seconds ago 215.8 MB |
04 | centos testfile2 4eac0fb23ec1 4 minutes ago 215.8 MB |
05 | centos centos6 5468f0e1072f 12 minutes ago 215.8 MB |
06 | centos 5 bac0c97c3010 7 days ago 466.9 MB |
07 | centos centos5 bac0c97c3010 7 days ago 466.9 MB |
08 | centos 6 510cf09a7986 7 days ago 215.8 MB |
09 | centos centos7 8efe422e6104 7 days ago 224 MB |
10 | centos 7 8efe422e6104 7 days ago 224 MB |
11 | centos latest 8efe422e6104 7 days ago 224 MB |
上記のDockerイメージ「centos:centos6.6」から、コンテナを起動します。コンテナ名はtest001としました。
1 | # docker run --name test0001 -i -t centos:centos6.6 /bin/bash |
ホストマシンの別の端末で、起動中のコンテナを確認します。
2 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
3 | 098686019f0d centos:centos6.6 "/bin/bash" 12 minutes ago Up 12 minutes test001 |
以下は、起動中のコンテナ「098686019f0d」のファイルシステムをホストマシンから確認する手順です。まず、コンテナ「098686019f0d」のメタデータから、コンテナのデバイスIDとサイズを確認します。
1 | # cd /var/lib/docker/devicemapper/metadata |
2 | # cat 098686019f0dec240ec5b0473046b78b5e56cb7dd0651e821d9e9216cfa9e37e |python -mjson.tool |
上記より、このコンテナのデバイスIDは6、サイズが、10737418240であることがわかります。次に、起動しているコンテナがマウントされているループバックデバイスを表示します。
3 | crw-------. 1 root root 10, 236 12月 17 17:46 control |
4 | lrwxrwxrwx. 1 root root 7 1月 13 11:23 docker-8:3-84171797-098686019f0dec240ec5b0473046b78b5e56cb7dd0651e821d9e9216cfa9e37e -> ../dm-3 |
5 | lrwxrwxrwx. 1 root root 7 1月 13 08:33 docker-8:3-84171797-pool -> ../dm-1 |
6 | lrwxrwxrwx. 1 root root 7 1月 13 05:28 encrypted001 -> ../dm-2 |
7 | lrwxrwxrwx. 1 root root 7 1月 13 05:28 pool001-lvol001 -> ../dm-0 |
上記のdocker-8:3-84171797-poolと先述のデバイスID、サイズを使って、テスト用のボリュームを作成します。具体的には、コンテナのサイズ「10737418240」と、デバイスIDの「6」をdmsetupコマンドの--tableオプションで指定します。
1 | # dmsetup create testvol01 --table "0 $((10737418240 / 512)) thin /dev/mapper/docker-8:3-84171797-pool 6" |
テスト用のボリュームtestvol01は/dev/mapperディレクトリ以下に作成されていますので、これをマウントします。
1 | # mount /dev/mapper/testvol01 /mnt |
/mntにマウントしたコンテナのディレクトリツリーと/etc/redhat-releaseファイルを確認します。
03 | drwxr-xr-x. 21 root root 4096 1月 13 08:07 . |
04 | drwxr-xr-x. 4 root root 4096 9月 9 06:30 .. |
05 | dr-xr-xr-x. 2 root root 4096 1月 2 23:23 bin |
06 | drwxr-xr-x. 4 root root 90112 1月 2 23:23 dev |
07 | drwxr-xr-x. 45 root root 4096 1月 2 23:23 etc |
08 | drwxr-xr-x. 2 root root 4096 9月 23 2011 home |
09 | dr-xr-xr-x. 7 root root 4096 1月 2 23:23 lib |
10 | dr-xr-xr-x. 6 root root 12288 1月 2 23:23 lib64 |
11 | drwx------. 2 root root 4096 1月 2 23:21 lost+found |
12 | drwxr-xr-x. 2 root root 4096 9月 23 2011 media |
13 | drwxr-xr-x. 2 root root 4096 9月 23 2011 mnt |
14 | drwxr-xr-x. 2 root root 4096 9月 23 2011 opt |
15 | drwxr-xr-x. 2 root root 4096 1月 2 23:21 proc |
16 | dr-xr-x---. 2 root root 4096 1月 2 23:23 root |
17 | dr-xr-xr-x. 2 root root 4096 1月 2 23:23 sbin |
18 | drwxr-xr-x. 3 root root 4096 1月 2 23:23 selinux |
19 | drwxr-xr-x. 2 root root 4096 9月 23 2011 srv |
20 | drwxr-xr-x. 2 root root 4096 1月 2 23:21 sys |
21 | drwxrwxrwt. 2 root root 4096 1月 2 23:23 tmp |
22 | drwxr-xr-x. 13 root root 4096 1月 2 23:21 usr |
23 | drwxr-xr-x. 17 root root 4096 1月 2 23:21 var |
25 | # cat /mnt/rootfs/etc/redhat-release |
26 | CentOS release 6.6 (Final) |
コンテナが持つファイルシステムを確認し終えたら、マウントを解除し、テスト用のボリュームは削除しておきます。
3 | # dmsetup remove /dev/mapper/testvol01 |
【注意】
dmsetupコマンドにより、コンテナのファイルシステムを確認するためのテスト用のボリュームを作成する際に、デバイスIDを間違えると、別のコンテナのファイルシステムの中身を見ることになりますので十分注意して下さい。
Dockerfileを使ったイメージファイルの構築
Dockerイメージの作成や、イメージファイルからコンテナを起動する一連の手順は、先述のdockerコマンドでコマンドラインから入力することで可能ですが、イメージ作成作業、アプリケーションのインストール等の複数の作業をまとめて行いたい場合があります。そのような場合は、Dockerfileを使うと便利です。Dockerファイルは、開発環境におけるMakefileのように、一連の作業をDockerで定義された書式に従って事前に記述し、それに基づいてイメージの作成を行います。以下では、CentOS 7で稼働するApache Webサーバーが起動するコンテナのイメージファイルの作成、コンテナの起動、コンテナへのアクセス方法を述べます。まず、Apacheが稼働するコンテナ用のDockerfileを用意します。今回は、/root/apacheディレクトリを作成し、その下にDockerfileを作成します。
04 | FROM centos:centos7 ←使用するDockerイメージ名を指定 |
05 | MAINTAINER Masazumi Koga |
07 | RUN yum swap -y fakesystemd systemd ←systemdをDockerイメージにインストール |
08 | RUN yum install -y initscripts |
09 | RUN yum install -y httpd ←Apache WebサーバーのhttpdパッケージをDockerイメージにインストール |
10 | RUN echo "Hello Apache." > /var/www/html/index.html ←テスト用のHTMLファイルをDockerイメージに配置 |
11 | RUN systemctl enable httpd ←コンテナ起動時にhttpdサービスが起動するように設定 |
12 | EXPOSE 80 ←Dockerコンテナが外部に開放するポート番号を指定 |
Dockerfile内では、FROM行に利用するイメージの種類を記述します。イメージ名はコマンドラインから「docker images」で確認可能ですので、一覧に表示されているイメージ名を記述します。ここではCentOS 7のイメージ「ceentos:centos7」を指定しています。RUN行では、Dockerのイメージを作成する際に実行したいコマンドを記述します。今回、RUN行に、「yum swap -y fakesystemd systemd」が指定されています。Dockerリポジトリに標準で用意されているCentOS 7のDockerイメージは、デフォルトでsystemdを利用しないものが用意されています。しかし、多くのCentOS 7向けのアプリケーションやサービスがsystemdを使用するため、Dockerイメージにsystemdをインストールしたい場合があります。今回は、yumコマンドで、fakesystemdを削除し、systemdをインストールしています。さらに、RUN行の「yum install -y httpd」は、Apache Webサーバーのhttpdパッケージをインストールする記述です。今回使用するDockerイメージは、CentOS 7のsystemdを有効にしますので、RUN行で「systemctl enable httpd」を記述し、コンテナが起動した際に、自動的にApache Webサーバーが起動するようにします。Apache Webサーバーのコンテナが外部に開放するポート番号をEXPOSE行で指定します。Dockerfileを記述したら、Dockerイメージを生成します。
6 | -rw-r--r--. 1 root root 263 11月 9 17:09 Dockerfile |
9 | # docker build -t centos7_apache . |
Apache Webサーバー入りのDockerイメージ「centos7_apache」が作成されているかを確認します。
2 | REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE |
3 | centos7_apache latest ac8e9d882d7e About a minute ago 381.9 MB |
作成したDockerイメージ「centos7_apache」を使ってDockerコンテナを起動します。今回起動するコンテナ名は、「apache001」としました。
1 | # docker run --name apache001 --privileged -i -t -d -p 80:80 centos7_apache /sbin/init |
2 | 3db4623293db8c6a2e516ac788bb10fa32a73175c46d08c19a6b441d148b6838 |
DockerイメージがCentOS 7ベースで、コンテナ内でsystemdを使用する場合は、コンテナの起動オプションに、「--privileged」オプションが必要になります。またコンテナの起動に指定するコマンドは、「/sbin/init」を指定します。コンテナが起動したかを確認します。
2 | CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
3 | 3db4623293db centos7_apache:latest "/sbin/init" 15 seconds ago Up 15 seconds 0.0.0.0:80->80/tcp apache001 |
コンテナ「apache001」が起動していることがわかります。ホストマシンからコンテナ「apache001」にログインします。
1 | # nsenter -t $(docker inspect --format '{{.State.Pid}}' apache001) -i -m -n -p -u /bin/bash |
上記のようにログインプロンプトが「[root@3db4623293db /]」になったことで、コンテナにログインできていることがわかります。コンテナにログインできていますので、コンテナ上でApache Webサービスが起動しているかを確認します。
1 | [root@3db4623293db /]# systemctl status httpd |
コンテナがhttpdサービスを正常に起動できていることを確認できたら、コンテナに割り振られたIPアドレスをコンテナ上で確認します。
1 | [root@3db4623293db /]# ip a |grep inet |
3 | inet 172.17.0.26/16 scope global eth0 |
コンテナが外部にWebサービスを提供できているかをホストマシンや他のクライアントマシンから確認します。コマンドラインから確認するには、curlコマンドが有用です。
1 | # curl 172.17.0.26/index.html |
【注意】
本連載では、CentOS 7のDockerイメージにsystemdをインストールする方法を紹介しましたが、Dockerコンテナ上でのsystemdの利用については、全てのアプリケーションやデーモンについて、十分なテストが行われているわけではありません。したがって、利用者の自己責任の元で十分な動作確認を行って上記手順を利用するように下さい。