Dockerfileメモ
ベースイメージ
- debian
- Dockerfileのベストプラクティスで推奨されているイメージ
- busybox
- 組込用途で作られたもの。非常に小さい。
- alpine
- busybox同様、非常に小さいイメージ。パッケージマネージャ付き。
コンテキスト
Dockerはビルドを行うパスのファイルをすべてDockerデーモンに送ってから、Dockerfileを元にイメージのビルドを行う。この送られるファイル群のことをコンテキストという。
例えば、RailsプロジェクトでDockerfileを作成してビルドしたとすれば、log/*.log
を含むすべてのプロジェクトファイルがDockerデーモンに送られることとなる。log/*.log
はイメージのビルドに必要ないし巨大なファイルになりがちで、無視できない無駄な遅延になりうる。
.dockerignore
ファイルを使うと.gitignore
のようにコンテキストに含めないファイルを指定することができる。
# .dockerignore
log
Dockerfile概要
FROM ベースイメージ名 AS ビルドステージ名
# ...
FROM ベースイメージ名
ENV 設定する環境変数名 内容
ADD イメージにファイルを追加する(ADDとCOPYの違いは後述)
COPY イメージにファイルを追加する
COPY --from=nodejs /tmp/node /opt/node
WORKDIR RUNやCOPYコマンドを実行するパス
RUN シェルコマンド
ENTRYPOINT コンテナ起動時に実行するコマンド(実行時に変更不可能)
CMD コンテナ起動時に実行するコマンドあるいはENTRYPOINTの引数(実行時にdockerコマンドの引数で変更可能)
FROM
元となるベースイメージを指定する。ruby:2.7.2
など。マルチステージビルドという機能で、FROM ruby:2.7.2 AS before_build
のようにすると、次のFROM
が現れるまで、そのイメージでコマンドが実行される。後続のFROM
内でCOPY --from=before_build /before_build内部のディレクトリ/ファイル /コピー先のディレクトリ/ファイル
とすることで、ファイルをコピーすることができる。
FROM ruby:2.7.2 AS before_build
# /tmp/download_commandができる
WORKDIR /tmp
RUN curl -LO https://example.com/download_command
FROM ruby:2.7.2
# /tmp/download_commandをコピーする
COPY --from=before_build /tmp/download_command /app/bin/command
よくある使い方としては、コンパイル型言語でプログラムのビルド用のビルドステージを用意し、バイナリをコピーする使い方がある。マルチステージビルドを使うことで、コンパイラなど稼働時に不要なプログラムなどを稼働用イメージに入れずに済む。
ENV
環境変数を追加する。
ENV PATH /opt/foo/bin:$PATH
ADDとCOPY
- 指定できるファイル
- どちらもローカルファイルはDockerfileのあるディレクトリ内のファイルしか指定できない。
ADD
はURLを指定してリモートのファイルを指定することができる。ADD
は圧縮ファイルを展開する(らしいが、リモートのtar.xzファイルを指定したら展開されなかった)
ADD
を使わずとも、ローカルファイルはCOPY
でリモートファイルはRUN curl ...
で代用できるためADD
はあまり使われない。
COPY ["ファイル1", "ファイル2", ..., "コピー先ディレクトリ"]
という形での指定もできる。
WORKDIR
COPY
、RUN
、CMD
、ENTRYPOINT
などのコマンドを実行するディレクトリを指定する。シェルのcd
コマンドと思えば良い。docker run --rm -it イメージ名 bash
とした時のカレントディレクトリにもなる。
RUN
RUN
コマンドの指定の仕方は2種類ある。
# シェル形式
# sh -c "echo $PATH > file1"が実行され
# イメージ内に$PATH環境変数の値が出力されたfile1ファイルが作成される
RUN echo $PATH > file1
# exec形式
# シェルを介さずに直接echo $PATH > file2が実行され
# イメージビルド時に
# $PATH > file2
# と表示される(file2は作成されない)
RUN ["echo", "$PATH", ">", "file2"]
シェル形式はsh -c "echo $PATH > file1"
を実行する。exec形式はシェルを介さずに直接echo $PATH > file2
を実行する。
シェル形式はシェルを用いて実行されるので環境変数$PATH
が展開され、リダイレクトが解釈されるが、exec形式の場合はシェルを介さないため$PATH
も>
もただの文字列として処理される。
RUN
コマンドの場合、exec形式はあまり使われない。
ENTRYPOINT
書式はRUN
コマンドと同じ。exec形式が推奨されている。
コンテナ起動時に実行されるコマンドを指定する。docker run --rm -it イメージ名 bash
のようにdocker
コマンドから別のコマンドに差し替えることはできない。
FROM ruby
WORKDIR /
ENTRYPOINT ["ls"]
CMD ["-l"]
上記Dockerfileの場合、docker build -t イメージ名 .
、docker run --rm イメージ名
とした場合、/
ディレクトリ上でls -l
コマンドが実行され結果が表示される。
docker run --rm イメージ名 -tl
とした場合、/
ディレクトリ上でls -tl
コマンドが実行され結果が表示される。
この様に、docker run
コマンドなどの最後で指定するコマンドは、Dockerfile内のCMD
の指定を置き換えているだけである。
CMD
書式はRUN
コマンドと同じ。exec形式が推奨されている。
ENTRYPOINT
コマンドが指定されている場合は、ENTRYPOINT
コマンドで指定されているコマンドの引数となる。
ENTRYPOINT
コマンドが指定されていない場合は、CMD
コマンドの指定内容のコマンドがコンテナ起動時に実行される。