サーチ…


前書き

Dockerfilesは、プログラムでDockerイメージを構築するために使用されるファイルです。 Dockerイメージを迅速かつ再現性よく作成できるため、共同作業に役立ちます。 Dockerファイルには、Dockerイメージを作成するための指示が含まれています。各命令は1行に記述され、 <INSTRUCTION><argument(s)>の形式で与えられます。 Docker docker buildコマンドを使用してDockerイメージを構築するには、Dockerfilesを使用します。

備考

Dockerfilesの形式は次のとおりです。

# This is a comment
INSTRUCTION arguments
  • コメントは#始まります。
  • 指示は大文字のみです
  • 基本イメージを指定するには、Dockerfileの最初の命令がFROMなければなりません

Dockerファイルを構築するとき、DockerクライアントはDockerデーモンに「構築コンテキスト」を送信します。ビルドコンテキストには、Dockerfileと同じディレクトリにあるすべてのファイルとフォルダが含まれます。 COPYおよびADD操作では、このコンテキストのファイルしか使用できません。


一部のDockerファイルは、次のもので始まることがあります。

# escape=`

これは、Dockerパーサに` \代わりにエスケープ文字として使用するよう指示するために使用されます。これは主にWindows Dockerファイルに便利です。

HelloWorldドッカーファイル

最小のDockerfileは次のようになります。

FROM alpine
CMD ["echo", "Hello StackOverflow!"]

これにより、DockerはアルパインFROM )に基づくイメージを構築し、コンテナーの最小限の配布を行い、結果イメージを実行するときに特定のコマンド( CMD )を実行するよう指示します。

ビルドして実行する:

docker build -t hello .
docker run --rm hello

これは出力されます:

Hello StackOverflow!

ファイルのコピー

Dockerイメージのビルドコンテキストからファイルをコピーするには、 COPY命令を使用します。

COPY localfile.txt containerfile.txt

ファイル名にスペースが含まれている場合は、代替構文を使用します。

COPY ["local file", "container file"]

COPYコマンドはワイルドカードをサポートしています。たとえば、すべてのイメージをimages/ディレクトリにコピーするために使用できます。

COPY *.jpg images/

注:この例では、 images/が存在しない可能性があります。この場合、Dockerは自動的に作成します。

ポートを公開する

Dockerfileから公開されたポートを宣言するには、 EXPOSE命令を使用します。

EXPOSE 8080 8082

Exposed portsの設定はDockerコマンドラインからオーバーライドできますが、Dockerファイルに明示的に設定することをお勧めします。

Dockerfilesのベストプラクティス

グループの一般的な操作

Dockerは画像をレイヤーの集合として構築します。各レイヤーは、ファイルが削除されたことをこのデータが示している場合でも、データを追加することができます。すべての命令が新しいレイヤーを作成します。例えば:

RUN apt-get -qq update
RUN apt-get -qq install some-package

欠点がいくつかあります:

  • 2つのレイヤーが作成され、より大きなイメージが生成されます。
  • RUN文で単独でapt-get updateを使用するとキャッシュの問題が発生し、 apt-get install命令が失敗することがあります。あとでパッケージを追加してapt-get install変更した後、ドッカーが最初の命令と変更した命令を同じものとして解釈し、前の手順のキャッシュを再利用するとします。その結果、 apt-get updateコマンドは、ビルド中にそのキャッシュされたバージョンが使用されるため、実行されません

代わりに、以下を使用します。

RUN apt-get -qq update && \
    apt-get -qq install some-package

1つのレイヤーしか生成しないためです。

メンテナ

通常これはDockerfileの2行目です。誰が担当し、助けることができるのかを伝えます。

LABEL maintainer John Doe <[email protected]>

あなたがそれをスキップすると、あなたのイメージを壊すことはありません。しかし、それはあなたのユーザーのどちらにも役立ちません。

簡潔にする

Dockerファイルを短くしてください。複雑な設定が必要な場合は、専用のスクリプトを使用するか、ベースイメージを設定することを検討してください。

ユーザー指導

USER daemon

USER命令は、イメージを実行し、いずれかの場合に使用するユーザー名またはUIDを設定RUNCMDENTRYPOINTで、それに続く命令Dockerfile

ワークディレクション

WORKDIR /path/to/workdir

WORKDIR命令は、 WORKDIR RUNCMDENTRYPOINTCOPY 、およびADD命令の作業ディレクトリを設定します。 WORKDIRが存在しない場合は、後続のDockerfile命令で使用されていなくても作成されます。

1つの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

音量指示

VOLUME ["/data"]

VOLUME命令は、指定された名前のマウント・ポイントを作成し、ネイティブ・ホストまたは他のコンテナーから外部マウント・ボリュームを保持するものとしてマークします。値は、JSON配列、 VOLUME ["/var/log/"] 、またはVOLUME /var/logVOLUME /var/log /var/dbなどの複数の引数を持つプレーンな文字列です。 Dockerクライアントを使用した詳細情報や例、マウント方法については、ボリュームを介した共有ディレクトリを参照してください。

docker runコマンドは、新しく作成されたボリュームを、ベースイメージ内の指定された場所に存在するデータで初期化します。たとえば、次のDockerfileスニペットを考えてみましょう。

FROM ubuntu
RUN mkdir /myvol
RUN echo "hello world" > /myvol/greeting
VOLUME /myvol

このDockerfileの結果、dockerが実行され、/ myvolに新しいマウントポイントが作成され、新しく作成されたボリュームにグリーティングファイルがコピーされます。

注:宣言後にボリューム内のデータを変更するビルドステップがあれば、その変更は破棄されます。

注意:リストはJSON配列として解析されます。つまり、一重引用符( ')ではなく、二重引用符( ")を使用する必要があります。

COPY命令

COPYは2つの形式があります。

COPY <src>... <dest>
COPY ["<src>",... "<dest>"] (this form is required for paths containing whitespace)

COPY命令は、 <src>から新しいファイルまたはディレクトリをコピーし、パス<dest>コンテナのファイルシステムに追加します。

複数の<src>リソースを指定できますが、ビルド元のソースディレクトリ(ビルドのコンテキスト)に対して相対的でなければなりません。

<src>はワイルドカードが含まれ、一致はGoのfilepath.Matchを使用して行われます。一致ルール。例えば:

COPY hom* /mydir/        # adds all files starting with "hom"
COPY hom?.txt /mydir/    # ? is replaced with any single character, e.g., "home.txt"

<dest>は、宛先コンテナ内でソースがコピーされる絶対パスまたはWORKDIR基準とするパスです。

COPY test relativeDir/   # adds "test" to `WORKDIR`/relativeDir/
COPY test /absoluteDir/  # adds "test" to /absoluteDir/

すべての新しいファイルとディレクトリは、UIDとGIDが0で作成されます。

注:stdin( docker build - < somefile )を使用してビルドする場合、ビルドコンテキストは存在しないため、 COPYは使用できません。

COPYは以下の規則に従います:

  • <src>パスはビルドのコンテキスト内になければなりません。ドッカービルドの最初のステップは、コンテキストディレクトリ(およびサブディレクトリ)をドッカーデーモンに送信することなので、 COPY ../something/ somethingをCOPYできません。

  • <src>がディレクトリの場合、ファイルシステムのメタデータを含め、ディレクトリの内容全体がコピーされます。注:ディレクトリ自体はコピーされず、その内容だけがコピーされます。

  • <src>が他の種類のファイルである場合、そのメタデータと共に個別にコピーされます。この場合、 <dest>が末尾にスラッシュ/で終わると、ディレクトリとみなされ、 <src>内容は<dest>/base(<src>)書き込まれます。

  • 複数の<src>リソースが直接指定されている場合、またはワイルドカードの使用のために指定されている場合、 <dest>はディレクトリでなければならず、スラッシュ/終わる必要があります。

  • <dest>の末尾にスラッシュがない場合、通常のファイルとみなされ、 <src>内容は<dest>書き込まれます。

  • <dest>が存在しない場合は、そのパスに存在しないすべてのディレクトリと共に作成されます。

ENVおよびARG命令

ENV

ENV <key> <value>
ENV <key>=<value> ...

ENV命令は、環境変数<key>を値に設定します。この値はすべての "子孫" Dockerfileコマンドの環境にあり、多くの場合でもインラインで置き換えることができます。

ENV命令には2つの形式があります。最初の形式ENV <key> <value>は、単一の変数を値に設定します。最初のスペースの後の文字列全体は、スペースや引用符などの文字を含む<value>として扱われます。

第2の形式、 ENV <key>=<value> ...は、一度に複数の変数を設定することを可能にします。 2番目のフォームは構文で等号(=)を使用していますが、最初のフォームではそうではありません。コマンドライン解析と同様に、引用符とバックスラッシュを使用して値にスペースを含めることができます。

例えば:

ENV myName="John Doe" myDog=Rex\ The\ Dog \
    myCat=fluffy

そして

ENV myName John Doe
ENV myDog Rex The Dog
ENV myCat fluffy

最終コンテナで同じネット結果が得られますが、単一のキャッシュレイヤーを生成するため、最初のフォームが優先されます。

ENVを使用して設定された環境変数は、コンテナが結果のイメージから実行されたときにも保持されます。 docker run --env <key>=<value> inspectを使用して値を表示し、 docker run --env <key>=<value>を使用して値を変更できdocker run --env <key>=<value>

ARG

設定を保持しない場合は、代わりにARG使用してください。 ARGは構築中にのみ環境を設定します。たとえば、

ENV DEBIAN_FRONTEND noninteractive

apt-getユーザは、 docker exec -it the-container bash介して対話コンテキストでコンテナに入ったときに、Debianベースのイメージを混乱させる可能性があります。

代わりに、以下を使用します。

ARG DEBIAN_FRONTEND noninteractive

次のコマンドを使用するだけで、1つのコマンドに値を設定することもできます。

RUN <key>=<value> <command>

露出指示

EXPOSE <port> [<port>...]

EXPOSE命令は、コンテナが実行時に指定されたネットワークポートをリッスンすることをDockerに通知します。 EXPOSEは、コンテナのポートをホストからアクセス可能にしません。そのためには、ポート範囲を公開するには-pフラグを使用するか、公開されているすべてのポートを公開するには-Pフラグを使用する必要があります。これらのフラグは、 docker run [OPTIONS] IMAGE [COMMAND][ARG...]ポートをホストに公開するために使用されます。 1つのポート番号を公開し、別の番号で外部に公開することができます。

docker run -p 2500:80 <image name>

このコマンドは、<image>という名前のコンテナを作成し、コンテナのポート80をホストマシンのポート2500にバインドします。

ホスト・システムでポート・リダイレクションをセットアップするには、 -Pフラグの使用を参照してください。 Dockerネットワーク機能は、ネットワーク内のポートを公開せずにネットワークを作成することをサポートしています(詳細については、この機能の概要を参照してください)。

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."

イメージには複数のラベルを付けることができます。複数のラベルを指定するには、可能であればラベルを単一のLABEL命令に結合することをお勧めします。各LABEL命令は新しいレイヤーを作成し、多くのラベルを使用すると非効率的なイメージになる可能性があります。この例では、単一のイメージレイヤーが作成されます。

LABEL multi.label1="value1" multi.label2="value2" other="value3"

上記は次のように書くこともできます:

LABEL multi.label1="value1" \
      multi.label2="value2" \
      other="value3"

ラベルは、 FROMイメージのLABELを含めて加法的です。 Dockerが既に存在するラベル/キーに遭遇した場合、新しい値は同一のキーを持つ以前のラベルを上書きします。

イメージのラベルを表示するには、docker inspectコマンドを使用します。

"Labels": {
    "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"
},

CMD命令

CMD命令には3つの形式があります。

CMD ["executable","param1","param2"] (exec form, this is the preferred form)
CMD ["param1","param2"] (as default parameters to ENTRYPOINT)
CMD command param1 param2 (shell form)

DockerfileにはCMD命令は1つしか存在できません。複数のCMDをリストすると、最後のCMDだけが有効になります。

CMDの主な目的は、実行中のコンテナのデフォルトを提供することです。これらのデフォルトには実行可能ファイルを含めることができますが、実行ファイルを省略することもできます。この場合、 ENTRYPOINT命令も指定する必要があります。

注: CMDを使用してENTRYPOINT命令のデフォルト引数を指定する場合は、 CMD命令とENTRYPOINT命令の両方をJSON配列形式で指定する必要があります。

注意:execフォームはJSON配列として解析されます。つまり、一重引用符( ')以外の単語を二重引用符( ")で囲む必要があります。

注:シェル形式とは異なり、exec形式ではコマンドシェルは呼び出されません。つまり、通常のシェル処理は行われません。たとえば、 CMD [ "echo", "$HOME" ]$HOME変数置換を行いません。シェル処理を行う場合は、シェルフォームを使用するか、シェルを直接実行します( CMD [ "sh", "-c", "echo $HOME" ]

CMD命令は、シェル形式またはEXEC形式で使用すると、イメージの実行時に実行されるコマンドを設定します。

CMDシェル形式を使用すると、コマンドは/bin/sh -c

FROM ubuntu
CMD echo "This is a test." | wc -

シェルなしでコマンドを実行する場合は、コマンドをJSON配列として表現し、実行可能ファイルのフルパスを指定する必要があります。この配列形式は、 CMDの好ましい形式です。追加のパラメータは、配列内の文字列として個別に表現する必要があります。

FROM ubuntu
CMD ["/usr/bin/wc","--help"]

コンテナに毎回同じ実行可能ファイルを実行させる場合は、 CMDと組み合わせてENTRYPOINTを使用することを検討する必要があります。 ENTRYPOINT参照してください。

ユーザーがドッカーの実行に引数を指定すると、 CMD指定されたデフォルトを上書きします。

注意: RUNCMD混同しないでください。 RUN実際には画像構築時にコマンドを実行し、結果をコミットします。 CMDはビルド時には何も実行しませんが、イメージに意図されたコマンドを指定します。

主催者の指示

MAINTAINER <name>

MAINTAINER命令では、生成された画像のAuthorフィールドを設定できます。

MAINTAINER DIRECTIVEを使用しないでください

Official Docker Documentationによると、 MAINTAINER命令は推奨されなくなりました。代わりに、 LABEL命令を使用して、生成されたイメージの作成者を定義する必要があります。 LABEL命令は柔軟性があり、メタデータの設定を可能にし、 docker inspectコマンドで簡単に表示できます。

LABEL maintainer="[email protected]"

FROM命令

FROM <image>

または

FROM <image>:<tag>

または

FROM <image>@<digest>

FROM命令は、その後の命令のためにベースイメージを設定します。そのため、有効なDockerファイルの最初の命令はFROMなければなりません。イメージは任意の有効なイメージにすることができます。パブリック・リポジトリからイメージを取り出すことによって開始するのは特に簡単です。

FROMはDockerfileの最初の非コメント命令でなければなりません。

複数の画像を作成するために、単一のDockerファイル内にFROMを複数回表示することができます。各新しいFROMコマンドの前に、コミットによって最後に出力されたイメージIDを書き留めるだけです。

タグまたはダイジェスト値はオプションです。どちらかを省略すると、ビルダーはデフォルトで最新のものとみなします。ビルダーは、タグ値と一致しない場合はエラーを戻します。

実行命令

RUNは2つの形式があります:

RUN <command> (shell form, the command is run in a shell, which by default is /bin/sh -c on Linux or cmd /S /C on Windows)
RUN ["executable", "param1", "param2"] (exec form)

RUN命令は、現在の画像の上に新しいレイヤーのコマンドを実行し、結果をコミットします。結果として得られたコミットされたイメージは、 Dockerfile次のステップで使用されます。

レイヤー化されたRUN命令と生成コミットは、Dockerのコアコンセプトに準拠しています。ここでは、コミットは安く、ソース管理と同様に画像の履歴の任意の点からコンテナを作成できます。

exec形式を使用すると、シェル文字列の混乱を避けることができ、指定されたシェル実行可能ファイルを含まないベースイメージを使用してRUNコマンドを実行することができます。

シェルフォームのデフォルトのシェルは、 SHELLコマンドを使用して変更できます。

シェル形式では、 \ (バックスラッシュ)を使用して、次の行に1つの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" ]

注意: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命令によって無効にすることができます。詳細は以下を参照してください。

ONBUILD命令

ONBUILD [INSTRUCTION]

ONBUILD命令は、イメージが別のビルドのベースとして使用されるときに、後で実行されるトリガ命令をイメージに追加する。トリガは、下流のDockerfileのFROM命令の直後に挿入されたかのように、下流のビルドのコンテキストで実行されます。

どのビルド命令もトリガとして登録できます。

これは、アプリケーション構築環境やユーザー固有の構成でカスタマイズ可能なデーモンなど、他のイメージを構築するためのベースとして使用されるイメージを構築する場合に便利です。

たとえば、イメージが再利用可能なPythonアプリケーションビルダーである場合、特定のディレクトリにアプリケーションソースコードを追加する必要があります。そのあとでビルドスクリプトを呼び出す必要があります。アプリケーションのソースコードにまだアクセスしていないため、 ADDRUN呼び出すことはできません。アプリケーションのビルドごとに異なります。アプリケーション開発者に、アプリケーションにコピー・ペーストするための定型的なDockerfileを提供するだけでも問題はありませんが、アプリケーション固有のコードと混同されるため、エラーが発生しやすく、更新が困難です。

解決方法は、 ONBUILDを使用して、次のビルド段階で、後で実行するように進行命令を登録することです。

それはどのように動作するのです:

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ことはできません。

警告: ONBUILD命令は、 FROMまたはMAINTAINER命令をトリガしません。

STOPSIGNAL命令

STOPSIGNAL signal

STOPSIGNAL命令は、コンテナに送られて終了するシステムコール信号を設定します。このシグナルは、カーネルのsyscallテーブル内の位置(例えば9)に一致する有効な符号なしの番号、またはSIGAMEのような形式のシグナル名(例えばSIGKILL)です。

保健指導

HEALTHCHECK命令には、次の2つの形式があります。

HEALTHCHECK [OPTIONS] CMD command (check container health by running a command inside the container)
HEALTHCHECK NONE (disable any healthcheck inherited from the base image)

HEALTHCHECK命令は、Dockerに、コンテナがまだ動作していることを確認するためのテスト方法を指示します。これにより、サーバプロセスがまだ実行中であっても、無限ループに陥り、新しい接続を処理できないWebサーバなどのケースを検出できます。

コンテナにヘルスチェックが指定されている場合、コンテナには通常の状態に加えて正常性ステータスがあります。このステータスは、最初は開始されています。ヘルスチェックが合格するたびに、健康状態になります(以前の状態に関係なく)。特定の回数の連続した失敗の後、それは不健全になります。

CMD前に表示されるオプションは次のとおりです。

--interval=DURATION (default: 30s)
--timeout=DURATION (default: 30s)
--retries=N (default: 3)

ヘルスチェックは、最初にコンテナが開始されてから数秒後に実行され、前のチェックが完了するたびに間隔秒後に実行されます。

チェックの1回の実行にタイムアウト秒を超えると、チェックは失敗したとみなされます。

コンテナが正常でないとみなされるために、ヘルスチェックの連続した失敗が再試行されます。

一つだけ存在できHEALTHCHECKの命令Dockerfile 。 2つ以上をリストすると、最後のHEALTHCHECKだけがHEALTHCHECKになります。

CMDキーワードの後のコマンドは、シェルコマンド( HEALTHCHECK CMD /bin/check-running )またはexecアレイ(他のDockerfileコマンドと同様に、詳細はENTRYPOINTを参照してください)。

コマンドの終了ステータスは、コンテナの正常性ステータスを示します。可能な値は次のとおりです。

  • 0: success - コンテナは健康で使用可能です
  • 1: unhealthy - コンテナが正しく動作していない
  • 2: starting - コンテナはまだ使用できる状態ではなく、正しく動作しています

コンテナがすでに「開始」状態から移動したときにプローブが2(「開始」)を返した場合、代わりに「不健全」として扱われます。

たとえば、Webサーバーが3秒以内にサイトのメインページを提供できるように5分ごとにチェックするには、次のようにします。

HEALTHCHECK --interval=5m --timeout=3s \
  CMD curl -f http://localhost/ || exit 1

失敗したプローブをデバッグするのに役立つように、コマンドがstdoutまたはstderrに書き込む出力テキスト(UTF-8エンコード)は、正常性状態に格納され、 docker inspectで照会できます。そのような出力は短く保たれるべきです(最初の4096バイトだけが現在格納されています)。

コンテナの正常性状態が変わると、新しい状態でhealth_statusイベントが生成されます。

Docker 1.12にHEALTHCHECK機能が追加されました。

シェル命令

SHELL ["executable", "parameters"]

SHELL命令では、シェル形式のコマンドに使用されるデフォルトのシェルをオーバーライドすることができます。 Linuxのデフォルトのシェルは["/bin/sh", "-c"] 、Windowsでは["cmd", "/S", "/C"]です。 SHELL命令は、DockerfileのJSON形式で記述する必要があります。

SHELL命令は、Windows上で特に有用です。ここでは、一般的に使用され、全く異なる2つのネイティブシェルがあります:cmdとpowershell、shを含む代替シェルがあります。

SHELL命令は複数回現れます。各SHELL命令は、以前のすべて上書きされますSHELL指示をし、すべての後続の命令に影響を与えます。例えば:

FROM 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

SHELL命令のシェル形式がDockerfileで使用されている場合( RUNCMDENTRYPOINT 、次の命令はSHELL命令の影響を受けます。

次の例は、Windows上で見つかった一般的なパターンであり、 SHELL命令を使用して簡素化することができます。

...
RUN powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"
...

ドッカーによって呼び出されるコマンドは次のようになります。

cmd /S /C powershell -command Execute-MyCmdlet -param1 "c:\foo.txt"

これは2つの理由で非効率的である。まず、不要なcmd.exeコマンドプロセッサ(別名シェル)が呼び出されます。第2に、シェル形式の各RUN命令は、余分なpowershellコマンドを前置するコマンドを必要とします。

これをより効率的にするために、2つのメカニズムの1つを使用することができます。 1つは、次のようなRUNコマンドのJSON形式を使用することです。

...
RUN ["powershell", "-command", "Execute-MyCmdlet", "-param1 \"c:\\foo.txt\""]
...

JSONフォームは明白であり、不要なcmd.exeを使用しませんが、二重引用符とエスケープを使用すると、より詳細な冗長性が必要になります。別の仕組みは、 SHELL命令とシェル形式を使用することです。特に、エスケープ・パーサー・ディレクティブと組み合わせると、Windowsユーザーにとってより自然な構文になります。

# escape=`

