先に要点
- .dockerignore は、Docker build に渡したくないファイルを除外し、builder へ送る build context を軽くするための設定ファイルです。
- 書かないと
node_modulesや.gitまで context に入り、transferring contextが数百MB〜GB規模になってビルドが遅くなります。 - 最も怖いのは速度ではなく事故で、
.envが混入するとCOPY . .経由でイメージに焼き込まれ、シークレットが漏れます。 - PHP の
vendorと Node のnode_modulesは「両方除外」が基本ですが、その理由(OS依存とビルド手順)は言語で少し違います。
Dockerfile を書き始めたあと、地味だけどかなり大事なのが .dockerignore です。
ここを後回しにすると、ビルドが重い、キャッシュが効きにくい、不要ファイルが混ざる、場合によっては秘密情報まで送ってしまう、という形であとから効いてきます。
この記事では、2026年6月時点で Docker Docs の Build context と .dockerignore 関連ドキュメントを確認しながら、.dockerignore とは何か、なぜ必要か、書かないと何が困るのかを、実際のコマンド出力や事故の流れまで踏み込んで整理します。
Dockerfile の基本から先に押さえたいなら、Dockerfileとは?何を書くもの?最初に読むべき命令を初心者向けに整理 もつながりやすいです。
.dockerignoreとは何か
.dockerignore は、Docker build に含めたくないファイルやフォルダを除外するための設定ファイルです。プロジェクトのルート(build context の起点になるディレクトリ)に置きます。
Docker Docs でも、.dockerignore は「builder へ送る前に build context からファイルやディレクトリを除外し、特にリモートビルダー利用時にビルド速度を改善する」と説明されています。
ここで大事なのは、.dockerignore が Dockerfile の中身を制御するというより、Docker build に何を渡すかを減らす仕組みだという点です。Dockerfile の COPY や RUN が動く前の、もっと手前のステージで効きます。
初心者向けにざっくり言うと、Docker に見せる作業フォルダを軽く・安全にするための除外設定です。
build context って何なのか
Docker build を実行すると、Docker はまず指定したディレクトリ(多くは docker build . の .)の中身を build context としてまとめ、builder へ転送します。Docker Docs でも、build context は builder に送られる files and directories だと整理されています。
転送のとき、ターミナルにはこういう行が出ます。
#16 [internal] load build context
#16 transferring context: 13.16MB 2.2s done
この transferring context の数字こそが、build context の実サイズです。ここが何百MBやGBになっていたら、.dockerignore が効いていないサインだと思ってよいです。
Dockerfile が見るもの
COPY や ADD は、すでに builder へ送られた build context の中からファイルを選んでイメージに入れます。送られていないものはコピーできません。
.dockerignore が見るもの
その「builder へ送る対象」そのものを減らします。COPY で拾わなくても、context に入っている時点で転送コストとキャッシュ判定に影響します。
つまり、Dockerfile の COPY . . だけを見ていても不十分で、そもそも builder 側へ何が送られているかが本質です。.dockerignore は、この最初に送る対象を減らすところで効きます。
書かないと何が困るのか
1. ビルドが遅くなりやすい(数値で見る)
不要なファイルまで build context に含まれると、そのぶん転送量が増えます。特に効くのは次のような肥大しやすいディレクトリです。
| ディレクトリ | 典型サイズの目安 | build に必要か |
|---|---|---|
node_modules(中規模アプリ) |
数百MB〜1GB超 | 不要(コンテナ内で入れ直す) |
.git(履歴の長いリポジトリ) |
数十MB〜数百MB | ほぼ不要 |
vendor(PHP / Composer) |
数十MB〜数百MB | 方針次第(後述) |
dist / build / coverage |
数MB〜数十MB | 通常は不要 |
たとえば node_modules が 500MB あるプロジェクトで、それを .dockerignore に追加するだけで transferring context が 520MB から 20MB 程度に落ち、context の load フェーズが体感で数十秒短くなる、というのはよくある話です。リモートビルダーや CI のように context をネットワーク越しに送る環境では、この差がさらに大きく出ます。
数字は環境依存ですが、考え方は単純です。送らないファイルは転送時間ゼロ・ハッシュ計算ゼロです。
2. キャッシュ効率が悪くなる
build context に余計なファイルが入ると、少しの変更でもキャッシュが崩れやすくなります。たとえば COPY . . を使っている場合、.git を context に含めていると、コミットや git pull のたびに .git/ の中身が変わり、COPY レイヤーのキャッシュが毎回無効化されます。すると本来は再利用できた npm install や composer install のレイヤーまで毎回やり直しになりがちです。
これは Dockerfile 側の COPY 順序(依存定義だけ先にコピーする手法)とも関係しますが、前提として .dockerignore で揺れやすいものを context から外しておく方が安定します。
3. .env が混入してシークレットが漏れる(事故の流れ)
ここが速度より怖いポイントです。.env・鍵ファイル・個人用メモ・ローカル設定が context に入っていると、Dockerfile の書き方次第でイメージへ焼き込まれます。実際の事故は次のように進みます。
注意したいのは、後から .dockerignore に .env を追加してリビルドしても、すでに docker push 済みのイメージや古いレイヤーには秘密情報が残るという点です。一度焼き込んだ資格情報は「除外して直す」だけでは消えません。漏れた前提でキーを作り直すのが正解です。
「COPY していないから大丈夫」と思いがちですが、そもそも builder へ送らないのが最も安全です。
4. .git が入って無駄に大きくなる
Git 管理情報が build context に入ると、サイズが増えるだけでなく、前述のとおり履歴変更でキャッシュが崩れる原因にもなります。.git はかなり代表的な除外候補です。
PHPのvendorとNodeのnode_modules、なぜ方針が分かれるのか
「依存ディレクトリは除外する」という結論は同じでも、理由は PHP と Node.js で少し違います。ここを理解すると、自分のプロジェクトで判断できるようになります。
| 観点 | Node.js(node_modules) |
PHP(vendor) |
|---|---|---|
| 除外する一番の理由 | OS / アーキ依存のネイティブモジュール(node-gyp 系)があり、ホストでビルドしたものはコンテナ内 OS で動かないことがある |
多くは純粋な PHP コードだが、巨大で context を膨らませ、ローカルと本番で構成がズレやすい |
| イメージ内でどう用意するか | COPY package*.json ./ の後に RUN npm ci で入れ直す |
COPY composer.json composer.lock ./ の後に RUN composer install --no-dev で入れ直す |
| 本番での落とし穴 | npm ci は lock に厳密。dev 依存は --omit=dev で外す |
--no-dev を忘れると PHPUnit など開発用パッケージまで本番イメージに入る |
Node.js は「ホストでビルドしたバイナリがコンテナで壊れる」リスクがあるため、node_modules をローカルから持ち込むのは原則 NG です。一方 PHP の vendor は中身がコードであるぶん持ち込んでも動くことはありますが、ローカルが macOS・本番が Linux、PHP バージョンも違う、といった環境差でズレるため、コンテナ内で composer install し直すのが安全という整理になります。
どちらも結論は「ローカルの依存ディレクトリは .dockerignore で除外し、依存はコンテナ内で再構築する」です。理由が分かっていれば、Python の .venv や Go のキャッシュなど他言語でも同じ判断ができます。
.gitignore と何が違うのか
ここは混ざりやすいです。
.gitignore
Git に追跡させたくないものを指定する。バージョン管理の対象を絞るためのファイル。
Docker build に渡したくないものを指定する。builder へ送る context を絞るためのファイル。
似ていますが役割は別です。Git 管理したいけれど Docker build には渡したくないものもありますし(例: README、設計用の画像、テストコード)、その逆もあります。
要するに、.gitignore があるから .dockerignore は不要、とはなりません。glob のパターン構文はほぼ共通(# でコメント、* と ** のワイルドカード、! で否定)なので書き味は近いですが、中身は別ファイルとして管理するのが正解です。
最初に入れやすい例
プロジェクトによって違いますが、最初はこういう内容から入りやすいです。
# バージョン管理・履歴
.git
.gitignore
# 依存(コンテナ内で入れ直す)
node_modules
vendor
.venv
# ビルド成果物・テスト出力
dist
build
coverage
# 秘密情報・ローカル専用(最重要)
.env
.env.*
!.env.example
*.pem
*.key
# OS / エディタの生成物
.DS_Store
.idea
.vscode
*.log
最後の !.env.example は否定パターンで、.env.* でまとめて除外しつつテンプレートだけ残す書き方です(.dockerignore は最後にマッチしたルールが勝つため、順序が重要)。秘密情報の .env 本体は除外し、共有用の .env.example だけ残す、という運用がよく使われます。
大事なのは、Docker build に本当に必要なものだけ送るという考え方です。
ビルドが重いとき、何を除外すべきか調べる
「とりあえず全部書く」のではなく、実際に何が重いかを測ってから除外すると効果が分かりやすいです。
$ du -sh ./* | sort -rh | head
612M ./node_modules
180M ./.git
24M ./coverage
8.2M ./src
1.1M ./package-lock.json
この例なら、node_modules・.git・coverage を外すだけで context が 800MB 近くから 10MB 前後まで落ちます。du -sh は Windows の標準環境には無いので、WSL や Git Bash、あるいはコンテナ内で実行すると使いやすいです。
実務でどう考えるといいか
ローカルだけで使うものをまず疑う
IDE 設定(.idea / .vscode)、テスト成果物、キャッシュ、ログ、手元の秘密ファイルは、build context に不要なことが多いです。
大きいフォルダをそのまま入れない
node_modules や .git は典型です。「なんでこんなに build が重いんだろう」となる前に、まず除外候補として見た方がよいです。
セキュリティの観点でも見る
.dockerignore は速度最適化だけの話ではありません。意図しないファイル混入、特に .env や鍵の漏洩を防ぐ意味でもかなり重要です。デプロイ先がパブリックなレジストリなら、なおさら手前で止める価値があります。
Node.js 案件では、ローカルの node_modules と .env を context に入れないだけで、ビルド速度と事故リスクの両方を下げられます。依存はコンテナ内で npm ci し直し、秘密情報は build へ渡さず実行時に環境変数で渡す、という整理が基本です。PHP 案件なら vendor を除外し、composer install --no-dev で本番用だけ入れ直します。
初心者がハマりやすい点
COPY していないから安全だと思ってしまう
そうとも限りません。context に送った時点で転送・ハッシュ計算のコストが発生し、COPY . . のような書き方なら結局イメージに入ります。.dockerignore は別で持つ方が安全です。
とりあえず .gitignore をコピペして終わる
方向性は近いですが、完全に同じでよいとは限りません。Docker build に必要なファイル(設定テンプレートなど)まで除外しないよう注意します。逆に、Git では追跡している README やテストコードを Docker には渡さない、という調整も有効です。
一度書いたら見直さない
プロジェクトが育つと、増える不要物も変わります。ビルドが重くなってきたら、du -sh ./* で再計測して .dockerignore を見直すだけで改善することもあります。
.dockerignoreに関するよくある質問
Q. .gitignore をそのまま .dockerignore にコピーして良いですか?
A. 多くは共通しますが完全に同じではありません。Docker build に必要なファイル(.env.example など)まで除外しないよう注意します。.git node_modules tmp/ などは両方で除外して問題ありません。glob 構文はほぼ同じなので、コピーをたたき台にして調整するのは現実的です。
Q. .dockerignore を書かないとどうなりますか?
A. docker build 時にプロジェクト全体が build context として送信されます。大規模プロジェクトでは数百MB〜GB 単位になり、transferring context が長くなる・不要ファイルがイメージに含まれる・.env 経由でシークレットが漏れる、といった問題が出ます。
Q. node_modules は .dockerignore に入れるべきですか?
A. ほぼ全てのケースで入れるべきです。ホスト OS の node_modules はコンテナ内 OS と互換性がないネイティブモジュールを含むことがあり、コンテナ内で npm ci し直すのが安全です。サイズも大きく、除外で context が大幅に軽くなります。
Q. .env ファイルは除外すべきですか?
A. 本番用 .env は必ず除外します。.env.* で除外しつつ !.env.example でテンプレートだけ残す運用が一般的です。間違って .env がイメージに焼き込まれるとシークレット漏洩になり、その場合は除外して直すだけでなくキーのローテーションが必要です。
Q. .dockerignore のパターンはどう書きますか?
A. 基本は .gitignore と同じ glob です。node_modules、*.log、tmp/**、否定の !keep.txt のように書けます。最後にマッチしたルールが優先されるので、除外と否定の順序に注意します。
Q. 開発と本番で .dockerignore を分けたいです。
A. BuildKit では Dockerfile ごとの専用 ignore ファイルが使えます。docker build -f Dockerfile.prod . のように build すると、まず Dockerfile.prod.dockerignore が探され、無ければルートの .dockerignore が使われます。命名は「Dockerfile名 + .dockerignore」で、同じディレクトリに置きます(--dockerignore= のようなフラグは存在しません)。
Q. ビルドが遅いとき、.dockerignore で改善できますか?
A. 改善できます。du -sh ./* でサイズの大きいディレクトリを見つけ、build に不要なものを .dockerignore で除外します。transferring context の数字が数百MBから数十MBに落ちれば、context 送信時間が大きく短縮されます。
Q. すでに .env を含むイメージを push してしまいました。.dockerignore に追加すれば直りますか?
A. 今後のビルドは直りますが、すでに push 済みのイメージや古いレイヤーには秘密情報が残ります。漏れた前提で、該当する API キーや DB パスワードを必ず再発行(ローテーション)し、古いイメージはレジストリから削除してください。
まとめ
.dockerignore は、Docker build に渡したくないファイルを除外して build context を軽く・安全にするための設定ファイルです。書かないと、ビルドが重くなるだけでなく、キャッシュ効率の悪化や、.env などの混入によるシークレット漏洩につながります。
最初は、大きいフォルダ・ローカル専用ファイル・秘密情報を context から外す、という意識だけでも十分です。重くなってきたら du -sh ./* で測り、transferring context の数字を見ながら削っていきましょう。
続けて読むなら、Dockerfileとは?何を書くもの?最初に読むべき命令を初心者向けに整理 や Docker Hubとは?イメージを pull する仕組みと注意点を解説 もつながりやすいです。
参考リンク
- Docker Docs: Build context
- Docker Docs: Dockerfile reference: .dockerignore file
- Docker Docs: Build best practices