なぜDockerfileが必要なのか?
DockerHubにはubuntuやpythonなど様々なイメージが提供されているのに、なぜDockerfileへの理解が必要なのでしょうか?
基本的にはDockerHubで提供しているイメージはubuntuのみ、pythonのみなど最低限の機能しか入っていないものが多い。開発実務では多くの技術スタックを組み合わせていくことになるため、イメージをカスタムする必要がある。DockerfileはDockerイメージの基になるテキストファイルと考えれば良い。
Dockerfileに関するコマンド
Dockerfileからイメージを作成する
docker image build {ディレクトリパス}
ディレクトリパスは基本的にはDockerfileがあるディレクトリを指定する。
-tオプションでイメージの名前をつけられる。
例)docker image build -t test-image:v1 {ディレクトリパス}
-tをつけないとイメージ名が"none"になる。
Dockerfileの書き方
FROM {dockerイメージ}
FROMは一番ベースのイメージを記載する。
例)FROM ubuntu:20.04
RUN {コマンド名}
RUNはイメージからコンテナを起動する際に実行するコマンドを記載していく。
例)
RUN apt install
RUN apt install -y curl
COPY {コピー元のファイルパス} {コピー先のディレクトリパス}
COPYで好きなファイルをイメージに配置する。コピー先は存在しなければ新しく作成される。
ビルドコンテキストについて
docker image build {ディレクトリパス}
の{ディレクトリパス}は厳密にはビルドコンテキストパスと呼ばれるものになる。そしてこのコマンドをより詳細にいうと、Dockerfileとビルドコンテキストからイメージを作成するコマンドとなる。なのでビルドコンテキストとDockerfileは全くの別物となる。image buildするさいにDockerfileがビルドコンテキストのパスに存在するものとして、Dockerfileを探しにいく。逆に言うとビルドコンテキストのパスとDockerfileのパスが異なっていても指定することもできる(後述)。
ビルドコンテキストを理解するためにはまずはdockerのアーキテクチャを把握する必要がある。
以下の図は公式ドキュメントで紹介されているDocker Engineの全体像。

(出典:Docker 概要)
ターミナルでのdockerコマンドの入力は図のクライアント dockerCLIにあたる。入力したコマンドをREST APIを介してサーバ dockerデーモンに渡すことで、イメージを作ったり、コンテナを作ったりしている。なのでdockerCLIとdockerデーモンが別々の環境にあっても操作ができることになる。
dockerデーモンはクライアントとは別々の環境に存在することが思想にあるため、例えばローカルのファイルをdockerイメージ内に配置したい、などの場合にはdockerデーモンに対して、事前にローカルのファイルについての情報を教えてあげる必要がある。それが上で説明したビルドコンテキストの正体。ビルドコンテキストに指定した配下のファイルを操作することができるようになる。逆に言えばビルドコンテキストにないファイル等はdockerデーモンが認識できないため操作できない。
Dockerfileとビルドコンテキストを別々に指定する方法
Dockerfileがある場所とビルドコンテキストに指定したい場所が別々の階層の場合は以下のコマンドで指定できる。
docker image build -f {Dockerfileのディレクトリパス} {ビルドコンテキスト}
デフォルトコマンドを変更する
Dockerfile内にCMDを記述することでコンテナ実行時のデフォルトコマンドを設定できる。例えばDocker Hubからプルしたubuntuのデフォルトコマンドはbashだが、CMDを記述することによって任意のコマンドに変更できる。
FROM ubuntu
CMD ["実行コマンド","パラメータ1","パラメータ2",・・・]
パラメータはいくつでもOK。CMDを複数記述したさいは最後のCMDのみ有効になることに注意。
環境変数を設定する
ENV 環境変数名 = "値"
複数記述可。「””」,「=」は省略可。設定した変数を呼び出すには先頭に$をつけるのを忘れずに。
変数を設定する
イメージ作成時に利用する変数を渡す。
ARG 変数名 = デフォルト値
dockerfile例)
以下は変数sampleを設定し、コンテナを起動するさいにsample.txtに任意の文字列を書き込み、catでファイルの中身を表示する。
FROM ubuntu
ARG sample
RUN echo $sample > sample.txt
CMD ["cat", "sample.txt"]
イメージを作成する際は以下のように、--build-argオプションをつける。
docker image build --build-arg sample="hello wolrd" .
作成したイメージからコンテナを起動すると以下のような出力になる。
user % docker container run -it {イメージID}
hello wolrd
user %
ARGとENVの違い
ARG:イメージ作成時のみ有効な一時的な変数
ENV:イメージ作成時とコンテナ起動時、両方で有効な変数
作業ディレクトリを変更する
RUNやCMDなどの作業ディレクトリの指定は以下のコマンド
workdir {ディレクトリパス}
で現在の作業ディレクトリを変更できる。デフォルトでは/(ルート)になっている。