FROM windowsservercore
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 3.584 kB
Step 1 : FROM windowsservercore
 ---> 5bc36a335344
Step 2 : SHELL powershell -command
 ---> Running in 87d7a64c9751
 ---> 4327358436c1
Removing intermediate container 87d7a64c9751
Step 3 : RUN New-Item -ItemType Directory C:\Example
 ---> Running in 3e6ba16b8df9


Directory: C:\


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----         6/2/2016   2:59 PM                Example


 ---> 1f1dfdcec085
Removing intermediate container 3e6ba16b8df9
Step 4 : ADD Execute-MyCmdlet.ps1 c:\example\
 ---> 6770b4c17f29
Removing intermediate container b139e34291dc
Step 5 : RUN c:\example\Execute-MyCmdlet -sample 'hello world'
 ---> Running in abdcf50dfd1f
Hello from Execute-MyCmdlet.ps1 - passed hello world
 ---> ba0e25255fda
Removing intermediate container abdcf50dfd1f
Successfully built ba0e25255fda
PS E:\docker\build\shell>

SHELL命令は、シェルの動作方法を変更するためにも使用できます。たとえば、WindowsでSHELL cmd /S /C /V:ON|OFFを使用すると、遅延環境変数拡張セマンティクスを変更できます。

SHELL命令は、zsh、csh、tcshなどの代替シェルが必要な場合はLinuxでも使用できます。

SHELL機能がDocker 1.12に追加されました。

Debian / Ubuntuパッケージのインストール

1回の実行コマンドでインストールを実行し、アップデートをマージしてインストールします。後でさらにパッケージを追加すると、アップデートが再度実行され、必要なパッケージがすべてインストールされます。アップデートを個別に実行すると、キャッシュが更新され、パッケージのインストールが失敗する可能性があります。スクリプトによるインストールでは、フロントエンドを非対話型に設定し、インストールするには-yを渡す必要があります。インストールの最後にクリーニングとパージを行うと、レイヤーのサイズが最小限に抑えられます。

FROM debian

RUN apt-get update \
 && DEBIAN_FRONTEND=noninteractive apt-get install -y \
    git \
    openssh-client \
    sudo \
    vim \
    wget \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow