DockerfileのONBUILD

Docker 0.8においてONBUILDというDockerfile用のコマンドが導入された.0.8ではOSXのdocker clientが脚光を浴びたが,このONBUILDはかなり強力な機能.リリースノートはこちらONBUILDの公式ドキュメントはこちら

ONBUILDを使うと,次のビルドで実行するコマンドをイメージに仕込むことができるようになる.つまり,ベースイメージにONBUILDによるコマンドを仕込み,別のDockerfileでそのベースイメージを読み込みビルドした際に,そのコマンドを実行させるということが可能になる.要するに,親DockerfileのDockerfileコマンドを子Dockerfileのビルド時に実行させることができる機能.

これは,アプリケーション用のイメージを作るときや,ユーザ特有の設定を組み込んだデーモン用のイメージを作るときなどに有用になる.また,オリジナルのHerokuのBuildpack的なものを作ることもできる.

言葉では伝えられないので簡単に動作例を示す.例えば,以下のようなDockerfile.baseを準備する.

# Docekerfile.base
FROM ubuntu
ONBUILD RUN echo "See you later"

これをtcnksm/echo_baseという名前でビルドする.

$ docker build -t tcnksm/echo_base - < Dockerfile.base
Step 0 : FROM ubuntu
Pulling repository ubuntu
...
f323cf34fd77: Download complete
---> 9cd978db300e
Step 1 : ONBUILD RUN echo "See you later"
---> Running in 9e42ede94d60
---> e18fdd8d9fa8

RUN echoは実行されていない.

次に,このtcnksm/echo_baseを基にした別のイメージを作成するDockerfileを準備する.

FROM tcnksm/echo_base

tcnksm/echoという名前でビルドする.

$ docker build -t tcnksm/echo .
Uploading context 3.584 kB
Uploading context
Step 0 : FROM tcnksm/base
# Executing 1 build triggers
Step onbuild-0 : RUN echo "See you later"
---> Running in cddf3cf85ff8
See you later
---> 9f0189c1e902
---> 9f0189c1e902
Successfully built 9f0189c1e902

ベースイメージtcnksm/echo_baseで仕込んだRUN echo ..が実行された.これがONBUILDの機能.

では,実際の開発プロセスにおいてどのように使えるか.

Apache base image

/var/www以下のhtdocsを表示する単純なDockerアプリーションを作るとする.この場合Dockerfileには,apacheのインストール,Apacheの起動コマンドの登録,/var/www/以下へのhtdocsの追加などを書くことになる.あとはこのDockerfileをコピーしてビルドすれば,どこでもこのアプリケーションを動作させることができる.

新しくhtdocsを更新したい場合は,ビルドし直す,scpできるようにしてファイルをコンテナ内にぶっ込む,volume機能を使ってファイルをマウントする,などが考えられる.

ONBUILDを使えば,ファイルの更新を考慮したイメージを作成することができる.つまり,親DockerfileでApacheのインストールなどの基本的なConfigurationを行う一方で,更新がかかるhtdocsの/var/www/への追加は子Dockerfileのビルド時に実行させることが可能になる.これを実現する親Dockerfileは以下のようになる.

# Dockerfile.base
FROM ubuntu:12.04

RUN apt-get update
RUN apt-get install -y apache2

ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
ENV APACHE_LOG_DIR /var/log/apache2

ONBUILD ADD . /var/www/

EXPOSE 80
ENTRYPOINT ["/usr/sbin/apache2"]
CMD ["-D", "FOREGROUND"]

カレントディレクトリを/var/wwwに追加する部分をONBUILDで記述する.あとは,ベースイメージをビルドし,レジストリにpushしておく

$ docker build -t tcnksm/apache_base - < Dockerfile.base
$ docker push

Apache application image

htdocsを開発する.

$ echo "<h1>Hello, docker</h1>" > index.html

開発が終了したら,以下のようなDockerfileを準備しビルドする.

FROM tcnksm/apache_base
$ docker build -t tcnksm/apache .

ビルドすると,親Dockerfileで記述したONBUILDが実行され,カレントディレクトリのhtdocsがイメージの/var/www/以下に追加される.あとは,このイメージを好きなところにデプロイして起動するだけ.

$ docker run -p 80:80 tcnksm/apache

開発方法

htdocsの開発中に実際にapacheを起動して,ブラウザで動作確認などができるとよい.以下のようにvolumeでカレントディレクトリをベースイメージの/var/wwwにマウントして起動すれば,リアルタイムで更新を確認しつつ開発を進めることができる.

$ docker run -p 80:80 -v $(pwd):/var/www -t tcnksm/apache_base

vagrant shareのように外部の開発者とやり取りしつつ開発したいなら,ngrokを使ってDocker share的なこともできる.

開発が終了したら,上のDockerfileを使って最終イメージをビルドし,イメージをデプロイする.例えば,Orchardにデプロイするには以下のようにする(Orchardの使い方は,“OrchardにDockerアプリケーションをデプロイ”に書いた).

$ orchard docker build -t tcnksm/apache .
$ orchard docker run -d -p 80:80 tcnksm/apache

参考