Docker ビルドコンテキストの仕組みとファイル転送の最適化

docker build コマンドを実行する際、末尾に指定されるパス(例えば .)は、Dockerfile の所在を示すものではなく、ビルドコンテキストのディレクトリを定義しています。多くの初学者がこの引数を Dockerfile の場所と誤解しがちですが、実際にはビルドプロセスに必要なファイル群を含む範囲を指定する役割を果たします。

Docker のアーキテクチャを理解するには、クライアントとサーバーの役割を区別する必要があります。Docker エンジン(デーモンプロセス)がサーバー側で動作し、docker コマンドなどのクライアントツールは Docker Remote API を経由してエンジンと通信します。表面上はローカルで操作しているように見えますが、実際のビルド処理はすべてサーバー側のエンジンで実行されます。このクライアント・サーバーモデルにより、リモートホスト上の Docker エンジンに対しても容易に操作を行えるようになります。

イメージ構築時には、RUN 指令だけでなく、COPYADD 指令を用いてローカルファイルをイメージ内に配置するケースが頻繁にあります。ビルド処理がサーバー側で行われる以上、クライアント側のファイルをサーバーに渡す仕組みが必要です。ここでビルドコンテキストが機能します。ユーザーがコンテキストパスを指定すると、docker build はそのディレクトリ配下のすべてのファイルをアーカイブ化し、Docker エンジンへ転送します。エンジン側ではこのアーカイブを展開し、ビルドに必要なファイルセットとして利用します。

Dockerfile 内に以下のような記述がある場合を考えます。

COPY ./config/settings.yaml /etc/app/
docker build を実行したカレントディレクトリや Dockerfile のある場所にあるファイルではなく、指定されたコンテキストディレクトリ内の config/settings.yaml を参照します。したがって、COPY 指令で指定するソースパスは、コンテキスト内からの相対パスである必要があります。COPY ../secret.txt /appCOPY /var/log/syslog /app のような絶対パスや親ディレクトリへの参照は、コンテキストの範囲を超えるため許可されません。必要なファイルは事前にコンテキストディレクトリ内へ配置する必要があります。

前述の docker build -t web-app:1.0 ./src というコマンドにおいて、./src がコンテキスト目录となります。ビルド実行時の出力を確認すると、コンテキストの転送プロセスが確認できます。

$ docker build -t web-app:1.0 ./src
Sending build context to Docker daemon  5.632kB
...

コンテキストの仕組みを正しく理解していないと、パフォーマンス上の問題やエラーの原因となります。例えば、COPY で外部ファイルが参照できないことから、誤ってファイルシステムのルートディレクトリをコンテキストとして指定してしまうケースがあります。この場合、docker build はハードディスク全体のデータをパッケージ化しようとし、転送に膨大な時間を要したり、メモリ不足で失敗したりします。

推奨される運用方法としては、Dockerfile を専用の空ディレクトリかプロジェクトのルートディレクトリに配置することです。必要なファイルのみ在该目录下に集め、ビルド時に不要なファイル(ログファイルや一時ファイルなど)は、.gitignore と同様の構文を持つ .dockerignore ファイルを定義して除外します。これにより、コンテキストのサイズを最適化し、ビルド速度を向上させることができます。

最後に、Dockerfile の場所についての誤解を解きます。多くのユーザーが . を Dockerfile の場所と考えるのは、デフォルト動作によるものです。特に指定がない場合、Docker はコンテキストディレクトリ内にある Dockerfile という名前のファイルを自動的に使用します。しかし、これは単なるデフォルト設定に過ぎません。実際にはファイル名は任意でよく、場所もコンテキスト外に置けます。-f ../Dockerfile.prod のようにオプションを付与することで、特定のファイルを指定してビルドすることが可能です。尽管如此、慣習として Dockerfile という文件名を使用し、コンテキストディレクトリ内に配置するのが一般的です。

タグ: Docker Dockerfile build-context containerization DevOps

5月25日 11:36 投稿