基本
コンテナイメージの自動作成手順をまとめたのが、Dockerfileになります。 中身は以下のようなテキストになります。
# Dockerfile sample FROM docker.io/centos:6 MAINTAINER vagrant ADD hosts /etc/hosts RUN yum -y install screen CMD service iptables stop && bash
Dockrefaleでは実行する命令を上から順番に書いていきます。 上記の命令は、上から順に、"FROM"、"MAINTAINER”、"ADD"、"RUN"、"CMD"となります。 各命令の右側がDockerfileの命令のパラメータになります。
Dockerfileの命令
Dockerfileの主な命令は以下になります。
FROM | 作成元のコンテナイメージ |
MAINAINER | 作成者の名前 |
ENV | RUNコマンド実行時の環境変数を設定します。 |
RUN | 指定コマンドを実行します。※ |
ADD | コンテナの中にファイルをコピーします。 |
EXPOSE | コンテナの中で動作するプログラムが使用するポートを登録 |
CMD/ENTRYPOINT | コンテナが起動したときに実行される命令を指定 |
※RUNコマンドは複数指定することができますが、1個につき中間イメージ1個が作成されます。 そのため、RUNコマンドを減らせば、使用ディスク容量が減ります。
-
サンプル
開発用MySQLサーバーのDockerfileサンプルです。 MySQLは、公式レポジトリからyumでインストールします。
# Dockerfile for MySQL server # docker build -t my:mysql ./mysql/ FROM docker.io/centos:6 MAINTAINER vagrant # MySQL 5.6 RUN yum -y install http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm RUN yum -y install mysql-community-server EXPOSE 3306 # MySQL initialize RUN service mysqld start && mysql -e "GRANT ALL ON *.* to 'root'@'%'; FLUSH PRIVILEGES;" && service mysqld stop ADD init.sh /usr/local/bin/init.sh RUN chmod u+x /usr/local/bin/init.sh CMD ["/user/lobal/bin/init.sh"]
init.shは、Dockerのstopコマンドでmysqlサーバーを停止するためのものです。
#!/bin/bash cat <<EOF >> ~/.bashrc trap 'service mysqld stop; exit 0' TERM EOF exce /bin/bash参考 コンテナ停止時にサービスが停止しない
Dockerfileとinstall.shを同じディレクトリに置くと、buildコマンドでコンテナイメージを作成できます。 今回の例では、mysqlというディレクトリを作成し、そこにDockerfileとinstall.shファイルを置き、そのディレクトリを指定してbuildコマンドを実行します。
# docker build -t my:mysql ./mysql/
トラブル
-
サービスが起動しない
runコマンドでは、コンテナで実行するコマンドを指定できますが、これを指定するとDockerfileのCMDが実行されません。 DockerfileのCMD命令でサービスの起動を指定している場合、サービスが止まったままになります。
# docker run -itd --name mysql my:mysql /bin/bash
対策としては、runコマンドで実行コマンドを指定しないか、DockerfileのCMDをENTRYPOINTに変更するかになります。
ENTRYPOINT ["/usr/local/bin/init.sh"]
コンテナ停止時にサービスが停止しない
コンテナを停止して再度起動したとき、mysqldのログをみると、mysqlサーバーが正常にシャットダウンしていなくて、 リカバリー処理が実行さたと記録されていました。 stopコマンドでコンテナを停止しても、コンテナで動作しているサービスは自動で停止しないようです。
2016-04-11 03:13:56 250 [Note] InnoDB: Database was not shutdown normally!
2016-04-11 03:13:56 250 [Note] InnoDB: Starting crash recovery.
2016-04-11 03:13:56 250 [Note] InnoDB: Reading tablespace information from the .i
bd files...
2016-04-11 03:13:56 250 [Note] InnoDB: Restoring possible half-written data pages
2016-04-11 03:13:56 250 [Note] InnoDB: from the doublewrite buffer...
2016-04-11 03:13:56 250 [Note] InnoDB: 128 rollback segment(s) are active.
2016-04-11 03:13:56 250 [Note] InnoDB: Waiting for purge to start
2016-04-11 03:13:56 250 [Note] InnoDB: 5.6.29 started; log sequence number 1626007
...
参考 mysqlが正常終了した場合、以下のようなメッセージがログに記録されます。
2016-04-11 03:16:27 250 [Note] /usr/sbin/mysqld: Normal shutdown
そこで調べると、stopコマンドはコンテナ内のプロセスID:1のプロセスを停止して終了するだけのようです。 そのため、Dockerのstopコマンドでサービスも停止したい場合は、対策が必要になります。
一つの方法として、DockerfileのCMDで以下のようなシェルスクリプト(init.sh)を実行する方法があります。
#!/bin/bash cat <<EOF >> ~/.bashrc trap 'service mysqld stop; exit 0' TERM EOF exec /bin/bashこれは、停止させられるコンテナのプロセス(プロセスID 1)が、子プロセスにTERMシグナルを送るのを利用しています。
参考
※参考サイトは、参考書籍「 Docker実践入門――Linuxコンテナ技術の基礎から応用まで 」の著者で、本に詳細な説明があります。