Dockerfile リファレンス
Docker は Dockerfile からの指示を読み取ることによって自動的にイメージをビルドすることができます。Dockerfile は、ユーザーがコマンドラインで呼び出すことができるすべてのコマンドを含むテキストドキュメントです。このページでは、Dockerfile で使用できるコマンドについて説明します。
概要
Dockerfile は以下の指示をサポートしています:
指示 | 説明 |
---|---|
ADD | ローカルまたはリモートのファイルおよびディレクトリを追加します。 |
ARG | ビルド時の変数を使用します。 |
CMD | デフォルトコマンドを指定します 。 |
COPY | ファイルおよびディレクトリをコピーします。 |
ENTRYPOINT | デフォルト実行可能ファイルを指定します。 |
ENV | 環境変数を設定します。 |
EXPOSE | アプリケーションがリッスンしているポートを説明します。 |
FROM | ベースイメージから新しいビルドステージを作成します。 |
HEALTHCHECK | 起動時にコンテナの健康をチェックします。 |
LABEL | イメージにメタデータを追加します。 |
MAINTAINER | イメージの作者を指定します。 |
ONBUILD | イメージがビルドで使用される際の指示を指定します。 |
RUN | ビルドコマンドを実行します。 |
SHELL | イメージのデフォルトシェルを設定します。 |
STOPSIGNAL | コンテナを終了するためのシステムコールシグナルを指定します。 |
USER | ユーザIDおよびグループIDを設定します。 |
VOLUME | ボリュームマウントを作成します。 |
WORKDIR | 作業ディレクトリを変更します。 |
ADD
ADD
指示と COPY
は基本的に同じ形式と性質を持っています。しかし、ADD
は COPY
の上にいくつかの追加機能を加えます。
例えば、<source path>
が URL
である場合、Docker エンジンはこのリンクからファイルをダウンロードして <target path>
に配置しようとします。ダウンロードされたファイルの権限は自動的に 600
に設定されます。これが望ましい権限でない場合は、権限を調整するために追加の RUN
レイヤーが必要になります。さらに、ダウンロードされたファイルが圧縮アーカイブの場合、抽出するために追加の RUN
レイヤーも必要です。したがって、RUN
指示を直接使用し、wget
または curl
ツールを使用してダウンロードし、権限を処理し、抽出し、不要なファイルをクリーンアップする方が合理的です。このような機能は実際には実用的ではないため、使用することはお勧めできません。
<source path>
が tar
圧縮ファイルであり、圧縮形式が gzip
、bzip2
、または xz
の場合、ADD
指示はこの圧縮ファイルを自動的に <target path>
に解凍します。
いくつかのケースでは、公式の ubuntu
イメージのように、この自動解凍機能が非常に便利です:
FROM scratch
ADD ubuntu-xenial-core-cloudimg-amd64-root.tar.gz /
...
しかし、圧縮ファイルを解凍せずにコピーしたいと本当に思っている場合、ADD
コマンドを使用することはできません。
Docker 公式の Dockerfile ベストプラクティスドキュメントによると、可能な限り COPY
を使用する必要があります。COPY
の意味は非常にクリアであり、単にファイルをコピーするだけですが、ADD
にはより複雑な機能が含まれており、その振る舞いがクリアでない場合があります。ADD
に最適な使用ケースは、前述の自動解凍が必要な場合です。
さらに、ADD
指示はイメージビルドキャッシュを無効にする原因となることが注意されるべきであり、これによってイメージビルドプロセスが遅くなる可能性があります。
したがって、COPY
と ADD
の指示を選ぶ際には、この原則に従うことができます:すべてのファイルコピー操作に COPY
指示を使用し、自動解凍が必要な場合のみ ADD
を使用してください。
この指示を使用する際には、--chown=<user>:<group>
オプションを追加して、ファイルの所有者ユーザーとグル ープを変更することもできます。
ADD --chown=55:mygroup files* /mydir/
ADD --chown=bin files* /mydir/
ADD --chown=1 files* /mydir/
ADD --chown=10:11 files* /mydir/
ARG
フォーマット: ARG <parameter_name>[=<default_value>]
ARG
命令は、ENV
と同じ効果を持ちますが、両者とも環境変数を設定します。違いは、ARG
によってビルド環境で設定された環境変数は、コンテナが実行されているときには存在しないという点です。ただし、この理由だけで ARG
をパスワードやその他の機密情報を保存するために使用しないでください。なぜなら、docker history
はすべての値を表示できるためです。
Dockerfile の ARG
命令は、パラメータ名とそのデフォルト値を定義します。このデフォルト値は、docker build
コマンドで --build-arg <parameter_name>=<value>
としてオーバーライドできます。
ARG
命令を柔軟に使用することで、Dockerfile を変更せずに異なるイメージをビルドできます。
ARG
命令には効果のスコープがあります。FROM
命令の前に指定された場合、FROM
命令でのみ使用できます。
ARG DOCKER_USERNAME=library
FROM ${DOCKER_USERNAME}/alpine
RUN set -x ; echo ${DOCKER_USERNAME}
上記の Dockerfile を使用すると、${DOCKER_USERNAME}
変数の値は出力されません。正しく出力するには、FROM
の後で再度 ARG
を指定する必要があります。
# FROM のみで有効
ARG DOCKER_USERNAME=library
FROM ${DOCKER_USERNAME}/alpine
# FROM の後で使用するには、再度指定する必要があります
ARG DOCKER_USERNAME=library
RUN set -x ; echo ${DOCKER_USERNAME}
マルチステージビルドの場合、この問題に特に注意してください。
# この変数は各 FROM で有効です
ARG DOCKER_USERNAME=library
FROM ${DOCKER_USERNAME}/alpine
RUN set -x ; echo 1
FROM ${DOCKER_USERNAME}/alpine
RUN set -x ; echo 2
上記の Dockerfile では、両方の FROM
命令で ${DOCKER_USERNAME}
を使用できます。各ステージで使用される変数は、各ステージで個別に指定する必要があります。
ARG DOCKER_USERNAME=library
FROM ${DOCKER_USERNAME}/alpine
# FROM の 後で変数を使用するには、各ステージで個別に指定する必要があります
ARG DOCKER_USERNAME=library
RUN set -x ; echo ${DOCKER_USERNAME}
FROM ${DOCKER_USERNAME}/alpine
# FROM の後で変数を使用するには、各ステージで個別に指定する必要があります
ARG DOCKER_USERNAME=library
RUN set -x ; echo ${DOCKER_USERNAME}
CMD
CMD
命令には RUN
と似た形式があり、次の2つの形式があります。
shell
形式:CMD <command>
exec
形式:CMD ["executable", "param1", "param2"...]
- パラメータリスト形式:
CMD ["param1", "param2"...]
。ENTRYPOINT
命令が指定された後に実際のパラメータを指定するために使用されます。
以前コンテナについて紹介した時、Dockerは仮想マシンではなく、コンテナはプロセスであると言及しました。それらはプロセスなので、コンテナを起動する際にはプログラムとそのパラメータを指定する必要があります。CMD
命令は、コンテナのメインプロセスのデフォルトの起動コマンドを指定するために使用されます。
実行時には、イメージで設定されたこのデフォルトコマンドを新しいコマンドで置き換えることができます。例えば、ubuntu
イメージのデフォルトのCMD
は /bin/bash
です。もし私たちが直接 docker run -it ubuntu
を実行すると、bash
に入ります。また、実行時に異なるコマンドを指定することもできます。例えば docker run -it ubuntu cat /etc/os-release
とすると、デフォルトの /bin/bash
コマンドを cat /etc/os-release
に置き換えて、システムのバージョン情報を出力します。
命令形式については、一般的に exec
形式が推奨されます。これは解析時にJSON配列として解析されるため、ダブルクォート "
を使用する必要があり、シングルクォートは使用できません。
shell
形式を使用する場合、実際のコマンドは sh -c
の引数としてラップされて実行されます。例えば:
CMD echo $HOME
実際の実行時には、以下のようになります:
CMD [ "sh", "-c", "echo $HOME" ]
これは、これらの環境変数がシェルによって解析され、処理されるために、環境変数を使用できる理由です。
CMD
について言及すると、コンテナ内のアプリケーションがフォアグラウンドで実行されるべきか、バックグラウンドで実行されるべきかという問題が避けられません。これは初心者にとって一般的な混乱です。
Dockerは仮想マシンではなく、コンテナ内のアプリケーションはフォアグラウンドで実行されるべきです。仮想マシンや物理マシンでは systemd
を使用してバックグラウンドサービスを起動するのとは異なり、コンテナの中にはバックグラウンドサービスの概念はありません。
いくつかの初心者は CMD
を以下のように書きます:
CMD service nginx start
そして、実行後すぐにコンテナが終了することに気づきます。コンテナ内で systemctl
コマンドを使用しても、全く実行できないことがわかります。これは、フォアグラウンドとバックグラウンドの概念を理解しておらず、コンテナと仮想マシンの違いを区別せず、コンテナを従来の仮想マシンの視点から理解しようとしているためです。
コンテナのスタートアッププログラムはコンテナアプリケーションプロセスです。コンテナはメインプロセスのために存在し、メインプロセスが終了すると、コンテナも目的を失い、同様に終了します。他の補助プロセスは、気にする必要のないものです。
service nginx start
コマンドを使用することは、initシステムがnginxサービスをバックグラウンドデーモンプロセスとして起動しようとする試みです。先に述べたように、CMD service nginx start
は CMD [ "sh", "-c", "service nginx start"]
と解釈されるため、実際のメインプロセスは sh
です。service nginx start
コマンドが終了すると、sh
も終了し、メインプロセスが終了し、自然とコンテナが終了します。
正しいアプローチは、直接 nginx
実行ファイルを実行し、それをフォアグラウンドで実行することを要求することです。例えば:
CMD ["nginx", "-g", "daemon off;"]
COPY [--chown=<user>:<group>] <source_path>... <destination_path>
COPY [--chown=<user>:<group>] ["<source_path1>",... "<destination_path>"]
コマンドラインに似たフォーマットと、関数呼び出しに似たフォーマットの二つがあり、`RUN`命令と同様です。
`COPY`命令は、ビルドコンテキスト内の`<source_path>`からファイルやディレクトリを新しいイメージのレイヤーの`<destination_path>`へコピーします。例えば:
```bash
COPY package.json /usr/src/app/
<source_path>
は複数のパスにすることができ、ワイルドカードを使用することもできます。ワイルドカードルールはGoのfilepath.Match
ルールに準拠する必要があります。例えば:
COPY hom* /mydir/
COPY hom?.txt /mydir/
<destination_path>
はコンテナ内の絶対パスか、作業ディレクトリに対する相対パスにすることができます(作業ディレクトリはWORKDIR
命令を使用して指定できます)。コピー先のパスは事前に作成する必要はありません。ディレクトリが存在しない場合は、ファイルをコピーする前に作成されます。
加えて、COPY
命令を使用する際には、ソースファイルの様々なメタデータが保持されることに注意が必要です。例えば、読み取り、書き込み、実行権限やファイルの変更時間などです。この特徴はイメージのカスタマイズに役立ちます。特に、関連するファイルをGitで管理している場合に便利です。
この命令を使用する際には、--chown=<user>:<group>
オプションを追加して、ファイルの所有者とグループを変更することもできます。
COPY --chown=55:mygroup files* /mydir/
COPY --chown=bin files* /mydir/
COPY --chown=1 files* /mydir/
COPY --chown=10:11 files* /mydir/
ソースパスがフォルダーの場合、コピーする際に直接フォルダーをコピーするのではなく、フォルダーの内容を目的のパスにコピーします。
ENTRYPOINT
ENTRYPOINT
のフォーマットは、RUN
命令と同じで、exec
フォーマットとshell
フォーマットに分けられます。
ENTRYPOINT
の目的はCMD
と同じで、どちらもコンテナの起動プログラムとそのパラメータを指定するために使用されます。ENTRYPOINT
も実行時に置き換えることができますが、CMD
よりも少し手間がかかり、docker run
の--entrypoint
パラメータを使用して指定する必要があります。
ENTRYPOINT
が指定されると、CMD
の意味が変わります。それはもはや直接そのコマンドを実行するのではなく、ENTRYPOINT
命令に渡される引数としてCMD
の内容を扱います。言い換えれば、実行される際にはこのようになります:
<ENTRYPOINT> "<CMD>"
では、CMD
があるなら、なぜENTRYPOINT
が必要なのでしょうか?この<ENTRYPOINT> "<CMD>"
にはどのような利点があるのでしょうか?いくつかのシナリオを見てみましょう。
シナリオ1: イメージがコマンドのように振る舞うようにする
例えば、私たちの現在のパブリックIPアドレスを知るイメージが必要だとしましょう。まずCMD
を使用して実装することができます:
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
CMD [ "curl", "-s", "http://myip.ipip.net" ]
もしdocker build -t myip .
を使用してイメージをビルドし、現在のパブリックIPをクエリする必要がある場合、次のように実行するだけです:
$ docker run myip
現在のIP:8.8.8.8 カリフォルニア州アメリカ合衆国
さて、今ではコマンドとして イメージを使用できるように思えますが、通常コマンドには引数があります。引数を追加したい場合はどうでしょうか?上記のCMD
からわかるように、実際のコマンドはcurl
ですので、HTTPヘッダ情報を表示するためには-i
パラメータを追加する必要があります。docker run myip -i
に直接-i
パラメータを追加できますか?
$ docker run myip -i
docker: Error response from daemon: invalid header field value "oci runtime error: container_linux.go:247: starting container process caused \"exec: \\\"-i\\\": executable file not found in $PATH\"\n".
実行可能なファイルが見つからないというエラーが表示されていますが、先に述べたように、イメージ名の後に続くものはcommand
であり、実行時にデフォルトのCMD
の値を置き換えることになります。したがって、ここでは-i
が元のCMD
を置き換えてしまい、元のcurl -s http://myip.ipip.net
の最後に追加されるのではありません。しかし、-i
はコマンドではないので、当然見つかることはありません。
したがって、-i
パラメータを追加する場合は、完全なコマンドを再入力する必要があります:
$ docker run myip curl -s http://myip.ipip.net -i
これは明らかに良い解決策ではありませんが、ENTRYPOINT
を使用するとこの問題を解決できます。今度はENTRYPOINT
を使用してこのイメージを再実装してみましょう:
FROM ubuntu:18.04
RUN apt-get update \
&& apt-get install -y curl \
&& rm -rf /var/lib/apt/lists/*
ENTRYPOINT [ "curl", "-s", "http://myip.ipip.net" ]
今度はdocker run myip -i
を再度試してみましょう:
$ docker run myip
現在のIP:8.8.8.8 カリフォルニア州アメリカ合衆国
$ docker run myip -i
HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Tue, 22 Nov 2016 05:12:40 GMT
Content-Type: text/html; charset=UTF-8
Vary: Accept-Encoding
X-Powered-By: PHP/5.6.24-1~dotdeb+7.1
X-Cache: MISS from cache-2
X-Cache-Lookup: MISS from cache-2:80
X-Cache: MISS from proxy-2_6
Transfer-Encoding: chunked
Via: 1.1 cache-2:80, 1.1 proxy-2_6:8006
Connection: keep-alive
現在のIP:8.8.8.8 カリフォルニア州 アメリカ合衆国
今回はうまくいきました。これはENTRYPOINT
が存在する場合、CMD
の内容がENTRYPOINT
への引数として渡されるからであり、ここでは-i
が新しいCMD
であるため、curl
の引数として渡され、望んだ効果を得ることができました。
シナリオ2: アプリケーション起動前の準備作業
コンテナを起動するとは、メインプロセスを開始することですが、メインプロセスを開始する前に、いくつかの準備作業が必要な場合があります。
たとえば、mysql
のようなデータベースタイプでは、いくつかのデータベース設定や初期化作業が必要になることがあり、これらのタスクは最終的なmysqlサーバーが実行される前に解決する必要があります。
さらに、root
ユーザーとしてサービスを開始することは避けたいですが、サービスの開始前には、それでもroot
ユーザーとして必要な準備作業を実行し、最終的にはサービスユーザーのアイデンティティに切り替えてサービスを開始する必要があります。または、デバッグのような便利性のために、サービス以外のコマンドをroot
ユーザーとして実行することができます。
これらの準備作業はコンテナのCMD
とは関係がなく、CMD
が何であろうと関わらず事前処理ステップとして実行されなければなりません。この場合、スクリプトを書いてENTRYPOINT
に置いて実行することができます。このスクリプトは受け取った引数(つまり<CMD>
)を最後に実行するコマンドとして扱います。例えば、公式のredis
イメージはこのようにしています:
FROM alpine:3.4
...
RUN addgroup -S redis && adduser -S -G redis redis
...
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 6379
CMD [ "redis-server" ]
redis
サービス用にredis
ユーザーを作成し、最終的にENTRYPOINT
をdocker-entrypoint.sh
スクリプトとして指定しています。
#!/bin/sh
# allow the container to be started with `--user`
if [ "$1" = 'redis-server' -a "$(id -u)" = '0' ]; then
find . \! -user redis -exec chown redis '{}' +
exec gosu redis "$0" "$@"
fi
exec "$@"
このスクリプトの内容はCMD
の内容に基づいて判断しています。redis-server
であれば、redis
ユーザーのアイデンティティに切り替えてサーバーを開始します。それ以外の場合は、root
ユーザーとして実行されます。例えば:
$ docker run -it redis id
uid=0(root) gid=0(root) groups=0(root)
ENV
ENVは環境変数を設定するための命令で、以下の2つのフォーマットがあります。
ENV <key> <value>
ENV <key1>=<value1> <key2>=<value2>...
この命令は非常にシンプルで、環境変数を設定するだけです。以降のRUN
命令や実行時に実行されるアプリケーションは、ここで定義された環境変数を直接使用することができます。
ENV VERSION=1.0 DEBUG=on \
NAME="Happy Feet"
この例では、改行の方法と、スペースが含まれる値をダブルクォートで囲む方法を示しており、シェルの振る舞いと一致しています。
一度環境変数が定義されると、後続の命令で使用することができます。例えば、公式のnode
イメージのDockerfile
には以下のようなコードがあります。
ENV NODE_VERSION 7.2.0
RUN curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.xz" \
&& curl -SLO "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-x64.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-x64.tar.xz" -C /usr/local --strip-components=1 \
&& rm "node-v$NODE_VERSION-linux-x64.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs
環境変数は以下の命令で展開できます:ADD, COPY, ENV, EXPOSE, FROM, LABEL, USER, WORKDIR, VOLUME, STOPSIGNAL, ONBUILD, RUN。
この命令リストからわかるように、環境変数は多くの場面で使用することができ、非常に強力です。環境変数を利用することで、異なる環境変数を使って一つのDockerfileから複数のイメージを作成することができます。
EXPOSE
フォーマットはEXPOSE <port1> [<port2>...]
です。
EXPOSE
命令は、コンテ ナが実行中に提供するサービスのポートを宣言します。これは単なる宣言であり、この宣言のためにアプリケーションが実際にこれらのポートを開くわけではありません。Dockerfileにこの宣言を書くことのメリットは2つあります:一つは、このイメージサービスのデーモンポートをイメージユーザーに理解させるのに便利であり、ポートマッピングの設定に役立ちます。もう一つは、実行時にランダムポートマッピング、すなわちdocker run -P
を使用すると、EXPOSE
によって公開されるポートが自動的にランダムにマッピングされることです。
EXPOSE
命令は、実行時に-p <host port>:<container port>
を使用することと区別する必要があります。-p
はホストポートとコンテナポートをマッピングし、すなわち、コンテナの対応するポートサービスを外部アクセスに公開しますが、EXPOSE
はコンテナが使用する意図のポートを宣言するだけであり、ホスト上で自動的にポートマッピングを実行するわけではありません。
FROM
Dockerfileでは、FROM
命令はベースイメージを指定し、これが新しいイメージを構築するための出発点です。これはDockerfileの最初の命令であり、ビルドプロセスのためのベース環境を定義するために使用されます。
FROM
命令の一般的な使用方法
-
公式イメージから構築する:
FROM image:tag
この使用法は、既存の公式イメージをベースイメージとして指定します。
image
はイメージの名前であり、tag
はバージョンタグです。例えば、ベースイメージとしてubuntu:18.04
を使用することができます。 -
カスタムイメージから構築する:
FROM <username>/<imagename>:<tag>
この使用法は、カスタムイメージをベースイメージとして指定します。
<username>
はDocker Hub上のユーザー名、<imagename>
はイメージの名前、<tag>
はバージョンタグです。 -
マルチステージビルド:
FROM <base-image> AS <stage-name>
この使用法では、単一のDockerfileで複数のビルドステージを定義し、各ステージに異なるベースイメージを使用できます。
<base-image>
はベースイメージであり、<stage-name>
はステージの名前です。マルチステージビルドは通常、ビルドプロセス中に異なるツールや依存関係を利用し、その後必要なファイルや実行可能ファイルを一つのステージから次のステージにコピーし、最終的なイメージのサイズを減らすために使用されます。
-
ローカルファイルシステムから構築する:
FROM scratch
この使用法は、既存のベースイメージを使用せず、空のイメージからビルドを開始することを示します。この場合、必要なファイルや設定を自分で追加する必要があります。
FROM
命令はDockerfile内で1回 しか現れることができず、最初の命令でなければなりません。これはビルドプロセスの出発点を定義し、後続の命令はこの出発点に基づいて行われます。
HEALTHCHECK
形式:
HEALTHCHECK [オプション] CMD <コマンド>
: コンテナのヘルスチェック状態を確認するコマンドを設定します。HEALTHCHECK NONE
: ベースイメージにヘルスチェックの命令が含まれている場合、この行を使用してベースイメージのヘルスチェック命令を上書きします。
HEALTHCHECK
命令はDockerにコンテナの状態が正常かどうかを判断する方法を指示します。これはDocker 1.12で導入された新しい命令です。
HEALTHCHECK
命令の前は、Dockerエンジンはコンテナ内のメインプロセスが終了したかどうかを確認することで、コンテナが異常状態にあるかどうかを判断していました。多くの場合、これは問題ではありませんが、プログラムがデッドロックや無限ループの状態に入ると、アプリケーションプロセスは終了しませんが、コンテナはサービスを提供できなくなります。1.12より前は、Dockerはコンテナ内のこのような状態を検出せず、リスケジュールを行わないため、サービスを提供できないがユーザーのリクエストを受け入れているコンテナが発生することがありました。
1.12から、DockerはHEALTHCHECK
命令を提供し、メインプロセスのサービス状態がまだ正常であるかどうかを判断するコマンドを指定し、コンテナの実際の状態をより正確に反映できるようになりました。
イメージにHEALTHCHECK
命令が指定されていて、それからコンテナが開始された場合、初期状態はstarting
になります。HEALTHCHECK
命令が通過すると、状態はhealthy
に変わります。チェックが一定回数連続して失敗すると、状態はunhealthy
に変わります。
HEALTHCHECK
は以下のオプションをサポートしています:
--interval=<間隔>
: 2回のヘルスチェック間の間隔で、デフォルトは30秒です。--timeout=<期間>
: ヘルスチェックコマンドを実行するタイムアウト時間です。この時間を超えると、現在のヘルスチェックは失敗とみなされ、デフォルトは30秒です。--retries=<回数>
: 指定された回数連続して失敗した後、コンテナの状態はunhealthy
とみなされ、デフォルトは3回です。
CMD
やENTRYPOINT
と同様に、HEALTHCHECK
は一度だけ出現可能です。複数記述された場合は、最後のものが有効になります。
HEALTHCHECK [オプション] CMD
の後のコマンドはENTRYPOINT
と同じ形式であり、shell
フォーマットとexec
フォーマットがあります。コマンドの戻り値はヘルスチェックの成功または失敗を決定します:0
:成功; 1
:失敗; 2
:予約済み、この値は使用しないでください。
例えば、シンプルなWebサービスのイメージがあり、そのWebサービスが適切に動作しているかを判断するためのヘルスチェックを追加したいとします。この決定にはcurl
を使用することができます。Dockerfile
内のHEALTHCHECK
は以下のように書くことができます:
FROM nginx
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
ここでは、チェックを5秒ごとに実行するように設定しています(この間隔はテスト目的で非常に短く、実際には比較的長いべきです)、また、ヘルスチェックコマンドが3秒以内に応答しない場合は失敗とみなします。ヘルスチェックコマンドとしてcurl -fs http://localhost/ || exit 1
を使用します。
このイメー ジをビルドするにはdocker build
を使用します:
$ docker build -t myweb:v1 .
ビルド後、コンテナを起動します:
$ docker run -d --name web -p 80:80 myweb:v1
このイメージを実行した後、docker container ls
を使用して初期状態が(health: starting)
であることがわかります:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
03e28eb00bd0 myweb:v1 "nginx -g 'daemon off" 3 seconds ago Up 2 seconds (health: starting) 80/tcp, 443/tcp web
数秒待って再びdocker container ls
を実行 すると、ヘルスステータスが(healthy)
に変わっていることがわかります:
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
03e28eb00bd0 myweb:v1 "nginx -g 'daemon off" 18 seconds ago Up 16 seconds (healthy) 80/tcp, 443/tcp web
ヘルスチェックがリトライの回数よりも連続して失敗すると、状態は(unhealthy)
に変わります。
トラブルシューティングに役立てるため、ヘルスチェックコマンドの出力(stdout
とstderr
を含む)はヘルス状態に保存され、docker inspect
を使って閲覧できます。
$ docker inspect --format '{{json .State.Health}}' web | python -m json.tool
{
<style>\n body {\n width: 35em;\n margin: 0 auto;\n font-family: Tahoma, Verdana, Arial, sans-serif;\n }\n</style>\n</head>\n<body>\n<h1>Welcome to nginx!</h1>\n<p>If you see this page, the nginx web server is successfully installed and\nworking. Further configuration is required.</p>\n\n<p>For online documentation and support please refer to\n<a href=\"http://nginx.org/\">nginx.org</a>.<br/>\nCommercial support is available at\n<a href=\"http://nginx.com/\">nginx.com</a>.</p>\n\n<p><em>Thank you for using nginx.</em></p>\n</body>\n</html>\n",
"Start": "2016-11-25T14:35:37.780192565Z"
}
],
"Status": "healthy"
}
LABEL
LABEL
命令は、イメージにキーと値のペアのメタデータを追加するために使用されます。
LABEL <キー>=<値> <キー>=<値> <キー>=<値> ...
イメージの作者、ドキュメントのアドレスなどを宣言するためにいくつかのラベルを使用することもできます:
LABEL org.opencontainers.image.authors="yeasy"
LABEL org.opencontainers.image.documentation="https://www.ubitools.com"
RUN
DockerfileでのRUN
命令は、コンテナ内部でコマンドを実行するために使用されます。有効なコマンドやシェルスクリプトを実行することができます。
RUN
命令の一般的な使用例
-
単一のコマンドを実行する:
RUN <command>
この使用法では、
<command>
はコンテナ内で実行される単一のコマンドです。例えば:RUN apt-get update
RUN apt-get install -y packageこれは、それぞれパッケージリストを更新し、パッケージをインストールするコマンドをコンテナ内で実行します。
-
複数のコマンドを実行する:
RUN <command1> && <command2>