LoginSignup
3
6

More than 3 years have passed since last update.

Dockerfile リファレンス 日本語訳

Last updated at Posted at 2020-10-20

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 の以下に示す命令でサポートされています。

環境変数の置換では、命令全体を通じて各変数に同じ値が使用されます。
言い換えると、この例では次のようになります。

ENV abc=hello
ENV abc=bye def=$abc
ENV ghi=$abc

結果は bye ではなく hello の値を持つ def になります。
ただし ghiabcbye に設定したのと同じ命令の一部ではないため、 bye の値になります。

.dockerignore ファイル

docker CLI はコンテキストを docker デーモンに送信する前に、コンテキストのルートディレクトリで .dockerignore という名前のファイルを探します。
このファイルが存在する場合 CLI はコンテキストを変更して、その中のパターンに一致するファイルとディレクトリを除外します。
これにより、大きなファイルや機密性の高いファイルやディレクトリをデーモンに不必要に送信したり、 ADD または COPY を使用してイメージに追加したりすることを回避できます。

CLIは .dockerignore ファイルを Unix シェルのファイルグロブに似た改行で区切られたパターンのリストとして解釈します。
照合の目的で、コンテキストのルートは作業ディレクトリとルートディレクトリの両方であると見なされます。
たとえば、パターン /foo/barfoo/bar はどちらも、 PATHfoo サブディレクトリまたは 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*.mdREADME-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 の前にある可能性がある唯一の命令です。 ARGFROM の相互作用を理解する を参照してください。
  • FROM は、単一の Dockerfile 内に複数回出現して、複数のイメージを作成したり、あるビルドステージを別のビルドステージの依存関係として使用したりできます。 新しい FROM 命令の前に、 commit によって出力された最後のイメージ ID をメモするだけです。 各 FROM 命令は、前の命令によって作成されたすべての状態をクリアします。
  • オプションで FROM 命令に AS name を追加することにより、新しいビルドステージに名前を付けることができます。 この名前は、後続の FROM および COPY --from=<name> 命令で使用して、このステージで作成されたイメージを参照できます。
  • タグまたはダイジェスト値はオプションです。 いずれかを省略すると、ビルダーはデフォルトで最新のタグを想定します。 タグ値が見つからない場合、ビルダーはエラーを返します。

オプションの --platform フラグを使用して、 FROM がマルチプラットフォームイメージを参照する場合にイメージのプラットフォームを指定できます。
たとえば、 linux/amd64linux/arm64 、または windows/amd64 です。
デフォルトでは、ビルドリクエストのターゲットプラットフォームが使用されます。
このフラグの値にはグローバルビルド引数を使用できます。
たとえば、自動プラットフォーム引数を使用すると、ステージをネイティブビルドプラットフォームに強制し、それを使用してステージ内のターゲットプラットフォームにクロスコンパイルできます。
( --platform=$BUILDPLATFORM )

ARGFROM の相互作用を理解する

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 を実行したい場合は、ENTRYPOINTCMD と組み合わせて使用​​することを検討する必要があります。
ENTRYPOINT を参照してください。

ユーザーが docker run の引数を指定すると、 CMD で指定された既定値が上書きされます。

注意

RUNCMD を混同しないでください。
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 wgetRUN 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 と同じ動作になり、結果は次の和集合になります。
    1. 宛先パスに存在するものは何でも
    2. 競合するソースツリーの内容はファイルごとに 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 シグナルを受信しないことを意味します。
したがって executabledocker 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 設定を上書きできますが、これは binaryexec にのみ設定できます( 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 executabledocker 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

CMDENTRYPOINT の相互作用を理解する

CMD 命令と ENTRYPOINT 命令はどちらも、コンテナの実行時に実行されるコマンドを定義します。
CMDENTRYPOINT の協業を説明する規則を示します。

  1. Dockerfile は少なくとも 1 つの CMD または ENTRYPOINT コマンドを指定する必要があります。
  2. コンテナで executable を使用する場合は ENTRYPOINT を定義する必要があります。
  3. CMDENTRYPOINT コマンドのデフォルト引数を定義する方法として、またはコンテナでアドホックコマンドを実行する方法として使用する必要があります。
  4. 代替引数を使用してコンテナーを実行すると 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で RUNCMDENTRYPOINT に続く命令で使用するユーザー名(または 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 でそれに続くすべての RUNCMDENTRYPOINTCOPY 、および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 <varname>=<value> ` フラグを使用して 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 仕様を使用すると、 ARGENV 命令の間にさらに便利な相互作用を作成できます。

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_PROXYdocker 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 アプリケーションビルダーである場合、特定のディレクトリにアプリケーションソースコードを追加する必要があり、その後にビルドスクリプトを呼び出す必要がある場合があります。
アプリケーションのソースコードにはまだアクセスできず、アプリケーションのビルドごとに異なるため、今は単純に ADDRUN を呼び出すことはできません。
アプリケーション開発者にボイラープレート Dockerfile を提供して、アプリケーションにコピーアンドペーストすることもできますが、
これは非効率的で、エラーが発生しやすく、アプリケーション固有のコードと混在するため、更新が困難です。

解決策は ONBUILD を使用して、次のビルドステージで後で実行する事前命令を登録することです。

仕組みは次のとおりです。

  1. ONBUILD 命令が発生すると、ビルダーはビルド中のイメージのメタデータにトリガーを追加します。 それ以外の場合、命令は現在のビルドに影響を与えません。
  2. ビルドの最後に、すべてのトリガーのリストがイメージマニフェストの OnBuild キーの下に保存されます。 それらは docker inspect コマンドで検査できます。
  3. 後で FROM 命令を使用して、イメージを新しいビルドのベースとして使用できます。 FROM 命令の処理の一環として、ダウンストリームビルダーは ONBUILD トリガーを探し、登録されたのと同じ順序でそれらを実行します。 いずれかのトリガーが失敗すると、 FROM 命令が中止され、ビルドが失敗します。 すべてのトリガーが成功すると、 FROM 命令が完了し、ビルドは通常どおり続行されます。
  4. トリガーは、実行後に最終イメージからクリアされます。 言い換えれば、それらは「孫」ビルドによって継承されません。

たとえば次のようなものを追加できます。

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 つのネイティブシェル( cmdpowershell )と、 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.
3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6