Dockerfile reference の日本語訳。
Docker は Dockerfile から指示を読み取ることにより、イメージを自動的に構築できます。
Dockerfile はイメージを構築する為のコマンドを記述したテキストドキュメントです。
ユーザーがコマンドラインから呼び出して使用します。
docker build を使用することで、ユーザーは複数のコマンドライン命令を連続して実行する自動ビルドを作成できます。
このページでは Dockerfile で使用できるコマンドについて説明します。
このページを読み終えたら Dockerfile Best Practices for a tip-oriented guide を参照してください。
使用法
docker build コマンドは Dockerfile とコンテキストからイメージをビルドします。
ビルドのコンテキストは、指定された場所の PATH または URL にあるファイルのセットです。
PATH はローカルファイルシステム上のディレクトリです。
URL は Git リポジトリの場所です。
コンテキストは再帰的に処理されます。
したがって PATH にはサブディレクトリが含まれ、 URL にはリポジトリとそのサブモジュールが含まれます。
次の例は、現在のディレクトリをコンテキストとして使用するビルドコマンドを示しています。
$ docker build .
Sending build context to Docker daemon 6.51 MB
...
ビルドは CLI ではなく Docker デーモンによって実行されます。
ビルドプロセスが最初に行うことは、コンテキスト全体を(再帰的に)デーモンに送信することです。
ほとんどの場合、コンテキストとして空のディレクトリから開始し、Dockerfile をそのディレクトリに保持することをお勧めします。
Dockerfile の構築に必要なファイルのみを追加してください。
警告
ルートディレクトリ/
を PATH として使用しないでください。
ビルド実行時にハードドライブの内容全体が Docker デーモンに転送されます。
ビルドコンテキストでファイルを使用する際、 Dockerfile は COPY
命令などの命令で指定されたファイルを参照します。
ビルドのパフォーマンスを向上させるには、コンテキストディレクトリに .dockerignore
ファイルを追加してファイルとディレクトリを除外します。
.dockerignore
ファイルを作成する方法については、このページのドキュメントを参照してください。
慣例として Dockerfile はコンテキストのルートに配置しますが、
docker build で -f
フラグを使用して、ファイルシステム内の任意の場所にある Dockerfile
を指定できます。
$ docker build -f /path/to/a/Dockerfile .
ビルドが成功した場合に新しいイメージを保存するリポジトリとタグを指定できます。
$ docker build -t shykes/myapp .
ビルド後にイメージを複数のリポジトリにタグ付けするには、ビルドコマンドの実行時に複数の -t
パラメータを追加します。
$ docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .
Docker デーモンは Dockerfile の命令を実行する前に、 Dockerfile の事前検証を実行し、構文が正しくない場合はエラーを返します。
$ docker build -t test/myapp .
Sending build context to Docker daemon 2.048 kB
Error response from daemon: Unknown instruction: RUNCMD
Docker デーモンは Dockerfile 内の命令を 1 つずつ実行し、必要に応じて各命令の結果を新しいイメージにコミットしてから、最終的に新しいイメージの ID を出力します。
Docker デーモンは、送信したコンテキストを自動的にクリーンアップします。
各命令は独立して実行され、新しいイメージが作成されることに注意してください。
したがって RUN cd /tmp
は次の命令に影響を与えません。
Docker は可能な場合は常に、中間イメージ(キャッシュ)を再利用して、Docker ビルドプロセスを大幅に高速化します。
中間イメージの再利用は、コンソール出力の Using cache
メッセージによって示されます。
(詳細については Dockerfile ベストプラクティスガイド を参照してください)
$ docker build -t svendowideit/ambassador .
Sending build context to Docker daemon 15.36 kB
Step 1/4 : FROM alpine:3.2
---> 31f630c65071
Step 2/4 : MAINTAINER SvenDowideit@home.org.au
---> Using cache
---> 2a1c91448f5f
Step 3/4 : RUN apk update && apk add socat && rm -r /var/cache/
---> Using cache
---> 21ed6e7fbb73
Step 4/4 : CMD env | grep _TCP= | (sed 's/.*_PORT_\([0-9]*\)_TCP=tcp:\/\/\(.*\):\(.*\)/socat -t 100000000 TCP4-LISTEN:\1,fork,reuseaddr TCP4:\2:\3 \&/' && echo wait) | sh
---> Using cache
---> 7ea8aef582cc
Successfully built 7ea8aef582cc
ビルドキャッシュは親チェーンを持つローカルイメージからのみ使用されます。
これはイメージが以前のビルドによって作成されたか、イメージのチェーン全体が docker load
で読込まれたことを意味します。
特定のイメージのビルドキャッシュを使用する場合は --cache-from
オプションを使用して指定できます。
--cache-from
で指定されたイメージは、親チェーンを持つ必要はなく、他のレジストリから取得できます。
ビルドが完了したら、リポジトリをレジストリにプッシュする方法を検討する準備が整います。
BuildKit
バージョン 18.09 以降の Docker は moby/buildkit プロジェクトによって提供されるビルドを実行するための新しいバックエンドをサポートします。
BuildKit バックエンドには、古い実装と比較して多くの利点があります。
たとえば BuildKit は次のことができます。
- 未使用のビルドステージの実行を検出してスキップします
- ビルドの独立したビルドステージを並列化します
- ビルド間でビルドコンテキスト内の変更されたファイルのみを段階的に転送します
- ビルドコンテキストで未使用のファイルの転送を検出してスキップします
- 多くの新機能を備えた外部 Dockerfile 実装を使用します
- 残りの API(中間イメージとコンテナー)での副作用を回避します
- 自動プルーニングのためにビルドキャッシュに優先順位を付けます
BuildKit バックエンドを使用するには docker build を呼び出す前に、 CLI で環境変数 DOCKER_BUILDKIT=1
を設定する必要があります。
BuildKit ベースのビルドで使用できる実験的な Dockerfile 構文については BuildKit リポジトリのドキュメント を参照してください。
Format
Dockerfile の形式は次のとおりです。
# Comment
INSTRUCTION arguments
命令では大文字と小文字は区別されません。
ただし、引数と区別しやすいように大文字にするのが慣例です。
Docker は Dockerfile 内の命令を順番に実行します。
Dockerfile は FROM
命令で始まる必要があります。
これは、パーサーディレクティブ、コメント、およびグローバルスコープの ARG
の後にある可能性があります。
FROM
命令は、構築元の親イメージを指定します。
FROM
の前には Dockerfile の FROM
行で使用される引数を宣言する 1 つ以上の ARG
命令のみを付けることができます。
Docker は行が有効なパーサーディレクティブでない限り #
で始まる行をコメントとして扱います。
行内の他の場所にある #
マーカーは、引数として扱われます。
これにより、次のようなステートメントが可能になります。
# Comment
RUN echo 'we are running some # of cool things'
Dockerfile 命令が実行される前にコメント行が削除されます。
つまり次の例のコメントは、 echo
コマンドを実行するシェルによって処理されません。
以下の両方の例は同等です。
RUN echo hello \
# comment
world
RUN echo hello \
world
行継続文字はコメントではサポートされていません。
空白に関する注意
下位互換性のために、コメント(
#
)および命令(RUN
など)の前の先頭の空白は無視されますが、推奨されません。
これらの場合、先頭の空白は保持されないため、次の例は同等です。
# this is a comment-line RUN echo hello RUN echo world
# this is a comment-line RUN echo hello RUN echo world
ただし
RUN
に続くコマンドなど、命令引数の空白は保持されるため、次の例では、先頭に空白を指定してhello world
を出力します。
RUN echo "\ hello\ world"
パーサーディレクティブ
パーサーディレクティブはオプションであり、 Dockerfile の後続の行が処理される方法に影響を与えます。
パーサーディレクティブはビルドにレイヤーを追加せず、ビルドステップとして表示されません。
パーサーディレクティブは # directive=value
の形式で特別なタイプのコメントとして記述されます。
1 つのディレクティブは 1 回だけ使用できます。
コメント、空の行、またはビルダー命令が処理されると、 Docker はパーサーディレクティブを検索しなくなります。
パーサーディレクティブとして記述されたものをコメントとして扱い、パーサーディレクティブである可能性があるかどうかの検証を試みません。
したがって、すべてのパーサーディレクティブは Dockerfile の最上部にある必要があります。
パーサーディレクティブでは大文字と小文字は区別されません。
ただし慣例では小文字にする必要があります。
慣例ではパーサーディレクティブの後に空白行を含めることもできます。
行継続文字は、パーサーディレクティブではサポートされていません。
これらの規則により、次の例はすべて無効です。
行継続のため無効
# direc \
tive=value
2 回表示されるため無効
# directive=value1
# directive=value2
FROM ImageName
ビルダーの指示の後に表示されるため、コメントとして扱われます。
FROM ImageName
# directive=value
パーサーディレクティブではないコメントの後に表示されるため、コメントとして扱われます。
# About my dockerfile
# directive=value
FROM ImageName
unknowndirective
は、認識されないためコメントとして扱われます。
さらに knowndirective
は、パーサーディレクティブではないコメントの後に表示されるため、コメントとして扱われます。
# unknowndirective=value
# knowndirective=value
パーサーディレクティブでは、改行のない空白が許可されています。
したがって、次の行はすべて同じように扱われます。
#directive=value
# directive =value
# directive= value
# directive = value
# dIrEcTiVe=value
次のパーサーディレクティブがサポートされています。
- syntax
- escape
syntax
# syntax=[remote image reference]
例
# syntax=docker/dockerfile
# syntax=docker/dockerfile:1.0
# syntax=docker.io/docker/dockerfile:1
# syntax=docker/dockerfile:1.0.0-experimental
# syntax=example.com/user/repo:tag@sha256:abcdef...
この機能は BuildKit バックエンドが使用されている場合にのみ有効になります。
syntax
ディレクティブは、現在の Dockerfile のビルドに使用される Dockerfile ビルダーの場所を定義します。
BuildKit バックエンドを使用すると Docker イメージとして配布され、コンテナーサンドボックス環境内で実行されるビルダーの外部実装をシームレスに使用できます。
カスタム Dockerfile 実装により、次のことが可能になります。
- デーモンを更新せずにバグ修正を自動的に取得する
- すべてのユーザーが同じ実装を使用して Dockerfile をビルドしていることを保証できる
- デーモンを更新せずに最新の機能を使用することができる
- 新しい実験的またはサードパーティの機能を試すことができる
公式リリース
Docker は DockerHub の docker/dockerfile リポジトリーに Dockerfile を構築するために使用できるイメージの公式バージョンを配布しています。
新しいイメージがリリースされるチャネルは、安定版と実験版の 2 つです。
安定版チャネルは、セマンティックバージョニングに従います。
例:
- docker/dockerfile:1.0.0 - 不変バージョン 1.0.0 のみを許可する
- docker/dockerfile:1.0 - バージョン 1.0.* を許可する
- docker/dockerfile:1 - versions 1.. を許可する
- docker/dockerfile:latest - 安定版チャネルの最新リリース
実験版チャネルは、リリース時の安定版チャネルからのメジャーコンポーネントとマイナーコンポーネントを使用したインクリメンタルバージョン管理を使用します。
例:
- docker/dockerfile:1.0.1-experimental - 不変バージョン 1.0.1-experimental のみを許可する
- docker/dockerfile:1.0-experimental - 1.0 以降の最新の実験版リリース
- docker/dockerfile:experimental - 実験版チャネルの最新リリース
ニーズに適したチャネルを選択する必要があります。
バグ修正のみが必要な場合は docker/dockerfile:1.0 を使用する必要があります。
実験的な機能を活用したい場合は、実験版チャネルを使用する必要があります。
実験チャネルを使用している場合、新しいリリースには下位互換性がない可能性があるため、不変のフルバージョンバリアントを使用することをお勧めします。
マスタービルドとナイトリー機能リリースについては ソースリポジトリの説明 を参照してください。
escape
# escape=\ (backslash)
または
# escape=` (backtick)
エスケープディレクティブは Dockerfile 内の文字をエスケープするために使用される文字を設定します。
指定しない場合、デフォルトのエスケープ文字は \
です。
エスケープ文字は、行内の文字をエスケープするためと、改行をエスケープするための両方に使用されます。
これにより Dockerfile 命令を複数行にまたがることができます。
escape
パーサーディレクティブが Dockerfile に含まれているかどうかに関係なく、エスケープは、行の終わりを除いて、 RUN
コマンドでは実行されないことに注意してください。
エスケープ文字を「 ` 」に設定すると Windows で特に役立ちます。
ここでは \
はディレクトリパスの区切り文字です。
「 ` 」は Windows PowerShell と一貫性があります。
Windows で自明ではない方法で失敗する次の例を考えてみましょう。
2 行目の終わりにある 2 番目の \
は、最初の \
からのエスケープのターゲットではなく、改行のエスケープとして解釈されます。
同様に 3 行目の終わりにある \
は、実際に命令として処理されたとすると、行の継続として扱われます。
この dockerfile の結果は 2 行目と 3 行目が単一の命令と見なされることです。
FROM microsoft/nanoserver
COPY testfile.txt c:\\
RUN dir c:\
実行結果:
PS C:\John> docker build -t cmd .
Sending build context to Docker daemon 3.072 kB
Step 1/2 : FROM microsoft/nanoserver
---> 22738ff49c6d
Step 2/2 : COPY testfile.txt c:\RUN dir c:
GetFileAttributesEx c:RUN: The system cannot find the file specified.
PS C:\John>
上記の解決策の 1 つは COPY
命令と dir
の両方のターゲットとして /
を使用することです。
ただし、この構文は Windows のパスでは自然ではないため混乱を招きます。
最悪の場合 Windows のすべてのコマンドがパス区切り文字として /
をサポートしているわけではないため、エラーが発生しやすくなります。
escape
パーサーディレクティブを追加することにより、次の Dockerfile は Windows のファイルパスに自然なプラットフォームセマンティクスを使用して期待どおりに成功します。
# escape=`
FROM microsoft/nanoserver
COPY testfile.txt c:\
RUN dir c:\
実行結果:
PS C:\John> docker build -t succeeds --no-cache=true .
Sending build context to Docker daemon 3.072 kB
Step 1/3 : FROM microsoft/nanoserver
---> 22738ff49c6d
Step 2/3 : COPY testfile.txt c:\
---> 96655de338de
Removing intermediate container 4db9acbb1682
Step 3/3 : RUN dir c:\
---> Running in a2c157f842f5
Volume in drive C has no label.
Volume Serial Number is 7E6D-E0F7
Directory of c:\
10/05/2016 05:04 PM 1,894 License.txt
10/05/2016 02:22 PM <DIR> Program Files
10/05/2016 02:14 PM <DIR> Program Files (x86)
10/28/2016 11:18 AM 62 testfile.txt
10/28/2016 11:20 AM <DIR> Users
10/28/2016 11:20 AM <DIR> Windows
2 File(s) 1,956 bytes
4 Dir(s) 21,259,096,064 bytes free
---> 01c7f3bef04f
Removing intermediate container a2c157f842f5
Successfully built 01c7f3bef04f
PS C:\John>
環境変数の置換
環境変数( ENV
ステートメントで宣言)は、 Dockerfile によって解釈される変数として特定の命令で使用することもできます。
エスケープは、変数に似た構文をそのままステートメントに含めるためにも処理されます。
環境変数は Dockerfile で $variable_name
または ${variable_name}
のいずれかで表記されます。
それらは同等に扱われ、中括弧構文は通常 ${foo} _bar
のように空白のない変数名の問題に対処するために使用されます。
${variable_name}
構文は、以下に指定されている標準の bash 修飾子のいくつかもサポートしています。
-
${variable:-word}
は変数が設定されている場合、結果がその値になることを示します。
変数が設定されていない場合word
が結果になります。 -
${variable:+word}
は、変数が設定されている場合はword
が結果になり、それ以外の場合は結果が空の文字列になることを示します。
すべての場合において word
は、追加の環境変数を含む任意の文字列にすることができます。
エスケープは変数の前に \
を追加することで可能です。
たとえば \$ foo
または \${foo}
は、 $foo
と ${foo}
に変換されます。
例(解析された表現は #
の後に表示されます):
FROM busybox
ENV FOO=/bar
WORKDIR ${FOO} # WORKDIR /bar
ADD . $FOO # ADD . /bar
COPY \$FOO /quux # COPY $FOO /quux
環境変数は Dockerfile の以下に示す命令でサポートされています。
- ADD
- COPY
- ENV
- EXPOSE
- FROM
- LABEL
- STOPSIGNAL
- USER
- VOLUME
- WORKDIR
- ONBUILD (上記のサポートされている手順の 1 つと組み合わせた場合)
環境変数の置換では、命令全体を通じて各変数に同じ値が使用されます。
言い換えると、この例では次のようになります。
ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc
結果は bye
ではなく hello
の値を持つ def
になります。
ただし ghi
は abc
を bye
に設定したのと同じ命令の一部ではないため、 bye
の値になります。
.dockerignore ファイル
docker CLI はコンテキストを docker デーモンに送信する前に、コンテキストのルートディレクトリで .dockerignore
という名前のファイルを探します。
このファイルが存在する場合 CLI はコンテキストを変更して、その中のパターンに一致するファイルとディレクトリを除外します。
これにより、大きなファイルや機密性の高いファイルやディレクトリをデーモンに不必要に送信したり、 ADD
または COPY
を使用してイメージに追加したりすることを回避できます。
CLIは .dockerignore
ファイルを Unix シェルのファイルグロブに似た改行で区切られたパターンのリストとして解釈します。
照合の目的で、コンテキストのルートは作業ディレクトリとルートディレクトリの両方であると見なされます。
たとえば、パターン /foo/bar
と foo/bar
はどちらも、 PATH
の foo
サブディレクトリまたは URL にある git リポジトリのルートにある bar
という名前のファイルまたはディレクトリを除外します。
どちらも他のものを除外しません。
.dockerignore
ファイルの行が 1 列目の #
で始まる場合、この行はコメントと見なされ、 CLI によって解釈される前に無視されます。
.dockerignore
ファイルの記述例を示します:
# comment
*/temp*
*/*/temp*
temp?
このファイルにより、次のビルド動作が発生します。
ルール | 動作 |
---|---|
# comment |
無視します。 |
*/temp* |
ルートの直接のサブディレクトリで、名前が temp で始まるファイルとディレクトリを除外します。たとえば、プレーンファイル /somedir/temporary.txt は除外され、ディレクトリ /somedir/temp も除外されます。 |
*/*/temp* |
ルートの 2 階層下にあるサブディレクトリから temp で始まるファイルとディレクトリを除外します。たとえば、 /somedir/subdir/temporary.txt は除外されます。 |
temp? |
名前が temp + 1 文字であるルートディレクトリ内のファイルとディレクトリを除外します。たとえば、 /tempa と /tempb は除外されます。 |
マッチングは Go の filepath.Match
ルールを使用して行われます。
前処理ステップでは Go の filepath.Clean
を使用して、先頭と末尾の空白を削除し、 .
要素と ..
要素を削除します。
前処理後に空白の行は無視されます。
Docker は Go の filepath.Match
ルールに加えて、任意の数のディレクトリ(ゼロを含む)に一致する特別なワイルドカード文字列 **
もサポートしています。
たとえば **/*.go
はビルドコンテキストのルートを含むすべてのディレクトリにある .go
で終わるすべてのファイルを除外します。
!
(感嘆符)で始まる行を使用して、除外の例外を作成できます。
以下は、この仕組みを使用する .dockerignore
ファイルの例です。
*.md
!README.md
README.md
を除くすべてのマークダウンファイルはコンテキストから除外されます。
!
例外ルールの配置は、動作に影響を与えます。
特定のファイルに一致する .dockerignore
の最後の行は、そのファイルが含まれるか除外されるかを決定します。
次の例を考えてみましょう。
*.md
!README*.md
README-secret.md
README-secret.md
以外の README
ファイルを除いて、マークダウンファイルはコンテキストに含まれていません。
ここで、この例を検討します。
*.md
README-secret.md
!README*.md
すべての README
ファイルが含まれています。
!README*.md
は README-secret.md
と一致し、最後に来るため、真ん中の行は効果がありません。
.dockerignore
ファイルを使用して Dockerfile ファイルと .dockerignore
ファイルを除外することもできます。
これらのファイルは、そのジョブを実行する必要があるため、引き続きデーモンに送信されます。
ただし ADD
および COPY
命令はそれらをイメージにコピーしません。
最後に、除外するファイルではなく、コンテキストに含めるファイルを指定することをお勧めします。
これを実現するには、最初のパターンとして *
を指定し、その後に 1 つ以上の !
例外パターンを指定します。
注意
歴史的な理由から、パターン
.
は無視されます。
FROM
FROM [--platform=<platform>] <image> [AS <name>]
または
FROM [--platform=<platform>] <image>[:<tag>] [AS <name>]
または
FROM [--platform=<platform>] <image>[@<digest>] [AS <name>]
FROM
命令は、新しいビルドステージを初期化し、後続の命令のベースイメージを設定します。
そのため、有効な Dockerfile は FROM
命令で始まる必要があります。
イメージは任意の有効なイメージを指定することができます。
パブリックリポジトリからイメージを取得することから始めるのは特に簡単です。
-
ARG
は Dockerfile のFROM
の前にある可能性がある唯一の命令です。
ARG
とFROM
の相互作用を理解する を参照してください。 -
FROM
は、単一の Dockerfile 内に複数回出現して、複数のイメージを作成したり、あるビルドステージを別のビルドステージの依存関係として使用したりできます。
新しいFROM
命令の前に、commit
によって出力された最後のイメージ ID をメモするだけです。
各FROM
命令は、前の命令によって作成されたすべての状態をクリアします。 - オプションで
FROM
命令にAS name
を追加することにより、新しいビルドステージに名前を付けることができます。
この名前は、後続のFROM
およびCOPY --from=<name>
命令で使用して、このステージで作成されたイメージを参照できます。 - タグまたはダイジェスト値はオプションです。
いずれかを省略すると、ビルダーはデフォルトで最新のタグを想定します。
タグ値が見つからない場合、ビルダーはエラーを返します。
オプションの --platform
フラグを使用して、 FROM
がマルチプラットフォームイメージを参照する場合にイメージのプラットフォームを指定できます。
たとえば、 linux/amd64
、 linux/arm64
、または windows/amd64
です。
デフォルトでは、ビルドリクエストのターゲットプラットフォームが使用されます。
このフラグの値にはグローバルビルド引数を使用できます。
たとえば、自動プラットフォーム引数を使用すると、ステージをネイティブビルドプラットフォームに強制し、それを使用してステージ内のターゲットプラットフォームにクロスコンパイルできます。
( --platform=$BUILDPLATFORM
)
ARG
と FROM
の相互作用を理解する
FROM
命令は、最初の FROM
の前に発生する ARG
命令によって宣言される変数をサポートします。
ARG CODE_VERSION=latest
FROM base:${CODE_VERSION}
CMD /code/run-app
FROM extras:${CODE_VERSION}
CMD /code/run-extras
FROM
の前に宣言された ARG
はビルドステージの外にあるため、 FROM
の後の命令では使用できません。
最初の FROM
の前に宣言された ARG
のデフォルト値を使用するには、ビルドステージ内で値なしで ARG
命令を使用します。
ARG VERSION=latest
FROM busybox:$VERSION
ARG VERSION
RUN echo $VERSION > image_version
RUN
RUN
は 2 種類の形式があります:
-
RUN <command>
(シェル形式。コマンドはシェル上で実行される。
Linux の既定シェルは/bin/sh -c
。
Windows の既定シェルはcmd /S /C
) -
RUN ["executable", "param1", "param2"]
(exec
形式)
RUN
命令は、現在のイメージ上にある新しいレイヤーでコマンドを実行し、結果をコミットします。
結果がコミットされたイメージは Dockerfile の次のステップで使用されます。
RUN
命令を階層化し、コミットを生成することは、コミットが安価で、ソース管理のようにイメージの履歴の任意のポイントからコンテナを作成できる Docker のコアコンセプトに準拠しています。
exec
形式を使用すると、シェル文字列の変更を回避したり、指定したシェル実行可能ファイルを含まないベースイメージを使用して RUN
コマンドを実行できます。
シェル形式の既定のシェルは SHELL
コマンドを使用して変更できます。
シェル形式では、 \
(バックスラッシュ)を使用して、単一の RUN
命令を次の行に続けることができます。
たとえば、次の 2 行について考えてみます。
RUN /bin/bash -c 'source $HOME/.bashrc; \
echo $HOME'
これらを合わせると、次の 1 行に相当します。
RUN /bin/bash -c 'source $HOME/.bashrc; echo $HOME'
/bin/sh
以外の別のシェルを使用するには、目的のシェルを渡す exec
形式を使用します。例えば:
RUN ["/bin/bash", "-c", "echo hello"]
注意
exec
形式は JSON 配列として解析されます。
つまり一重引用符('
)ではなく、単語の前後に二重引用符("
)を使用する必要があります。
シェル形式とは異なり、 exec
形式はコマンドシェルを呼び出しません。
これは、通常のシェル処理が行われないことを意味します。
たとえば、 RUN ["echo", "$HOME"]
は、 $HOME
の変数置換を行いません。
シェル処理が必要な場合は、シェル形式を使用するか、シェルを直接実行します。
例: RUN ["sh", "-c", "echo $ HOME"]
。
シェル形式の場合のように、 exec
形式を使用してシェルを直接実行する場合、環境変数の展開を行うのは Docker ではなく、シェルです。
注意
JSON 形式では、バックスラッシュをエスケープする必要があります。
これは、バックスラッシュがパス区切り文字である Windows に特に関係があります。
次の行は、有効な JSON ではないため、シェル形式として扱われ、予期しない方法で失敗します:RUN ["c:\windows\system32\tasklist.exe"]
この例の正しい構文は次のとおりです:
RUN ["c:\\windows\\system32\\tasklist.exe"]
RUN
命令のキャッシュは、次のビルド中に自動的に無効になることはありません。
RUN apt-get dist-upgrade -y
のような命令のキャッシュは、次のビルドで再利用されます。
RUN
命令のキャッシュは --no-cache
フラグを使用して無効にすることができます(例: docker build --no-cache
)。
詳細については Dockerfile ベストプラクティスガイド を参照してください。
RUN
命令のキャッシュは、 ADD
および COPY
命令によって無効にすることができます。
既知の問題( RUN
)
-
イシュー 783 は、 AUFS ファイルシステムの使用時に発生する可能性のあるファイル権限の問題に関するものです。
たとえば、ファイルをrm
しようとしたときに気付くかもしれません。
最近の aufs バージョンがあるシステム(つまりdirperm1
マウントオプションを設定できる)の場合、 docker はdirperm1
オプションを使用してレイヤーをマウントすることで問題を自動的に修正しようとします。
dirperm1
オプションの詳細については aufs の man ページ を参照してください。
システムでdirperm1
がサポートされていない場合、 イシュー 783 は回避策を説明しています。
CMD
CMD
命令は 3 つの形式を持ちます:
-
CMD ["executable","param1","param2"]
(exec
形式。これが推奨される形式です) -
CMD ["param1","param2"]
(ENTRYPOINT
へのデフォルトパラメータとして使用します) -
CMD command param1 param2
(シェル形式)
Dockerfile には 1 つの CMD
命令しか存在できません。
複数の CMD
を列記すると、最後の CMD
のみが有効になります。
CMD
の主な目的は、実行中のコンテナに既定の動作を提供することです。
これらの既定の動作には、 executable
を含めることも、 executable
を省略することもできます。
executable
を省略する場合は ENTRYPOINT
命令も指定する必要があります。
CMD
を使用して ENTRYPOINT
命令のデフォルトの引数を提供する場合は、CMD
命令と ENTRYPOINT
命令の両方を JSON 配列形式で指定する必要があります。
注意
exec
形式は JSON 配列として解析されます。
つまり単語の前後に一重引用符('
)ではなく、二重引用符("
)を使用する必要があります。
シェル形式とは異なり、 exec
形式はコマンドシェルを呼び出しません。
これは、通常のシェル処理が行われないことを意味します。
たとえば CMD ["echo", "$HOME"]
は、 $HOME
で変数置換を行いません。
シェル処理が必要な場合は、シェル形式を使用するか、シェルを直接実行します。
例: CMD ["sh"、 "-c"、 "echo $ HOME"]
シェル形式の場合のように、 exec
形式を使用してシェルを直接実行する場合、環境変数の展開を行うのは Docker ではなく、シェルです。
シェル形式または exec
形式で使用する場合、 CMD
命令は、イメージの実行時に実行されるコマンドを設定します。
CMD
のシェル形式を使用する場合、 <command>
は /bin/sh -c
で実行されます:
FROM ubuntu
CMD echo "This is a test." | wc -
シェルなしで <command>
を実行したい場合は、コマンドを JSON 配列として表現し、 executable
へのフルパスを指定する必要があります。
この配列形式は、 CMD
の推奨フォーマットです。
追加のパラメータは、配列内の文字列として個別に表現する必要があります。
FROM ubuntu
CMD ["/usr/bin/wc","--help"]
コンテナで毎回同じ executable
を実行したい場合は、ENTRYPOINT
を CMD
と組み合わせて使用することを検討する必要があります。
ENTRYPOINT
を参照してください。
ユーザーが docker run の引数を指定すると、 CMD
で指定された既定値が上書きされます。
注意
RUN
とCMD
を混同しないでください。
RUN
は実際にコマンドを実行し、結果をコミットします。
CMD
はビルド時に何も実行しませんが、イメージに実行させたいコマンドを指定します。
LABEL
LABEL <key>=<value> <key>=<value> <key>=<value> ...
LABEL
命令はメタデータをイメージに追加します。
LABEL
はキーと値のペアです。
LABEL
の値にスペースを含めるには、コマンドライン解析の場合と同じように引用符とバックスラッシュを使用します。
使用例:
LABEL "com.example.vendor"="ACME Incorporated"
LABEL com.example.label-with-value="foo"
LABEL version="1.0"
LABEL description="This text illustrates \
that label-values can span multiple lines."
イメージには複数のラベルを付けることができます。
1 行に複数のラベルを指定できます。
Docker 1.10 より前は、これにより最終イメージのサイズが小さくなりましたが、現在はそうではありません。
次の 2 つの方法のいずれかで、 1 つの命令で複数のラベルを指定することもできます。
LABEL multi.label1="value1" multi.label2="value2" other="value3"
LABEL multi.label1="value1" \
multi.label2="value2" \
other="value3"
ベースイメージまたは親イメージ( FROM
行のイメージ)に含まれるラベルは、子イメージに継承されます。
ラベルがすでに存在するが値が異なる場合、最後に適用された値が以前に設定された値を上書きします。
イメージのラベルを表示するには docker image inspect
コマンドを使用します。
--format
オプションを使用してラベルのみを表示できます。
docker image inspect --format='' myimage
{
"com.example.vendor": "ACME Incorporated",
"com.example.label-with-value": "foo",
"version": "1.0",
"description": "This text illustrates that label-values can span multiple lines.",
"multi.label1": "value1",
"multi.label2": "value2",
"other": "value3"
}
MAINTAINER (非推奨)
MAINTAINER <name>
MAINTAINER
命令は、生成されたイメージの Author
フィールドを設定します。
LABEL
命令は MAINTAINER
よりもはるかに柔軟に必要なメタデータを設定できます。
代わりに LABEL
を使用してください。
たとえば docker inspect
を使用して簡単に表示できます。
MAINTAINER
フィールドに対応するラベルを設定するには:
LABEL maintainer="SvenDowideit@home.org.au"
これは、他のラベルとともに docker inspect
から表示されます。
EXPOSE
EXPOSE <port> [<port>/<protocol>...]
EXPOSE
命令は、コンテナ実行時に指定されたネットワークポートで待受けすることを Docker に通知します。
ポートが TCP と UDP のどちらで待受けするかを指定できます。
プロトコルが指定されていない場合、既定値は TCP です。
EXPOSE
命令は、実際にはポートを公開しません。
これは、イメージを作成する人とコンテナーを実行する人の間の一種のドキュメントとして機能し、ポートの公開が意図されています。
コンテナの実行時に実際にポートを公開するには、 docker run で -p
フラグを使用して 1 つ以上のポートを公開して紐づけするか、 -P
フラグを使用して公開されたすべてのポートを公開し、それらを上位ポートに紐づけします。
デフォルトでは EXPOSE
は TCP を想定していますが、
UDP を指定することもできます。
EXPOSE 80/udp
TCP と UDP の両方で公開するには、次の 2 行を記述します。
EXPOSE 80/tcp
EXPOSE 80/udp
この場合 docker run で -P
を使用すると、ポートは TCP 用に 1 回、 UDP 用に 1 回公開されます。
-P
はホスト上で一時的な上位ホストポートを使用するため、ポートは TCP と UDP で同じではないことに注意してください。
EXPOSE
設定に関係なく -p
フラグを使用して実行時にそれらをオーバーライドできます。
例:
docker run -p 80:80/tcp -p 80:80/udp ...
ホストシステムでポートリダイレクションを設定するには -P
フラグの使用を参照してください。
docker network
コマンドは、特定のポートを公開(expose または publish)する必要なしに、コンテナー間の通信用のネットワークの作成をサポートします。
これは、ネットワークに接続されたコンテナーが任意のポートを介して相互に通信できるためです。
詳細については、 docker network 機能の概要 を参照してください。
ENV
ENV <key>=<value> ...
ENV
命令は、環境変数 <key>
を値 <value>
に設定します。
この値は、ビルドステージの後続のすべての命令の環境にあり、多くの場合、インラインで置き換えることができます。
値は他の環境変数に対して解釈されるため、引用符がエスケープされていない場合は削除されます。
コマンドライン解析と同様に、引用符とバックスラッシュを使用して値にスペースを含めることができます。
例:
ENV MY_NAME="John Doe"
ENV MY_DOG=Rex\ The\ Dog
ENV MY_CAT=fluffy
ENV
命令では、複数の <key>=<value> ...
変数を一度に設定できます。
以下の例では、最終的なイメージで同じ最終結果が得られます。
ENV MY_NAME="John Doe" MY_DOG=Rex\ The\ Dog \
MY_CAT=fluffy
ENV
を使用して設定された環境変数は、結果のイメージからコンテナが実行されたときに保持されます。
docker inspect
を使用して値を表示し、 docker run --env <key>=<value>
を使用して値を変更できます。
環境変数の永続性は、予期しない副作用を引き起こす可能性があります。
たとえば ENV DEBIAN_FRONTEND=noninteractive
を設定すると、apt-get
の動作が変更され、イメージのユーザーを混乱させる可能性があります。
環境変数がビルド中にのみ必要であり、最終イメージでは必要ない場合は、代わりに単一のコマンドの値を設定することを検討してください。
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y ...
または最終的なイメージに保持されない ARG
を使用します。
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y ...
代替記法
ENV
命令では代替構文ENV <key> <value>
を使用でき、=
を省略できます。例:
ENV MY_VAR my-value
この構文では複数の環境変数を 1 つの
ENV
命令に設定することはできず、混乱を招く可能性があります。
たとえば次のように、単一の環境変数ONE
を値"TWO = THREE = world"
で設定します。ENV ONE TWO= THREE=world
代替構文は下位互換性のためにサポートされていますが、上記の理由により推奨されておらず、将来のリリースで削除される可能性があります。
ADD
ADD
は 2 つの形式を持ちます:
ADD [--chown=<user>:<group>] <src>... <dest>
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]
空白を含むパスには後者の形式が必要です。
注意
--chown
機能は Linux コンテナの構築に使用される Dockerfile でのみサポートされており、 Windows コンテナでは機能しません。
ユーザーとグループの所有権の概念は Linux と Windows の間で変換されないため、ユーザー名とグループ名を ID に変換するために/etc/passwd
と/etc/group
を使用すると、この機能は Linux OS ベースのコンテナである場合に限り実行可能に制限されます。
ADD
命令は、新しいファイル、ディレクトリ、またはリモートファイルの URL を <src>
からコピーし、パス <dest>
でイメージのファイルシステムに追加します。
複数の <src>
リソースを指定できますが、それらがファイルまたはディレクトリの場合、パスはビルドのコンテキストのソースからの相対パスとして解釈されます。
各 <src>
にはワイルドカードを含めることができ、照合は Go の filepath.Match
ルールを使用して行われます。
例えば hom
で始まるすべてのファイルを追加するには:
ADD hom* /mydir/
以下の例では ?
は home.txt
などの任意の 1 文字に置き換えられています。
ADD hom?.txt /mydir/
<dest>
は絶対パス、または WORKDIR
から見た相対パスであり、ソースは宛先コンテナ内にコピーされます。
以下の例では、相対パスを使用して test.txt
を <WORKDIR>/relativeDir/
に追加しています:
ADD test.txt relativeDir/
この例では絶対パスを使用して test.txt
を /abstractDir/
に追加します。
ADD test.txt /absoluteDir/
特殊文字( [
や ]
など)を含むファイルやディレクトリを追加する場合は、一致するパターンとして扱われないように、 Go 言語のルールに従ってこれらのパスをエスケープする必要があります。
たとえば、 arr[0].txt
という名前のファイルを追加するには、次を使用します。
ADD arr[[]0].txt /mydir/
追加されたコンテンツの特定の所有権を要求するために、オプションの --chown
フラグが特定のユーザー名、グループ名、またはUID / GIDの組み合わせを指定しない限り、すべての新しいファイルとディレクトリは UID と GID が 0 で作成されます。
--chown
フラグの形式では、ユーザー名とグループ名の文字列、または直接整数の UID と GID を任意の組み合わせで使用できます。
グループ名なしのユーザー名または GID なしの UID を指定すると、 GID と同じ数値の UID が使用されます。
ユーザー名またはグループ名が指定されている場合、コンテナのルートファイルシステムの /etc/passwd
ファイルと/etc/group
ファイルを使用して、名前から整数の UID または GID への変換がそれぞれ実行されます。
次の例は、 --chown
フラグの有効な定義を示しています。
ADD --chown=55:mygroup files* /somedir/
ADD --chown=bin files* /somedir/
ADD --chown=1 files* /somedir/
ADD --chown=10:11 files* /somedir/
コンテナルートファイルシステムに /etc/passwd
または /etc/group
ファイルが含まれておらず、ユーザー名またはグループ名が --chown
フラグで使用されている場合、 ADD
操作でビルドは失敗します。
数値 ID の使用はルックアップを必要とせず、コンテナルートファイルシステムのコンテンツに依存しません。
<src>
がリモートファイルの URL の場合、宛先には 600 の権限があります。
取得するリモートファイルに HTTP Last-Modified ヘッダーがある場合、そのヘッダーのタイムスタンプを使用して、宛先ファイルの mtime を設定します。
ただし ADD
中に処理される他のファイルと同様に、 mtime は、ファイルが変更されたかどうかの判断には含まれず、キャッシュを更新する必要があります。
注意
Dockerfile を
STDIN
(docker build- <somefile
)に渡してビルドする場合、ビルドコンテキストがないため、 Dockerfile には URL ベースのADD
命令のみを含めることができます。
圧縮されたアーカイブをSTDIN
: (docker build- <archive.tar.gz
)を介して渡すこともできます。アーカイブのルートにある Dockerfile と、アーカイブの残りの部分がビルドのコンテキストとして使用されます。
URL ファイルが認証を使用して保護されている場合、 ADD
命令は認証をサポートしていないため、 RUN wget
や RUN curl
を使用するか、コンテナ内から別のツールを使用する必要があります。
注意
最初に検出された
ADD
命令は、<src>
の内容が変更された場合、 Dockerfile からの後続のすべての命令のキャッシュを無効にします。
これにはRUN
命令のキャッシュの無効化が含まれます。
詳細については Dockerfile ベストプラクティスガイド – ビルドキャッシュを活用する を参照してください。
ADD
は次のルールに従います。
-
<src>
パスはビルドのコンテキスト内にある必要があります。
docker build の最初のステップはコンテキストディレクトリ(およびサブディレクトリ)を docker デーモンに送信することであるため、ADD ../something / something
はできません。 -
<src>
が URL であり、<dest>
が末尾のスラッシュで終わっていない場合、ファイルは URL からダウンロードされ、<dest>
にコピーされます。 -
<src>
が URL で、<dest>
が末尾にスラッシュで終わっている場合、ファイル名は URL から推測され、ファイルは<dest>/<filename>
にダウンロードされます。
たとえば、ADD http://example.com/foobar /
はファイル/foobar
を作成します。
この場合、適切なファイル名を検出できるように URL には重要なパスが必要です(http://example.com
は機能しません)。 -
<src>
がディレクトリの場合、ファイルシステムのメタデータを含むディレクトリの内容全体がコピーされます。
注意
ディレクトリ自体はコピーされず、その内容だけがコピーされます。
-
<src>
が認識された圧縮形式(gzip
,bzip2
またはxz
)のローカル tar アーカイブである場合、ディレクトリとして解凍されます。
リモート URL からのリソースは解凍されません。
ディレクトリがコピーまたは解凍されるとtar -x
と同じ動作になり、結果は次の和集合になります。- 宛先パスに存在するものは何でも
- 競合するソースツリーの内容はファイルごとに
2
を優先して解決されます。
注意
ファイルが認識された圧縮形式として識別されるかどうかは、ファイルの名前ではなく、ファイルの内容のみに基づいて行われます。
たとえば、空のファイルがたまたま.tar.gz
で終わっている場合、これは圧縮ファイルとして認識されず、解凍エラーメッセージは生成されず、ファイルは単に宛先にコピーされます。
-
<src>
が他の種類のファイルの場合、メタデータとともに個別にコピーされます。
この場合<dest>
の末尾にスラッシュ/
が付いていると、ディレクトリと見なされ、<src>
の内容は<dest>/base(<src>)
に書き込まれます。 - 直接またはワイルドカードの使用により複数の
<src>
リソースが指定されている場合、<dest>
はディレクトリである必要があり、スラッシュ/
で終了する必要があります。 -
<dest>
が末尾のスラッシュで終わっていない場合、それは通常のファイルと見なされ、<src>
の内容は<dest>
に書き込まれます。 -
<dest>
が存在しない場合は、パスに欠落しているすべてのディレクトリとともに作成されます。
COPY
COPY
は 2 つの形式を持ちます:
COPY [--chown=<user>:<group>] <src>... <dest>
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]
後者の形式は、空白を含むパスに必要です。
注意
--chown
機能は Linux コンテナの構築に使用される Dockerfile でのみサポートされており、 Windows コンテナでは機能しません。
ユーザーとグループの所有権の概念は Linux と Windows の間で変換されないため、ユーザー名とグループ名を ID に変換するために/etc/passwd
と/etc/group
を使用します。
この機能は Linux OS ベースのコンテナである場合に限り実行可能に制限されます。
COPY
命令は、新しいファイルまたはディレクトリを <src>
からコピーし、パス <dest>
でコンテナのファイルシステムに追加します。
複数の <src>
リソースを指定できますが、ファイルとディレクトリのパスは、ビルドのコンテキストのソースから見た相対パスとして解釈されます。
各 <src>
にはワイルドカードを含めることができ、照合は Go の filepath.Match
ルールを使用して行われます。
例えば hom
で始まるすべてのファイルを追加するには:
COPY hom* /mydir/
以下の例では ?
は home.txt
などの任意の 1 文字に置き換えられています。
COPY hom?.txt /mydir/
<dest>
は絶対パス、または WORKDIR
に相対的なパスであり、ソースは宛先コンテナ内にコピーされます。
以下の例では相対パスを使用して test.txt
を <WORKDIR>/relativeDir/
に追加しています。
COPY test.txt relativeDir/
この例では絶対パスを使用して test.txt
を /abstractDir/
に追加します。
COPY test.txt /absoluteDir/
特殊文字( [
や ]
など)を含むファイルやディレクトリをコピーする場合は、Go 言語のルールに従ってこれらのパスをエスケープして、一致するパターンとして扱われないようにする必要があります。
たとえば、 arr[0].txt
という名前のファイルをコピーするには、次を使用します。
COPY arr[[]0].txt /mydir/
オプションの --chown
フラグが、コピーされたコンテンツの特定の所有権を要求するために特定のユーザー名、グループ名、またはUID / GIDの組み合わせを指定しない限り、すべての新しいファイルとディレクトリは UID と GID が 0 で作成されます。
--chown
フラグの形式では、ユーザー名とグループ名の文字列、または直接整数の UID と GID を任意の組み合わせで使用できます。
グループ名なしのユーザー名または GID なしの UID を指定すると、 GID と同じ数値の UID が使用されます。
ユーザー名またはグループ名が指定されている場合、コンテナのルートファイルシステムの /etc/passwd
ファイルと /etc/group
ファイルを使用して、名前から整数の UID または GID への変換がそれぞれ実行されます。
次の例は、 --chown
フラグの有効な定義を示しています。
COPY --chown=55:mygroup files* /somedir/
COPY --chown=bin files* /somedir/
COPY --chown=1 files* /somedir/
COPY --chown=10:11 files* /somedir/
コンテナのルートファイルシステムに /etc/passwd
または /etc/group
ファイルが含まれておらず、ユーザー名またはグループ名が --chown
フラグで使用されている場合、ビルドは COPY
操作で失敗します。
数値 ID の使用はルックアップを必要とせず、コンテナルートファイルシステムのコンテンツに依存しません。
注意
STDIN
(docker build- < somefile
)を使用してビルドする場合、ビルドコンテキストがないためCOPY
は使用できません。
オプションで COPY
は、ソースの場所を前のビルドステージ( FROM .. AS <name>
で作成)に設定するために使用できるフラグ --from=<name>
を受け入れます。
ユーザーが送信するビルドコンテキストの代わりに使用されます。
指定された名前のビルドステージが見つからない場合は、代わりに同じ名前のイメージが使用されます。
COPY
は次のルールに従います:
-
<src>
パスはビルドのコンテキスト内にある必要があります。
dockerbuild
の最初のステップはコンテキストディレクトリ(およびサブディレクトリ)を docker デーモンに送信することであるため、COPY ../something /something
はできません。 -
<src>
がディレクトリの場合、ファイルシステムのメタデータを含むディレクトリの内容全体がコピーされます。
注意
ディレクトリ自体はコピーされず、その内容だけがコピーされます。
-
<src>
がディレクトリ以外の種類のファイルの場合、メタデータとともに個別にコピーされます。
この場合<dest>
の末尾にスラッシュ/
が付いていると、ディレクトリと見なされ、<src>
の内容は<dest>/base(<src>)
に書き込まれます。 - 直接またはワイルドカードの使用により複数の
<src>
リソースが指定されている場合、<dest>
はディレクトリである必要があり、スラッシュ/
で終了する必要があります。 -
<dest>
が末尾のスラッシュで終わっていない場合、それは通常のファイルと見なされ、<src>
の内容は<dest>
に書き込まれます。 -
<dest>
が存在しない場合は、パスに欠落しているすべてのディレクトリとともに作成されます。
注意
最初に検出された
COPY
命令は<src>
の内容が変更された場合、 Dockerfile からの後続のすべての命令のキャッシュを無効にします。
これにはRUN
命令のキャッシュの無効化が含まれます。
詳細については Dockerfile ベストプラクティスガイド – ビルドキャッシュを活用する を参照してください。
ENTRYPOINT
ENTRYPOINT
は 2 つの形式を持ちます:
推奨形式は exec
形式です:
ENTRYPOINT ["executable", "param1", "param2"]
シェル形式:
ENTRYPOINT command param1 param2
ENTRYPOINT
を使用すると、 executable
が実行されるコンテナを構成できます。
たとえば次の例では、 nginx をデフォルトのコンテンツで開始し、ポート 80 で待受けます。
$ docker run -i -t --rm -p 80:80 nginx
docker run <image>
へのコマンドライン引数は exec
形式ENTRYPOINT
のすべての要素の後に追加され、 CMD
を使用して指定されたすべての要素を上書きします。
これにより、引数をエントリポイントに渡すことができます。
つまり docker run <image> -d
は -d
引数をエントリポイントに渡します。
docker run --entrypoint
フラグを使用して ENTRYPOINT
命令を上書きできます。
シェル形式では CMD
またはコマンドライン引数の実行が使用されなくなりますが、 ENTRYPOINT
が信号を渡さない /bin/sh -c
のサブコマンドとして開始されるという欠点があります。
これは executable
がコンテナの PID 1 ではなく、 Unix シグナルを受信しないことを意味します。
したがって executable
は docker stop <container>
からSIGTERM
を受信しません。
Dockerfile の最後の ENTRYPOINT
命令のみが有効になります。
Exec 形式の ENTRYPOINT
の例
exec
形式の ENTRYPOINT
を使用して、かなり安定したデフォルトのコマンドと引数を設定してから、いずれかの形式の CMD
を使用して、変更される可能性が高い追加の既定動作を設定できます。
FROM ubuntu
ENTRYPOINT ["top", "-b"]
CMD ["-c"]
コンテナを実行すると top
が唯一のプロセスであることがわかります。
$ docker run -it --rm --name test top -H
top - 08:25:00 up 7:27, 0 users, load average: 0.00, 0.01, 0.05
Threads: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.1 us, 0.1 sy, 0.0 ni, 99.7 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem: 2056668 total, 1616832 used, 439836 free, 99352 buffers
KiB Swap: 1441840 total, 0 used, 1441840 free. 1324440 cached Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1 root 20 0 19744 2336 2080 R 0.0 0.1 0:00.04 top
結果をさらに調べるには docker exec
を使用できます。
$ docker exec -it test ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 2.6 0.1 19752 2352 ? Ss+ 08:24 0:00 top -b -H
root 7 0.0 0.1 15572 2164 ? R+ 08:25 0:00 ps aux
また docker stop test
を使用して top
を正常にシャットダウンするように要求できます。
次の Dockerfile は ENTRYPOINT
を使用して Apache をフォアグラウンドで(つまり PID 1 として)実行する方法を示しています。
FROM debian:stable
RUN apt-get update && apt-get install -y --force-yes apache2
EXPOSE 80 443
VOLUME ["/var/www", "/var/log/apache2", "/etc/apache2"]
ENTRYPOINT ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
単一の executable
のスタータースクリプトを作成する必要がある場合は exec
および gosu
コマンドを使用して、最後の executable
が Unix シグナルを確実に受信できるようにすることができます。
#!/usr/bin/env bash
set -e
if [ "$1" = 'postgres' ]; then
chown -R postgres "$PGDATA"
if [ -z "$(ls -A "$PGDATA")" ]; then
gosu postgres initdb
fi
exec gosu postgres "$@"
fi
exec "$@"
最後に、シャットダウン時に追加のクリーンアップを実行する(または他のコンテナと通信する)必要がある場合、または複数の executable
を調整する場合は、 ENTRYPOINT
スクリプトが Unix シグナルを送受信してさらにいくつかの作業を実行することを確認する必要があります。
#!/bin/sh
# Note: I've written this using sh so it works in the busybox container too
# USE the trap if you need to also do manual cleanup after the service is stopped,
# or need to start multiple services in the one container
trap "echo TRAPed signal" HUP INT QUIT TERM
# start service in background here
/usr/sbin/apachectl start
echo "[hit enter key to exit] or run 'docker stop <container>'"
read
# stop service and clean up here
echo "stopping apache"
/usr/sbin/apachectl stop
echo "exited $0"
このイメージを dockerrun -it --rm -p 80:80 --name test apache
で実行すると、 docker exec
または docker top
でコンテナーのプロセスを調べることができ、後続のスクリプトに Apache を停止するように依頼します。
$ docker exec -it test ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.0 4448 692 ? Ss+ 00:42 0:00 /bin/sh /run.sh 123 cmd cmd2
root 19 0.0 0.2 71304 4440 ? Ss 00:42 0:00 /usr/sbin/apache2 -k start
www-data 20 0.2 0.2 360468 6004 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
www-data 21 0.2 0.2 360468 6000 ? Sl 00:42 0:00 /usr/sbin/apache2 -k start
root 81 0.0 0.1 15572 2140 ? R+ 00:44 0:00 ps aux
$ docker top test
PID USER COMMAND
10035 root {run.sh} /bin/sh /run.sh 123 cmd cmd2
10054 root /usr/sbin/apache2 -k start
10055 33 /usr/sbin/apache2 -k start
10056 33 /usr/sbin/apache2 -k start
$ /usr/bin/time docker stop test
test
real 0m 0.27s
user 0m 0.03s
sys 0m 0.03s
注意
--entrypoint
を使用して ENTRYPOINT
設定を上書きできますが、これは binary
を exec
にのみ設定できます( sh -c
は使用されません)。
注意
exec
形式は JSON 配列として解析されます。
つまり単語の前後に一重引用符( '
)ではなく二重引用符( "
)を使用する必要があります。
シェル形式とは異なり exec
形式はコマンドシェルを呼び出しません。
これは通常のシェル処理が行われないことを意味します。
たとえば ENTRYPOINT ["echo", "$HOME"]
は、 $HOME
の変数置換を行いません。
シェル処理が必要な場合はシェル形式を使用するか、シェルを直接実行します。
例: ENTRYPOINT ["sh", "-c", "echo $HOME"]
シェル形式の場合のように exec
形式を使用してシェルを直接実行する場合、環境変数の展開を行うのは Docker ではなくシェルです。
シェル形式の ENTRYPOINT 記述例
ENTRYPOINT
にプレーンな文字列を指定すると /bin/sh -c
で実行されます。
この形式はシェル処理を使用してシェル環境変数を置き換え、 CMD
または docker run コマンドライン引数を無視します。
長時間実行されている ENTRYPOINT executable
を docker stop
が正しく通知するようにするには、 exec
で開始することを忘れないでください。
FROM ubuntu
ENTRYPOINT exec top -b
このイメージを実行すると単一の PID 1 プロセスが表示されます。
$ docker run -it --rm --name test top
Mem: 1704520K used, 352148K free, 0K shrd, 0K buff, 140368121167873K cached
CPU: 5% usr 0% sys 0% nic 94% idle 0% io 0% irq 0% sirq
Load average: 0.08 0.03 0.05 2/98 6
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
1 0 root R 3164 0% 0% top -b
docker stop
できれいに終了します:
$ /usr/bin/time docker stop test
test
real 0m 0.20s
user 0m 0.02s
sys 0m 0.04s
ENTRYPOINT
の先頭に exec
を追加するのを忘れた場合:
FROM ubuntu
ENTRYPOINT top -b
CMD --ignored-param1
次にそれを実行できます(次のステップの名前を付けます)。
$ docker run -it --name test top --ignored-param2
Mem: 1704184K used, 352484K free, 0K shrd, 0K buff, 140621524238337K cached
CPU: 9% usr 2% sys 0% nic 88% idle 0% io 0% irq 0% sirq
Load average: 0.01 0.02 0.05 2/101 7
PID PPID USER STAT VSZ %VSZ %CPU COMMAND
1 0 root S 3168 0% 0% /bin/sh -c top -b cmd cmd2
7 1 root R 3164 0% 0% top -b
指定された ENTRYPOINT
は、 top
の出力から PID 1 ではないことがわかります。
その後 docker stop test
を実行すると、コンテナーは正常に終了しません。
タイムアウト後に stop
コマンドは強制的に SIGKILL
を送信します。
$ docker exec -it test ps aux
PID USER COMMAND
1 root /bin/sh -c top -b cmd cmd2
7 root top -b
8 root ps aux
$ /usr/bin/time docker stop test
test
real 0m 10.19s
user 0m 0.04s
sys 0m 0.03s
CMD
と ENTRYPOINT
の相互作用を理解する
CMD
命令と ENTRYPOINT
命令はどちらも、コンテナの実行時に実行されるコマンドを定義します。
CMD
と ENTRYPOINT
の協業を説明する規則を示します。
- Dockerfile は少なくとも 1 つの
CMD
またはENTRYPOINT
コマンドを指定する必要があります。 - コンテナで
executable
を使用する場合はENTRYPOINT
を定義する必要があります。 -
CMD
はENTRYPOINT
コマンドのデフォルト引数を定義する方法として、またはコンテナでアドホックコマンドを実行する方法として使用する必要があります。 - 代替引数を使用してコンテナーを実行すると
CMD
が上書きされます。
次の表はさまざまな ENTRYPOINT
/ CMD
の組み合わせに対して実行されるコマンドを示しています。
No ENTRYPOINT | ENTRYPOINT exec_entry p1_entry | ENTRYPOINT [“exec_entry”, “p1_entry”] |
---|---|---|
No CMD | error, not allowed | /bin/sh -c exec_entry p1_entry |
CMD [“exec_cmd”, “p1_cmd”] | exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry |
CMD [“p1_cmd”, “p2_cmd”] | p1_cmd p2_cmd | /bin/sh -c exec_entry p1_entry |
CMD exec_cmd p1_cmd | /bin/sh -c exec_cmd p1_cmd | /bin/sh -c exec_entry p1_entry |
注意
ベースイメージから
CMD
が定義されている場合、ENTRYPOINT
を設定するとCMD
が空の値にリセットされます。
このシナリオで値を設定するには現在のイメージでCMD
を定義する必要があります。
VOLUME
VOLUME ["/data"]
VOLUME
命令は、指定された名前でマウントポイントを作成し、ネイティブホストまたは他のコンテナーから外部にマウントされたボリュームを保持するものとしてマークします。
値は JSON 配列 VOLUME ["/var/log/"]
、または VOLUME /var/log
や
VOLUME /var/log/ var/db
などの複数の引数を持つプレーン文字列にすることができます。
Docker クライアントを介した詳細、使用例とマウント手順については ボリュームを介したディレクトリの共有 を参照してください。
docker run コマンドは、新しく作成されたボリュームをベースイメージ内の指定された場所に存在するデータで初期化します。
たとえば、次の Dockerfile スニペットについて考えてみます。
FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol
この Dockerfile は docker run が /myvol
に新しいマウントポイントを作成し、新しく作成されたボリュームに greeting
ファイルをコピーするイメージになります。
ボリュームの指定についての注意事項
Dockerfile のボリュームについては、次の点に注意してください。
- Windows ベースのコンテナー上のボリューム: Windows ベースのコンテナーを使用する場合、コンテナー内のボリュームの宛先は次のいずれかである必要があります。
- 存在しない、または空のディレクトリ
-
C:
以外のドライブ
- Dockerfile 内からのボリュームの変更: ビルドステップで宣言後にボリューム内のデータが変更された場合、それらの変更は破棄されます。
- JSON フォーマット: リストは JSON 配列として解析されます。
単語は一重引用符('
)ではなく二重引用符("
)で囲む必要があります。 - ホストディレクトリはコンテナの実行時に宣言されます。
ホストディレクトリ(マウントポイント)はその性質上、ホストに依存します。
特定のホストディレクトリがすべてのホストで使用可能であるとは限らないため、これはイメージの移植性を維持するためです。
このため Dockerfile 内からホストディレクトリをマウントすることはできません。
VOLUME
命令はhost-dir
パラメーターの指定をサポートしていません。
コンテナを作成または実行するときに、マウントポイントを指定する必要があります。
USER
USER <user>[:<group>]
または
USER <UID>[:<GID>]
USER
命令はイメージの実行時と、 Dockerfileで RUN
、 CMD
、 ENTRYPOINT
に続く命令で使用するユーザー名(または UID)とオプションでユーザーグループ(またはGID)を設定します。
ユーザーのグループを指定する場合、ユーザーは指定されたグループメンバーシップのみを持つことに注意してください。
その他の構成済みグループメンバーシップは無視されます。
警告
ユーザーがプライマリグループを持っていない場合、イメージ(または次の手順)はルートグループで実行されます。
Windows では、組み込みアカウントでない場合は最初にユーザーを作成する必要があります。
これは Dockerfile の一部として呼び出されるnetuser
コマンドを使用して実行できます。
FROM microsoft/windowsservercore
# Create Windows user in the container
RUN net user /add patrick
# Set it for subsequent commands
USER patrick
WORKDIR
WORKDIR /path/to/workdir
WORKDIR
命令は、 Dockerfile でそれに続くすべての RUN
、 CMD
、 ENTRYPOINT
、 COPY
、および` ADD
命令の作業ディレクトリを設定します。
``WORKDIR`` が存在しない場合は、後続の Dockerfile 命令で使用されていなくても作成されます。
WORKDIR
命令は Dockerfile で複数回使用できます。
相対パスが指定されている場合、それは前の WORKDIR
命令のパスから見た相対パスになります。例えば:
WORKDIR /a
WORKDIR b
WORKDIR c
RUN pwd
この Dockerfile の最後の pwd
コマンドの出力は /a/b/c
になります。
WORKDIR
命令は、以前に ENV
を使用して設定された環境変数を解決できます。
Dockerfile で明示的に設定された環境変数のみを使用できます。
例えば:
ENV DIRPATH=/path
WORKDIR $DIRPATH/$DIRNAME
RUN pwd
この Dockerfile の最後の pwd
コマンドの出力は /path/$DIRNAME
になります。
ARG
ARG <name>[=<default value>]
ARG
命令はユーザーがビルド時に ``--build-arg =
フラグを使用して docker build コマンドでビルダーに渡すことができる変数を定義します。
ユーザーが Dockerfile で定義されていないビルド引数を指定すると、ビルドは警告を出力します。
[Warning] One or more build-args [foo] were not consumed.
Dockerfile には 1 つ以上の ARG
命令が含まれる場合があります。
たとえば以下は有効な Dockerfile です。
FROM busybox
ARG user1
ARG buildno
# ...
警告
github のキー、ユーザー資格情報などの秘密情報を渡すためにビルド時変数を使用することはお勧めしません。
ビルド時の変数値はdocker history
コマンドを使用してイメージのすべてのユーザーに表示されます。イメージをビルドするときに秘密情報を使用する安全な方法については BuildKit を使用してイメージをビルドする を参照してください。
既定値
ARG
命令には、オプションでデフォルト値を含めることができます。
FROM busybox
ARG user1=someuser
ARG buildno=1
# ...
ARG
命令にデフォルト値があり、ビルド時に値が渡されない場合、ビルダーはデフォルトを使用します。
Scope
ARG
変数の定義は、コマンドラインや他の場所での引数の使用からではなく、 Dockerfile で定義されている行から有効になります。
たとえば、次の Dockerfile について考えてみます。
FROM busybox
USER ${user:-some_user}
ARG user
USER $user
# ...
ユーザーは、次のコマンドを呼び出してこのファイルをビルドします。
$ docker build --build-arg user=what_user .
2 行目の USER
は、次の 3 行目でユーザー変数が定義されているため some_user
と評価されます。
4 行目の USER
は、ユーザーが定義され、 what_user
値がコマンドラインに渡されたときに what_user
と評価されます。
ARG
命令で定義される前は、変数を使用すると文字列が空になります。
ARG
命令は、それが定義されたビルドステージの最後でスコープ外になります。
複数のステージで arg
を使用するには、各ステージに ARG
命令を含める必要があります。
FROM busybox
ARG SETTINGS
RUN ./run/setup $SETTINGS
FROM busybox
ARG SETTINGS
RUN ./run/other $SETTINGS
ARG
変数の使用
ARG
または ENV
命令を使用して RUN
命令で使用可能な変数を指定できます。
ENV
命令を使用して定義された環境変数は、常に同じ名前の ARG
命令を上書きします。
ENV
および ARG
命令を含むこの Dockerfile について考えてみます。
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=v1.0.0
RUN echo $CONT_IMG_VER
次に、このイメージが次のコマンドで作成されていると仮定します。
$ docker build --build-arg CONT_IMG_VER=v2.0.1 .
この場合 RUN
命令は user:v2.0.1
によって渡された ARG
設定の代わりに v1.0.0 を使用します。
この動作は、ローカルスコープの変数が引数として渡された変数または環境から継承された変数を定義の観点から上書きするシェルスクリプトに似ています。
上記の例を使用しますが、異なる ENV
仕様を使用すると、 ARG
と ENV
命令の間にさらに便利な相互作用を作成できます。
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=${CONT_IMG_VER:-v1.0.0}
RUN echo $CONT_IMG_VER
ARG
命令とは異なり、 ENV
値は常にビルドされたイメージに保持されます。
--build-arg
フラグのない docker build を考えてみましょう:
$ docker build .
この Dockerfile の例を使用すると CONT_IMG_VER
は引き続きイメージに保持されますが、 ENV
命令によって 3 行目で設定された既定値であるため、その値は v1.0.0 になります。
この例の変数展開手法を使用すると、コマンドラインから引数を渡し、
ENV
命令を利用してそれらを最終イメージに永続化できます。
変数展開は Dockerfile 命令の限られた組合せでのみサポートされます。
定義済み ARG
Docker には Dockerfile 内の対応する ARG
命令なしで使用できる定義済み ARG
変数のセットがあります。
- HTTP_PROXY
- http_proxy
- HTTPS_PROXY
- https_proxy
- FTP_PROXY
- ftp_proxy
- NO_PROXY
- no_proxy
これらを使用するには、フラグを使用してコマンドラインで渡すだけです。
--build-arg <varname>=<value>
デフォルトでは、これらの定義済み変数は docker history
の出力から除外されます。
定義済み変数を除外すると、 HTTP_PROXY
変数内の機密認証情報が誤って漏洩するリスクが軽減されます。
たとえば --build-arg HTTP_PROXY=http://user:pass@proxy.lon.example.com
を使用して次の Dockerfile をビルドすることを検討してください。
FROM ubuntu
RUN echo "Hello World"
この場合 HTTP_PROXY
変数の値は、 docker history
で使用できず、キャッシュされません。
場所を変更し、プロキシサーバーが http://user:pass@proxy.sfo.example.com
に変更された場合、後続のビルドでキャッシュミスが発生することはありません。
この動作を上書きする必要がある場合は、次のように Dockerfile に ARG
ステートメントを追加することで上書きできます。
FROM ubuntu
ARG HTTP_PROXY
RUN echo "Hello World"
この Dockerfile をビルドすると、 HTTP_PROXY
は docker history
に保存され、その値を変更するとビルドキャッシュが無効になります。
グローバルスコープの自動プラットフォーム ARG
この機能は BuildKit バックエンドを使用している場合にのみ使用できます。
Docker は、ビルドを実行するノードのプラットフォーム(ビルドプラットフォーム)と結果のイメージのプラットフォーム(ターゲットプラットフォーム)に関する情報を使用して、一連の ARG
変数を事前定義します。
ターゲットプラットフォームは docker build の --platform
フラグで指定できます。
次の ARG
変数が自動的に設定されます。
- TARGETPLATFORM - ビルド結果のプラットフォーム。
例: linux/amd64, linux/arm/v7, windows/amd64. - TARGETOS - TARGETPLATFORM の OS コンポーネント
- TARGETARCH - TARGETPLATFORM のアーキテクチャーコンポーネント
- TARGETVARIANT - TARGETPLATFORM の変数コンポーネント
- BUILDPLATFORM - ビルドを実行するノードのプラットフォーム。
- BUILDOS - BUILDPLATFORM の OS コンポーネント
- BUILDARCH - BUILDPLATFORM のアーキテクチャーコンポーネント
- BUILDVARIANT - BUILDPLATFORM の変数コンポーネント
これらの引数はグローバルスコープで定義されているため、ビルドステージ内や RUN
コマンドで自動的に使用することはできません。
ビルドステージ内でこれらの引数の 1 つを公開するには、値なしで再定義します。
例えば:
FROM alpine
ARG TARGETPLATFORM
RUN echo "I'm building for $TARGETPLATFORM"
ビルドキャッシュへの影響
ARG
変数は、 ENV
変数のようにビルドされたイメージに永続化されません。
ただし ARG
変数は同様の方法でビルドキャッシュに影響を与えます。
Dockerfile が以前のビルドとは値が異なる ARG
変数を定義している場合、その定義ではなく、最初の使用時に cache miss
が発生します。
特に ARG
命令に続くすべての RUN
命令は、 ARG
変数を暗黙的に(環境変数として)使用するため、キャッシュミスを引き起こす可能性があります。
Dockerfile に一致する ARG
ステートメントがない限り、すべての定義済み ARG
変数はキャッシュから除外されます。
たとえば次の 2 つの Dockerfile について考えてみます。
FROM ubuntu
ARG CONT_IMG_VER
RUN echo $CONT_IMG_VER
FROM ubuntu
ARG CONT_IMG_VER
RUN echo hello
コマンドラインで --build-arg CONT_IMG_VER=<value>
を指定した場合、どちらの場合も、 2 行目の指定でキャッシュミスは発生しません。
3 行目はキャッシュミスを引き起こします。
ARG CONT_IMG_VER
により、 RUN
行は CONT_IMG_VER=<value> echo hello
の実行と同じものとして識別されるため、 <value>
が変更されるとキャッシュミスが発生します。
同じコマンドラインで別の例を考えてみましょう。
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=$CONT_IMG_VER
RUN echo $CONT_IMG_VER
この例ではキャッシュミスは 3 行目で発生します。
キャッシュミスは ENV
変数の値が ARG
変数を参照し、その変数がコマンドラインで変更されるために発生します。
この例では ENV
コマンドにより、イメージに値が含まれます。
この Dockerfile のように、 ENV
命令が同じ名前の ARG
命令を上書きする場合:
FROM ubuntu
ARG CONT_IMG_VER
ENV CONT_IMG_VER=hello
RUN echo $CONT_IMG_VER
3 行目では CONT_IMG_VER
の値が定数(hello)であるため、キャッシュミスは発生しません。
その結果 RUN
(4 行目)で使用される環境変数と値はビルド間で変更されません。
ONBUILD
ONBUILD <INSTRUCTION>
ONBUILD
命令はイメージが別のビルドのベースとして使用されるときに、後で実行されるトリガー命令をイメージに追加します。
トリガーは、ダウンストリーム Dockerfile の FROM
命令の直後に挿入されたかのように、ダウンストリームビルドのコンテキストで実行されます。
任意のビルド命令をトリガーとして登録できます。
これは他のイメージをビルドするためのベースとして使用されるイメージをビルドする場合に役立ちます。
たとえばアプリケーションビルド環境や、ユーザー固有の構成でカスタマイズできるデーモンなどです。
たとえばイメージが再利用可能な Python アプリケーションビルダーである場合、特定のディレクトリにアプリケーションソースコードを追加する必要があり、その後にビルドスクリプトを呼び出す必要がある場合があります。
アプリケーションのソースコードにはまだアクセスできず、アプリケーションのビルドごとに異なるため、今は単純に ADD
と RUN
を呼び出すことはできません。
アプリケーション開発者にボイラープレート Dockerfile を提供して、アプリケーションにコピーアンドペーストすることもできますが、
これは非効率的で、エラーが発生しやすく、アプリケーション固有のコードと混在するため、更新が困難です。
解決策は ONBUILD
を使用して、次のビルドステージで後で実行する事前命令を登録することです。
仕組みは次のとおりです。
-
ONBUILD
命令が発生すると、ビルダーはビルド中のイメージのメタデータにトリガーを追加します。
それ以外の場合、命令は現在のビルドに影響を与えません。 - ビルドの最後に、すべてのトリガーのリストがイメージマニフェストの
OnBuild
キーの下に保存されます。
それらはdocker inspect
コマンドで検査できます。 - 後で
FROM
命令を使用して、イメージを新しいビルドのベースとして使用できます。
FROM
命令の処理の一環として、ダウンストリームビルダーはONBUILD
トリガーを探し、登録されたのと同じ順序でそれらを実行します。
いずれかのトリガーが失敗すると、FROM
命令が中止され、ビルドが失敗します。
すべてのトリガーが成功すると、FROM
命令が完了し、ビルドは通常どおり続行されます。 - トリガーは、実行後に最終イメージからクリアされます。
言い換えれば、それらは「孫」ビルドによって継承されません。
たとえば次のようなものを追加できます。
ONBUILD ADD . /app/src
ONBUILD RUN /usr/local/bin/python-build --dir /app/src
警告
ONBUILD ONBUILD
を使用してONBUILD
命令を連鎖させることは許可されていません。
ONBUILD
命令はFROM
またはMAINTAINER
命令をトリガーしない場合があります。
STOPSIGNAL
STOPSIGNAL signal
STOPSIGNAL
命令は、終了するためにコンテナに送信されるシステムコール信号を設定します。
このシグナルは、カーネルの syscall
テーブル内の位置(たとえば 9)と一致する有効な符号なしの番号、または SIGNAME
形式のシグナル名(たとえば SIGKILL
)にすることができます。
HEALTHCHECK
HEALTHCHECK
命令には 2 種類の形式があります:
-
HEALTHCHECK [OPTIONS] CMD command
(コンテナ内でコマンドを実行して、コンテナの状態を確認します) -
HEALTHCHECK NONE
(ベースイメージから継承されたヘルスチェックを無効にする)
HEALTHCHECK
命令は、コンテナをテストしてコンテナがまだ機能していることを確認する方法を Docker に指示します。
これにより、サーバープロセスがまだ実行されていても Web サーバーが無限ループに陥り、新しい接続を処理できないなどのケースを検出できます。
コンテナにヘルスチェックが指定されている場合、通常のステータスに加えてヘルスステータスがあります。
このステータスは最初は「開始中」です。
ヘルスチェックに合格すると、ヘルスチェックが「正常」になります(以前の状態に関係なく)。
一定数の連続した失敗の後、「異常」となります。
CMD
の前に表示されるオプションは次のとおりです。
-
--interval=DURATION
(既定値: 30s) -
--timeout=DURATION
(既定値: 30s) -
--start-period=DURATION
(既定値: 0s) -
--retries=N
(既定値: 3)
ヘルスチェックは、最初にコンテナが開始されてから数秒後に実行され、次に前の各チェックが完了してから数秒後に再度実行されます。
チェックの 1 回の実行にタイムアウト秒より長い時間がかかる場合、チェックは失敗したと見なされます。
コンテナが異常であると見なされるには、ヘルスチェックの連続した失敗を再試行する必要があります。
開始期間はブートストラップに時間が必要なコンテナーの初期化時間を提供します。
その期間中のプローブ障害は、最大再試行回数にはカウントされません。
ただし、開始期間中にヘルスチェックが成功した場合、コンテナーは開始されたと見なされ、連続するすべての失敗は最大再試行回数にカウントされます。
Dockerfile には 1 つの HEALTHCHECK
命令しか存在できません。
複数列記すると最後の HEALTHCHECK
のみが有効になります。
CMD
キーワードの後のコマンドは、シェルコマンド(例: HEALTHCHECK CMD /bin/check-running
)または exec
配列(他の Dockerfile コマンドと同様)のいずれかです。
(詳細については ENTRYPOINT
を参照してください)
コマンドの終了ステータスは、コンテナのヘルスステータスを示します。
有効な値は次のとおりです。
- 0: success - コンテナは正常ですぐに使用できます
- 1: unhealthy - コンテナが正しく機能していません
- 2: reserved - この終了コードは使用しないでください
たとえば 5 分ごとにチェックして、ウェブサーバーが 3 秒以内にサイトのメインページにサービスを提供できるようにするには、次のようにします。
HEALTHCHECK --interval=5m --timeout=3s \
CMD curl -f http://localhost/ || exit 1
失敗したプローブのデバッグを支援するために、コマンドが stdout
または stderr
に書き込む出力テキスト(UTF-8 エンコード)はヘルスステータスに保存され docker inspect
で検索できます。
このような出力は短くする必要があります(現在、最初の 4096 バイトのみが格納されています)。
コンテナのヘルスステータスが変更されると、新しいステータスで health_status
イベントが生成されます。
HEALTHCHECK
機能は Docker 1.12 から追加されました。
SHELL
SHELL ["executable", "parameters"]
SHELL
命令を使用すると、シェル形式のコマンドに使用されるデフォルトのシェルを上書きできます。
Linux のデフォルトシェルは ["/bin/sh", "-c"]
です。
Windows のデフォルトシェルは ["cmd", "/S", "/C"]
です。
SHELL
命令は Dockerfile に JSON 形式で記述する必要があります。
SHELL
命令は一般的に使用されているまったく異なる 2 つのネイティブシェル( cmd
と powershell
)と、 sh
を含む代替シェルが利用可能な Windows で特に役立ちます。
SHELL
命令は複数回表示される可能性があります。
各 SHELL
命令は、以前のすべての SHELL
命令を上書きし、後続のすべての命令に影響を与えます。
例:
FROM microsoft/windowsservercore
# Executed as cmd /S /C echo default
RUN echo default
# Executed as cmd /S /C powershell -command Write-Host default
RUN powershell -command Write-Host default
# Executed as powershell -command Write-Host hello
SHELL ["powershell", "-command"]
RUN Write-Host hello
# Executed as cmd /S /C echo hello
SHELL ["cmd", "/S", "/C"]
RUN echo hello
次の命令はシェル形式が Dockerfile で使用されている場合に SHELL
命令の影響を受ける可能性があります:
RUN
CMD
ENTRYPOINT
次の例は SHELL
命令を使用して合理化できる Windows で見られる一般的なパターンです。
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
docker によって呼び出されるコマンドは次のようになります。
cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
これは 2 つの理由で非効率的です。
まず、不要な cmd.exe
コマンドプロセッサ(別名シェル)が呼び出されています。
次に、シェル形式の各 RUN
命令には、コマンドの前に追加の powershell -command
が必要です。
これをより効率的にするために 2 つのメカニズムのうちの 1 つを使用することができます。
1 つは次のような RUN
コマンドの JSON 形式を使用することです。
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
JSON 形式は明確であり、不要な cmd.exe
を使用しませんが、二重引用符とエスケープにより、より詳細な情報が必要になります。
別のメカニズムは SHELL
命令とシェル形式を使用することです。
これにより、特にエスケープパーサーディレクティブと組み合わせると Windows ユーザーにとってより自然な構文になります。
# escape=`
FROM microsoft/nanoserver
SHELL ["powershell","-command"]
RUN New-Item -ItemType Directory C:\Example
ADD Execute-MyCmdlet.ps1 c:\example\
RUN c:\example\Execute-MyCmdlet -sample 'hello world'
実行結果:
PS E:\docker\build\shell> docker build -t shell .
Sending build context to Docker daemon 4.096 kB
Step 1/5 : FROM microsoft/nanoserver
---> 22738ff49c6d
Step 2/5 : SHELL powershell -command
---> Running in 6fcdb6855ae2
---> 6331462d4300
Removing intermediate container 6fcdb6855ae2
Step 3/5 : RUN New-Item -ItemType Directory C:\Example
---> Running in d0eef8386e97
Directory: C:\
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/28/2016 11:26 AM Example
---> 3f2fbf1395d9
Removing intermediate container d0eef8386e97
Step 4/5 : ADD Execute-MyCmdlet.ps1 c:\example\
---> a955b2621c31
Removing intermediate container b825593d39fc
Step 5/5 : RUN c:\example\Execute-MyCmdlet 'hello world'
---> Running in be6d8e63fe75
hello world
---> 8e559e9bf424
Removing intermediate container be6d8e63fe75
Successfully built 8e559e9bf424
PS E:\docker\build\shell>
SHELL
命令は、シェルの動作方法を変更する目的にも使用できます。
たとえば Windows で SHELL cmd /S /C /V:ON|OFF
を使用すると、遅延環境変数の拡張セマンティクスを変更できます。
SHELL
命令は zsh, csh, tcsh などの代替シェルが必要な場合に Linux でも使用できます。
SHELL
機能は Docker 1.12 で追加されました。
外部実装機能
この機能は BuildKit バックエンドを使用している場合にのみ使用できます。
docker build は、構文ディレクティブを使用してビルダーの外部実装を使用することで有効になる、キャッシュマウント、ビルドシークレット、 ssh 転送などの実験的な機能をサポートします。
これらの機能については BuildKit リポジトリのドキュメント を参照してください。
Dockerfile 記述例
以下に Dockerfile 構文の例をいくつか示します。
# Nginx
#
# VERSION 0.0.1
FROM ubuntu
LABEL Description="This image is used to start the foobar executable" Vendor="ACME Products" Version="1.0"
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
# Firefox over VNC
#
# VERSION 0.3
FROM ubuntu
# Install vnc, xvfb in order to create a 'fake' display and firefox
RUN apt-get update && apt-get install -y x11vnc xvfb firefox
RUN mkdir ~/.vnc
# Setup a password
RUN x11vnc -storepasswd 1234 ~/.vnc/passwd
# Autostart firefox (might not be the best way, but it does the trick)
RUN bash -c 'echo "firefox" >> /.bashrc'
EXPOSE 5900
CMD ["x11vnc", "-forever", "-usepw", "-create"]
# Multiple images example
#
# VERSION 0.1
FROM ubuntu
RUN echo foo > bar
# Will output something like ===> 907ad6c2736f
FROM ubuntu
RUN echo moo > oink
# Will output something like ===> 695d7793cbe4
# You'll now have two images, 907ad6c2736f with /bar, and 695d7793cbe4 with
# /oink.