Edited at

よく使いそうなDockerfileの記法一覧

最近は開発環境だけでなくCircle CIなどもコンテナ化されたりと、Dockerがすっかりスタンダード化してきましたね。

今回はDockerを運用する際に必須なDockerfileのお作法についてまとめました。

公式サイトが提供しているガイドを中心に展開していきます。


基本的なお作法


  • ファイル名はDockerfileにする(拡張子なし)

  • 習慣的として、Dockerが提供しているコマンドは大文字で記載する(FROMとか)

  • コメントは#で書ける

  • エスケープは\で書ける


FROM

コンテナを構築するためのイメージを指定します。

docker hubに挙げられているイメージから取得できるのですが、特別な理由がない限りは公式のイメージを取得するのが無難です。

オレオレのイメージを取ると、のちのメンテなどが大変。


書き方

FROM <image> [AS <name>]

# or
FROM <image>[:<tag>] [AS <name>]
# or
FROM <image>[@<digest>] [AS <name>]


RUN

指定したコマンドを実行します。

一つのDockerfile内で何度でも使用できます。


書き方

RUN <command>

# or
RUN ["executable", "param1", "param2"] # ''ではなく""で囲む

RUNした結果はデフォルトでキャッシュされるため、キャッシュしたくない場合にはビルド時に下記のようにすればokです。

$ docker build --no-cache


CMD

指定したコマンドをコンテナ起動時に実行します。

ENTRYPOINTを明示することでCMDは省略可能です。

docker run コマンドに引数をつけることで上書き可能です。

一つのDockerfileに一つだけ記述できます。

一つのDockerfileに2つ以上記載した場合には、最後のCMDだけが適応されます。


書き方

# docker公式的にはこちらが推奨とのこと

CMD ["executable","param1","param2"]
# or
CMD command param1 param2


EXPOSE

公開ポートを指定します。

指定しない場合、外部との接続はできません。


書き方

EXPOSE <port> [<port>/<protocol>...]



ENV

Dockerfile内で使用する環境変数を設定します。


書き方

ENV <key> <value>

# or
ENV <key>=<value> ...


ADD

<src>で指定したファイル、ディレクトリ、リモートファイルをコピーし、コンテナ内の<dest>パスに追加します。


書き方

ADD [--chown=<user>:<group>] <src>... <dest>

# or
ADD [--chown=<user>:<group>] ["<src>",... "<dest>"]


書き方

# ワイルドカードも使える

ADD hom* /mydir/ # "hom"で始まる全てのファイルをコンテナ内の"/mydir/"配下に追加する


COPY

<src>で指定したファイル、ディレクトリーをコピーし、コンテナ内の<dest>パスに追加します。


書き方

# docker公式的にはこちらが推奨とのこと

COPY [--chown=<user>:<group>] <src>... <dest>
# or
COPY [--chown=<user>:<group>] ["<src>",... "<dest>"]


ENTRYPOINT

指定したコマンドをコンテナ起動時に実行します。

CMDと同様、一つのDockerfileに一度だけ記載できます。

CMDを明示することでENTRYPOINTは省略可能です。

docker run --entrypoint="" で上書き可能です。


書き方

ENTRYPOINT ["executable", "param1", "param2"] 

# or
ENTRYPOINT command param1 param2


VOLUME

Dockerが管理するデータ領域上にマウントする機能です。

Dockerが管理している外付けHDDみたいな感じで、永続化させたいデータやコンテナ間で共通して使用したいデータをVOLUMEにマウントします。

コンテナとボリュームは別モノなので、コンテナを削除してもボリュームは存続します。


書き方

VOLUME ["/data"]



USER

RUN/CMD/ENTRYPOINTなどを実行する際のユーザー名やUIDを指定します。


書き方

USER <user>[:<group>]

# or
USER <UID>[:<GID>]


WORKDIR

RUN/CMD/ENTRYPOINTなどを実行する際のworking directoryを指定します。


書き方

WORKDIR /path/to/workdir


環境変数ENVと一緒に使われることが多いです。


書き方F##

ENV DIRPATH /path

WORKDIR $DIRPATH
...


注意点


ADDとCOPY

Best practices for writing Dockerfiles - ADD or COPYによると、


Although ADD and COPY are functionally similar, generally speaking, COPY is preferred. That’s because it’s more transparent than ADD. COPY only supports the basic copying of local files into the container, while ADD has some features (like local-only tar extraction and remote URL support) that are not immediately obvious. Consequently, the best use for ADD is local tar file auto-extraction into the image, as in ADD rootfs.tar.xz /.

If you have multiple Dockerfile steps that use different files from your context, COPY them individually, rather than all at once. This ensures that each step’s build cache is only invalidated (forcing the step to be re-run) if the specifically required files change.




  • ADDCOPYはほぼ同じ機能を提供している。


  • COPYはベーシックな機能だけ入っているので基本的にはCOPYがおすすめ。


  • ADDの使いどころとしては、圧縮ファイルを扱いたいときはを使う

  • Dockerfileで複数ファイルを扱うステップがいくつかある場合には一気にコピーせず、それぞれのステップごとで処理することでキャッシュによる思わぬトラブルを避けられる。

とのことです。


CMDとENTRYPOINT

一つのDockerfileに最低でも必ずどちから一方を記述する必要があります。

それぞれを併用した際の挙動としては下記です。

#
ENTRYPOINTなし
ENTRYPOINT exec_entry p1_entry
ENTRYPOINT [“exec_entry”, “p1_entry”]

CMDなし
エラー
/bin/sh -c exec_entry p1_entry
exec_entry p1_entry

CMD [“exec_cmd”, “p1_cmd”]
exec_cmd p1_cmd
/bin/sh -c exec_entry p1_entry
exec_entry p1_entry exec_cmd p1_cmd

CMD [“p1_cmd”, “p2_cmd”]
p1_cmd p2_cmd
/bin/sh -c exec_entry p1_entry
exec_entry p1_entry p1_cmd p2_cmd

CMD exec_cmd p1_cmd
/bin/sh -c exec_cmd p1_cmd
/bin/sh -c exec_entry p1_entry
exec_entry p1_entry /bin/sh -c exec_cmd p1_cmd

ENTRYPOINT CMD の順で実行されるようです。


参考