Dockerfileを使いこなす(1)
Dockerは、ハイパーバイザー側の仮想化ソフトに比べて、飛躍的にサーバー集約を実現できる特徴がありますが、それだけではありません。Dockerの醍醐味は、OSとアプリケーションをパッケージ化する手順を自動化できるという点にあります。では、OSとアプリケーションのパッケージ化を自動化するとは、一体どういうことなのでしょうか?そこには、今までのコンテナ型のソフトウェアにはない斬新な考えがあります。それが、Dockerfileです。今回と次回は、Dockerfileを使ったOSとアプリケーションのパッケージ化の具体的な自動化手順について解説します。
Dockerfileを使ったイメージの作成
Dockerイメージの作成や、イメージからコンテナを起動する一連の手順は、dockerコマンドでコマンドラインから入力することで可能ですが、コンテナとなるベースイメージの入手やコンテナへのアプリケーションのインストールなどの複数の作業を一括して行いたい場合があります。
Dockerでは、これらの複数の作業を一括で行うための仕組みが用意されており、これを実現するのが、Dockerfileです。Dockerfileは、開発環境におけるMakefileのように、Dockerで定義されている書式に従って記述し、それに基づいてアプリケーションのインストールなどを行い、Dockerイメージの作成を行います。Dockerfileにより、Dockerコンテナの一連のアプリケーション構築作業を自動化することができますが、それだけでなく、Dockerfileは、コンテナがどうようなアプリケーションで構成されているか、誰がメンテナーなのか、どういう手順で構築されているのかなどの重要な情報を含んでおり、コンテナのメンテナンス効率の向上に大きく貢献します。
以下では、CentOS 7で稼働するApache Webサーバーが起動するコンテナのイメージファイルの作成を例に、Dockerfileを解説します。まず、アプリケーションであるApacheが稼働するコンテナのためのDockerfileを記述します。Dockerfileを配置する場所は、任意ですが、今回は、/root/apacheディレクトリを作成し、その下にDockerfileを作成することにします。
# mkdir /root/apache # cd /root/apache # vi Dockerfile FROM centos:centos7.1.1503 (1) MAINTAINER Masazumi Koga (2) ENV container docker (3) RUN yum update -y && yum clean all (4) RUN yum swap -y fakesystemd systemd && yum clean all (5) RUN yum install -y httpd && yum clean all (6) RUN echo "Hello Apache." > /var/www/html/index.html (7) RUN systemctl enable httpd (8) EXPOSE 80 (9)
- 使用するDockerイメージ名を指定
- Dockerfileのメンテナーを記述
- 環境変数を設定
- パッケージのアップデート
- systemdをDockerイメージにインストール
- httpdパッケージをDockerイメージにインストール
- テスト用のHTMLファイルを配置
- コンテナ起動時にhttpdサービスが起動するように設定
- Dockerコンテナが外部に開放するポート番号を指定
Dockerfile内では、FROM行に利用するイメージの種類を記述します。イメージ名はコマンドラインから「docker images」で確認可能ですので、一覧に表示されているイメージ名を記述します。ここではCentOS 7.1のイメージ「ceentos:centos7.1.1503」を指定しています。
RUN行では、Dockerのイメージの作成時に実行するコマンドを記述します。今回、RUN行に、「yum swap -y fakesystemd systemd」が指定されています。Dockerリポジトリに標準で用意されているCentOS 7.1のDockerイメージは、デフォルトでsystemdを利用しないものが用意されています。しかし、多くのCentOS 7.1向けのアプリケーションやサービスがsystemdを使用するため、Dockerイメージにsystemdをインストールしたい場合があります。今回は、yumコマンドで、fakesystemdを削除し、systemdをインストールしています。さらに、RUN行の「yum install -y httpd」は、Apache Webサーバーのhttpdパッケージをインストールする記述です。今回使用するDockerイメージは、CentOS 7.1のsystemdを有効にしますので、RUN行で「systemctl enable httpd」を記述し、コンテナが起動した際に、自動的にApache Webサーバーが起動するようにします。Apache Webサーバーのコンテナが外部に開放するポート番号をEXPOSE行で指定します。Dockerfileを記述したら、docker buildにより、Dockerイメージを生成します。
# pwd /root/apache # ls -l 合計 4 -rw-r--r--. 1 root root 328 6月 11 11:32 Dockerfile # docker build -f ./Dockerfile -t centos:c71apache01 --no-cache=true .
Apache Webサーバー入りのDockerイメージ「c71apache01」が作成されているかを確認します。
[root@ml115g5 apache]# docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE centos c71apache01 89a496bc9082 38 seconds ago 384.2 MB docker.io/centos centos7.1.1503 f1dade627e25 7 weeks ago 212.1 MB
作成したDockerイメージ「c71_apache01」を使ってDockerコンテナを起動します。今回起動するコンテナ名は、「web0001」としました。
# docker run -d --privileged --name web0001 -i -t -p 80:80 centos:c71apache01 /sbin/init cdb3c5da9d4e4f2d9c2bb2698234531a059384a160e8ff43c4a75591495a4ea4\
CentOS 7.1ベースのDockerイメージにおいて、コンテナ内でsystemdを使用する場合は、コンテナの起動オプションに、「--privileged」オプション、または、「--cap-add=SYS_ADMIN」オプションが必要になります。またコンテナの起動に指定するコマンドは、「/sbin/init」を指定します。コンテナが起動しているかどうかを確認します。
# docker ps -a CONTAINER ID IMAGE COMMAND ... STATUS PORTS NAMES cdb3c5da9d4e centos:c71apache01 "/sbin/init" ... Up 44 seconds 0.0.0.0:80->80/tcp web0001
コンテナ「web0001」が起動していることがわかります。ホストOSからコンテナ「web0001」にログインします。バックグランドで起動しているコンテナへのログインは、docker execで行います。docker execでは、現在稼働しているコンテナ名(ここではweb0001)を指定します。今回は、稼動中のコンテナにログインして、コマンドプロンプトからコマンドラインによる入力作業を行うため、/bin/bashを指定します。
# docker exec -i -t web0001 /bin/bash [root@cdb3c5da9d4e /]#
プロンプトが変化し、コンテナにログインできていますので、コンテナ上でApache Webサービスが起動しているかを確認します。
[root@cdb3c5da9d4e /]# systemctl status httpd |grep active Active:active (running) since Thu 2015-06-11 02:52:07 UTC; 3min 29s ago
コンテナがhttpdサービスを正常に起動できていることを確認できたら、コンテナに割り振られたIPアドレスをコンテナ上で確認します。以下では、コンテナweb0001に、IPアドレス172.17.0.26/16が割り振られていることがわかります。
[root@cdb3c5da9d4e /]# ip a |grep inet inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host inet 172.17.0.26/16 scope global eth0 inet6 fe80::42:acff:fe11:1a/64 scope link
コンテナが外部にWebサービスを提供できているかをホストマシンから確認します。コマンドラインから確認するには、curlコマンドが有用です。
# curl http://172.17.0.26/index.html Hello Apache. #
[補足]
稼働中のコンテナのbashプロンプトを起動せずに、ホストOSから直接、コンテナ内のコマンドを実行することも可能です。例えば、ホストOSから、上記のweb0001コンテナにインストールされているipコマンドを使ってweb0001コンテナのIPアドレスを調べる場合は、以下のようにdocker execで直接ipコマンドを指定することができます。
# docker exec -i -t web0001 ip a inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host inet 172.17.0.26/16 scope global eth0 inet6 fe80::42:acff:fe11:1a/64 scope link