• TOP
  • ブログ
  • デザイナー、コーダーのための Docker 入門(2)イメージの作成

ブログ

デザイナー、コーダーのための Docker 入門(2)イメージの作成

はじめに

こんにちは、技術グループの marunaga です。前回の記事では Docker の導入から、公開されているイメージを用いて Docker コンテナを起動するまでの一連の流れをご紹介しました。

今回は自分自身でオリジナルの Docker イメージを作成し、複数のコンテナを連携させて WEB アプリケーションを動作させるまで流れを追っていきたいと思います。事前に Boot2Docker を起動させておく必要がありますので、以下の 2 つのコマンドを実行しておきます。

$ boot3docker start
$ $(boot2docker shellinit)


また、ホスト PC のディレクトリをマウントさせるためのシェルスクリプトも実行しておいて下さい。

Docker イメージを作成するには


Docker イメージを作成するためには Dockerfile という設定ファイルに環境構築のための設定を記述して、docker build というコマンドを用いて行います。ほとんどの場合は Docker Hub Registory で公開されている既存のイメージをベース利用し、必要な機能を追加して作成していきます。

コマンドは以下のフォーマットで実行します。

$ docker build -t <image tag> <dockerfile dir>


各オプションは以下のとおり。

  • -t <image tag>:イメージを特定するためのタグを設定します(以降の例では ings/httpd-mt というタグをつけています)。
  • <dockerfile dir>Dockerfile が保存されているディレクトリを指定します。

MovableType 用の Apache のコンテナを作成する


では、早速イメージを作成してみましょう。これから挙げる例では、公式の Debian Wheezy のイメージをもとに、Apache や perl モジュールなどをインストールし、MovableType が動作するイメージを作成します。

必要な設定ファイルを以下のディレクトリ構成でカレントディレクトリに配置して下さい。

.
├── www/
│ └── htdocs/ ... Apache のドキュメントルート
└── recipes/
└── httpd-mt/ ... MT 用 Apache サーバ作成用のファイル
├── Dockerfile
├── localhost.conf
└── localhost-ssl.conf


Dockerfile の内容は以下のとおりです。

# 公式の Debian の wheezy 版のイメージを使用する
FROM debian:wheezy

# apt を アップデート
RUN apt-get update

# --------------------------------
# mysql の設定
# --------------------------------

RUN apt-get -y install mysql-client

# --------------------------------
# perl モジュールの設定
# --------------------------------

# perl モジュールのインストールに必要なパッケージ
RUN apt-get -y install curl make gcc libxml2-dev libssl-dev libexpat1-dev zip

# cpanminus のインストール
RUN curl -L https://cpanmin.us | perl - App::cpanminus

RUN cpanm \
Plack \
CGI::PSGI \
CGI::Parse::PSGI \
XMLRPC::Transport::HTTP::Plack \
Imager \
IPC::Run \
Crypt::DSA \
XML::SAX::ExpatXS \
XML::LibXML::SAX \
Archive::Zip

# --------------------------------
# apache の設定
# --------------------------------

RUN apt-get -y install apache2

# セキュリティの設定を書き換え
RUN sed -i \
-e 's/ServerTokens OS/ServerTokens Prod/g' \
-e 's/ServerSignature On/ServerSignature Off/g' \
/etc/apache2/conf.d/security

# ポートの設定を書き換え
RUN sed -i \
-e '/Listen 443$/i \ \ \ \ NameVirtualHost *:443' \
/etc/apache2/ports.conf

# SSL の設定を書き換え
RUN sed -i \
-e 's/SSLProtocol all -SSLv2/SSLProtocol All -SSLv2 -SSLv3/g' \
-e 's/#SSLStrictSNIVHostCheck On/SSLStrictSNIVHostCheck Off/g' \
/etc/apache2/mods-available/ssl.conf

# デフォルトのバーチャルホストの設定を無効化
RUN a2dissite default

# バーチャルホストの設定をコピーして、サイトを有効化し、ディレクトリを作成
ADD localhost.conf /etc/apache2/sites-available/localhost
RUN a2ensite localhost && mkdir /var/www/htdocs

# バーチャルホストの SSL の設定をコピーして、SSL モジュールとサイトを有効化
ADD localhost-ssl.conf /etc/apache2/sites-available/localhost-ssl
RUN a2enmod ssl && a2ensite localhost-ssl

