Dockerとコンテナ技術 その11:ビルドコンテキストと.dockerignore

前回までの記事でカスタムイメージの作成に必要なDockerfileについてまとめてきました。

キョウタコの技術日記

Dockerコンテナはレジストリから用途に合ったイメージを取得して作成する方法の他に、自分でカスタムしたイメージから作成…

キョウタコの技術日記

今回は前回の記事に続いて、Dockerfileについてまとめていきたいと思います。Dockerfileはカスタムイメージ…

今回はDockerのイメージのビルドにおいて覚えておくべき概念であるビルドコンテキストと、.dockerignoreという設定ファイルについてまとめていきます。

ビルドコンテキスト

ビルドコンテキストとは

ビルドコンテキストとは、Dockerがイメージをビルドする際にクライアントから渡されるファイル群のことです。
イメージをビルドする際、COPYコマンドでクライアント上のファイルをコンテナに配置していました。
実はこれは、クライアント上のファイルをそのままコピーしているのではなく、イメージのビルド時に渡されたビルドコンテキストのファイルを扱っているのです。

イメージのビルドとビルドコンテキスト

もう少し詳しく説明していきます。
コンテナイメージのビルドをする際、docker image build [ディレクトリパス]というコマンドを使用していたと思います。
こちらで指定している[ディレクトリパス]を今まではDockerfileが格納されているパスとしていましたが、正しくはビルドコンテキストで使用するディレクトリパスを指定しているのです。
そして、Dockerfileのパスを指定しない場合は、このビルドコンテキストの直下に配置する必要があるため、Dockerfileが格納されているパスという説明をしていたのです。
docker image buildコマンドを実行すると、ビルドコンテキストで指定されたパスの配下にあるフォルダとファイルを全て圧縮してDockerに渡されます。
こうして渡されたビルドコンテキストを元に、Dockerfileのコマンドを実行していきイメージをビルドしていきます。

実践でビルドコンテキストを理解する

では、実際の例を動かしてみてビルドコンテキストの理解を深めていきましょう。
任意の場所に以下のようなフォルダ構成を作成してください。

.
├── docker
│   └── Dockerfile
└── hello.txt

次に、Dockerfileを以下のように編集してください。

FROM ubuntu:20.04

COPY ../hello.txt /app/

これで準備完了です。
では、この状態でDockerfileがあるdockerディレクトリ内でdocker image buildコマンドを実行してみましょう。

# ./docker/フォルダ内で実行する
docker image build .

すると、以下のようになって失敗すると思います。

COPYコマンドが"/hello.txt": not foundという理由で実行が失敗すると思います。
これは、docker image build .で指定したビルドコンテキストとなるディレクトリ内にはhello.txtが存在せず、イメージをビルドする際にビルドコンテキストに存在しないファイルをコピーしようとしてしまうため、このようなエラーが発生します。
では、同じフォルダ構成のままイメージをビルドする方法をみていきましょう。
同じフォルダ構成でイメージをビルドするには、ビルドコンテキストにhello.txtを含んだディレクトリを指定した上で、Dockerfileを明示的に指定する必要があります。
前回はdockerフォルダ内からコマンド実行しましたが、今回はhello.txtがあるフォルダ内から以下のようにコマンドを実行しましょう。

# hello.txtがあるフォルダから実行する
docker image build -f ./docker/Dockerfile .

-fオプションはDockerfileのパスを明示的に指定するときに使います。
Dockerfileのパスを指定した上で、ビルドコンテキストにhello.txtを含むディレクトリを指定しています。
では、実行してみましょう。

今回はビルドコンテキストでhello.txtを渡しているため、COPYコマンドが失敗することなくビルドに成功しました。
実際に動かしてみることで理解が深まったのではないでしょうか。

.dockerignore

.dockerignoreファイルの役割

ビルドコンテキストについて理解したところで、次はビルドコンテキストに深く関わる.dockerignoreファイルについて理解していきましょう。
.dockerignoreは設定ファイルの一つで、ビルドコンテキストから除外するファイルやフォルダを指定することができます。
容量が大きいファイルや不要なファイルを指定して、効率的にビルドを行うために利用されます。

.dockerignoreの実践

では、実際に.dockerignoreを作成してイメージビルドをしてみましょう。
以下のような構成のフォルダを作成してください。

.
├── .dockerignore
├── Dockerfile
└── files
    ├── danke.txt
    └── hello.txt

次に、Dockerfileを以下のように編集してください。

FROM ubuntu:20.04

COPY ./files/ /files/

最後に、.dockerignoreを以下のように編集してください。

./files/danke.txt

これで準備は完了です。
実際にビルドして、danke.txtが除外されているか確認してみましょう。
Dockerfileがあるディレクトリで以下のコマンドを実行してください。

docker image build -t ignore-test:v1 .

イメージのビルドが完了したらコンテナを起動して、COPYされたfilesフォルダからdanke.txtが除外されているのか確認してみましょう。
以下のコマンドでコンテナを起動してください。

docker container run -it --rm ignore-test:v1

コマンド実行後、コンテナ内に入ると思うのでlsコマンドでfilesフォルダの中身を確認してみましょう。

ls ./files/

以下のように、danke.txtはCOPYされていないことが確認できると思います。

このように、.dockerignoreファイルに設定することでビルドコンテキストから任意のファイルを除外することができます。

まとめ

今回はイメージのビルドにまつわる重要な概念であるビルドコンテキストと、設定ファイルの一つである.dockerignoreについてまとめました。
ビルドコンテキストはイメージをビルドする際にDockerに渡されるファイル群であり、このファイル群を元にCOPYコマンドをはじめとしたイメージのビルドに関する操作が実行されます。
また、.dockerignoreはビルドコンテキストから除外するファイルを指定することができ、容量の大きいファイルなどを指定することでビルドの負荷を下げることなどに利用されます。
どちらも重要な概念なので、正しく理解していきましょう。
ここまで読んでいただきありがとうございました。
それでは、また。