# --------------------------------
# 後始末と起動処理
# --------------------------------

# パッケージをインストールした時のファイルを削除
RUN apt-get autoclean

# 80、443 番ポートを開放
EXPOSE 80 443

# apache を起動
CMD ["/usr/sbin/apache2ctl","-DFOREGROUND"]

localhost.conf の内容は以下のとおりです。

<VirtualHost *:80>

# ------------------
# ディレクトリ毎の設定
# ------------------

DocumentRoot /var/www/htdocs

<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>

<Directory /var/www/htdocs>
Options -Indexes +ExecCGI
AllowOverride None
AddType application/x-httpd-cgi .cgi
Order allow,deny
allow from all
</Directory>

# ------------------
# ログの設定
# ------------------

LogLevel warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

</VirtualHost>

localhost-ssl.conf の内容は以下のとおりです。

<IfModule mod_ssl.c>

# SNI(Server Name Indication)で SSL サイトを設定しているので、
# Windows XP 環境などでは正常に動作しない。
# 参考:<http://e-garakuta.net/techinfo/doku.php/linux/apache-sni>

<VirtualHost *:443>

# ------------------
# SSL の基本設定
# ------------------

SSLEngine on

# 認証用のファイルの設定(デフォルトのサイトで用意されていたものを使用)
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

# ------------------
# ディレクトリ毎の設定
# ------------------

DocumentRoot /var/www/htdocs

<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>

<Directory /var/www/htdocs>
Options -Indexes +ExecCGI
SSLOptions +StdEnvVars
AllowOverride None
AddType application/x-httpd-cgi .cgi
Order allow,deny
allow from all
</Directory>

<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>

# ------------------
# ログの設定
# ------------------

LogLevel warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

# ------------------
# その他の設定
# ------------------

# ie 向けの SSL 不具合対策
BrowserMatch ".*MSIE [2-5]\..*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0
BrowserMatch ".*MSIE [6-9]\..*" ssl-unclean-shutdown
BrowserMatch ".*MSIE [1-9][\d]+\..*" ssl-unclean-shutdown

</VirtualHost>

</IfModule>

それぞれのファイルの準備ができたら Dockerfile をもとにイメージをビルドします(しばらく時間がかかりますので、やりかけのお仕事の続きなどをどうぞ...)。

$ docker build -t ings/httpd-mt ./recipes/httpd-mt/


ビルドが完了しましたら、作成したイメージを元にコンテナを実行します。事前に、カレントディレクトリの ./www/htdocs/mt 以下に Movable Type の本体を設置しておいて下さい。

$ docker run --name httpd-mt -v $(pwd)/www:/var/www -p 8080:80 -p 4443:443 -itd ings/httpd-mt


起動が完了したら、前回 のように http://192.168.xx.xx:8080/mt/ にアクセスすることで Movable Type の動作を確認することができます。

01.png

インストール画面が表示されていますね!

MySQL コンテナ と MovableType 用の Apache のコンテナを連携させる


インストール画面が表示されたら、あとは初期設定をするだけ...といきたいところなのですが、このコンテナには MySQL がインストールされていないため、データベースの設定より先には進めなくなってしまいます。何らかの形で MySQL の環境を用意しなければなりません。

先ほどの Dockerfile に「MySQL をインストールする記述を追加してもう一度ビルドし直す」という方法もありますが、今回は別の方法をとってみようと思います。

Docker では、「1 つのコンテナで 1 つのアプリケーションを動作させて、それらを連携させて使用する」ことが推奨されています(例えば、Movable Type のコンテナと、MySQL のコンテナという具合に)。具体的には、コンテナ同士を連携させる仕組みとして、docker run コマンドには --link というオプションが用意されていますのでこれを使うことで実現します。

まずは前回の公式の Apache イメージを利用した時と同様に、公式の MySQL 用のコンテナmysql-mt という名前で起動させます。

$ docker run --name mysql-mt -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mt -e MYSQL_USER=mt -e MYSQL_PASSWORD=mt -e MYSQL_DATABASE=mt -itd mysql


いくつかの -e オプションが渡されていますが、これは環境変数を指定するためのオプションです。具体的には以下の内容の設定を行っています。

  • -e MYSQL_ROOT_PASSWORD=mt:MySQL の root ユーザーのパスワードを mt に設定しています。
  • -e MYSQL_USER=mt:Movable Type 用に専用のユーザー mt を作成しています。
  • -e MYSQL_PASSWORD=mt:Movable Type 用に専用のデータベースのパスワードを mt に設定しています。
  • -e MYSQL_DATABASE=mt:Movable Type 用に専用のデータベース mt を作成しています。


次に先ほど立ち上げた MovableType 用の Apache コンテナ一旦破棄し、先述の --link オプションを設定して起動し直します。

↓ コンテナの停止と破棄します。

$ docker stop httpd-mt && docker rm httpd-mt


↓ コンテナを再度起動します。

$ docker run --name httpd-mt --link mysql-mt:mysql-mt -v $(pwd)/www:/var/www -p 8080:80 -p 4443:443 -itd ings/httpd-mt


--link オプションは --link <container name>:<alias name> という形式で指定することで、連携させる MySQL 用のコンテナを Apache コンテナから参照可能な状態にします。無事に起動したら、先程と同様にブラウザから Movable Type の管理画面にアクセスし、データベースの設定画面に進みます。

02.png

この画面では先ほど MySQL コンテナを起動した時の値を元に、以下のように設定します。

  • データベースの種類:MySQLデータベース(推奨)
  • データベースサーバ:mysql-mt
  • データベース名:mt
  • ユーザー名:mt
  • パスワード:mt


入力後「接続テスト」をクリックして以下の画面が表示されれば、コンテナ同士のリンク成功です!

03.png

ちなみに、コンテナの連携どのように実現させているのでしょうか。その仕組みは、--link オプションを指定したコンテナの中身を見てみることで確認することができます。

以下のコマンドで動作中の Movable Type 用の Apache コンテナの /etc/hosts を確認してみると、

$ docker exec httpd-mt cat /etc/hosts

172.17.0.34 a507942cba07
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.3 mysql-mt

のように 172.17.0.3 mysql-mt の項目が追加されており、mysql-mt の名前で MySQL コンテナにアクセスできるようになっていることがわかります。

Docker コンテナのデータの永続化について


ここまでで Movable Type 用の環境を手軽に動作させる事ができるようになりました。しかし、Docker コンテナは一度停止して破棄してしまうと、それまで内部に保存されたデータまで破棄されてしまうという特徴があります。これは必要があるときに起動し、必要がなくなれば削除すればよい、という考え方に基づいたものなのですが、このままでは色々と支障があります。データ永続化の方法にも様々な手段があるのですが、今回は以下の 2 つを試してみました。

  1. ホスト(Mac)側のディレクトリをマウントし、その中にデータを保存する。
  2. データ保存のためだけのコンテナ(Data Volume Container)を作成し、その中にデータを保存する。


それぞれのパターンを、先ほどの MySQL コンテナ と MovableType 用の Apache のコンテナの連携のケースで実施してみます。

1. ホスト(Mac)側ディレクトリのマウントを利用しての永続化


これは MySQL のデータそのものをマウントしたホスト PC のディレクトリに保存してしまうという方法です。先ほどの MySQL のコマンドに、-v オプションでホスト PC のディレクトリをマウントさせます。コンテナ側のディレクトリには /var/lib/mysql という MySQL がデータを保存するディレクトリを指定しています。

$ docker run --name mysql-mt -v $(pwd)/www/mysql:/var/lib/mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mt -e MYSQL_USER=mt -e MYSQL_PASSWORD=mt -e MYSQL_DATABASE=mt -itd mysql


このようにすることで、MySQL のデータは ./www/mysql 以下に出力され、再度起動するときも同じディレクトリをマウントすることでデータをたとえコンテナを破棄したとしてもデータを残すことができます。

2. Data Volume Container を用いたデータの永続化


これは Docker が推奨する方法で、Data Volume Container という、保存領域を提供するのみの役割をもつコンテナのディレクトリを他のコンテナからマウントさせて、そこにデータを保存するという方法です。少しわかりにくいので、

  1. データコンテナを作成し、データコンテナに MySQL コンテナを紐付ける。
  2. MySQL コンテナを Apache コンテナをリンクさせ、Movable Type のウェブサイトを作成する。
  3. データコンテナのバックアップを取り、別のコンテナに復元する。
  4. 別のデータコンテナを参照して MySQL コンテナを起動させ、ウェブサイトの内容を編集する。
  5. 元のデータコンテナに切り替えてウェブサイトの内容を確認する。


という手順を行ってみたいと思います。

まずはデータコンテナを作成します。
このコンテナ上で特に操作をする必要はないので、Docker 上で動作するための最小限の構成で作成されている公式のイメージ busybox を使用します。

$ docker run --name mysql-data-1 -v /var/lib/mysql busybox:latest


上記の例にあるように、データ保存のために使用するディレクトリを -v オプションで指定しておきます。また、コンテナは起動指定なくてもよいので、-itd オプションは不要です。

次に、MySQL 用のコンテナを起動します。起動時に --volumes-from という他のコンテナのディレクトリを参照させるオプションを設定して起動します。

$ docker run --name mysql-mt --volumes-from mysql-data-1 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mt -e MYSQL_USER=mt -e MYSQL_PASSWORD=mt -e MYSQL_DATABASE=mt -itd mysql


--volumes-from を指定することで、MySQL 用のコンテナの /var/lib/mysql ディレクトリに、データコンテナの /var/lib/mysql ディレクトリがマウントされています。

次に、MovableType 用の Apache のコンテナを MySQL 用のコンテナとリンクさせて起動します。これは先程の例と同じです。

$ docker run --name httpd-mt --link mysql-mt:mysql-mt -v $(pwd)/www:/var/www -p 8080:80 -p 4443:443 -itd ings/httpd-mt


起動したらブラウザから Movable Type の管理画面にアクセスして初期設定を行い、「First Website」を作成してみましょう。

04.png

05.png

06.png

無事にウェブサイトが作成できました。

次に、別のデータコンテナにデータを復元するために、一旦データコンテナ内のデータをエクスポートします。以下はその一例で、データエクスポート用のコンテナをデータコンテナをマウントしたうえで一時的に起動し、必要なファイルを圧縮してホスト PC 側に保存する例です(--rm オプションを付けることで役割を終えたあとにすぐ削除するようにしています)。

$ docker run --rm --volumes-from mysql-data-1 -v "$(pwd)/www/backup":/backup busybox:latest tar cvf /backup/var_lib_mysql.tar /var/lib/mysql


コマンドが終了すると、./www/backup/var_lib_mysql.tar というファイルが出来上がっているはずです。今度はデータ復元用のデータコンテナを起動します。

$ docker run --name mysql-data-2 -v /var/lib/mysql busybox:latest


そして、エクスポートの際と同様にデータコンテナにデータを復元するためのコンテナを一時的に起動し、圧縮された ./www/backup/var_lib_mysql.tar ファイルを解凍します。

$ docker run --rm --volumes-from mysql-data-2 -v "$(pwd)/www/backup":/backup busybox:latest tar xvf /backup/var_lib_mysql.tar


その後、MySQL 用コンテナを新しいデータコンテナをマウントするように起動して、Apache 用コンテナを起動し直し、Movable Type の管理画面からブログを作成します。

$ docker run --name mysql-mt --volumes-from mysql-data-2 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mt -e MYSQL_USER=mt -e MYSQL_PASSWORD=mt -e MYSQL_DATABASE=mt -itd mysql
$ docker run --name httpd-mt --link mysql-mt:mysql-mt -v $(pwd)/www:/var/www -p 8080:80 -p 4443:443 -itd ings/httpd-mt


07.png

そして、再度、元のデータコンテナを使って MySQL 用コンテナを立ち上げ直し、Movable Type の管理画面にアクセスします。

$ docker run --name mysql-mt --volumes-from mysql-data-1 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mt -e MYSQL_USER=mt -e MYSQL_PASSWORD=mt -e MYSQL_DATABASE=mt -itd mysql

$ docker run --name httpd-mt --link mysql-mt:mysql-mt -v $(pwd)/www:/var/www -p 8080:80 -p 4443:443 -itd ings/httpd-mt


08.png

すると作成したブログがなくなっていて、データが切り替わっているということが確認できます。
ちょっと煩雑な手順にはなりますが、このようにしてもデータの永続化と復元を実施することができます。

コマンドを何度も実行しなければならないので、かなり煩わしいですね。。次回はコンテナの連携をスムーズに行うための方法をご紹介したいと思います。

目次