---
title: あなたの.envはDockerイメージに焼き込まれ、誰でも抜き出せる ― Dockerセキュリティ12枚
tags:  #docker #セキュリティ #devsecops #buildkit #コンテナ #環境変数  
author: [井本 賢](https://image.docswell.com/user/kenimo49)
site: [Docswell](https://www.docswell.com/)
thumbnail: https://bcdn.docswell.com/page/2JVVZLZ3JQ.jpg?width=480
description: .env を .gitignore に書けば秘密は守れる — その常識は Docker では通用しません。COPY .env した瞬間に秘密はレイヤーに焼き込まれ、RUN rm しても消えず、docker save で誰でも抜き出せます。  本スライドは Qiita で公開した記事「あなたの.envはDockerイメージに焼き込まれ、誰でも抜き出せる」の要点を12枚で俯瞰する teaser 版です。  ▼扱う論点 - Dockerイメージの読み取り専用レイヤー構造 - なぜ RUN rm .env でも秘密が残るのか - ARG / ENV が docker history で丸見えになる理由 - docker save でイメージから .env を抜き出す実演 - BuildKit secret mount で正しく守る書き方 - .dockerignore + マルチステージ + 実行時注入 + Trivy スキャンの4本柱  ▼元記事(全文無料 / Qiita) https://qiita.com/kenimo49/items/fd13ea9436bbb3985dfc  著者: ken imoto / kenimoto.dev
published: July 03, 26
canonical: https://image.docswell.com/s/kenimo49/ZJWWDE-qiita-env-baked-in-docker
---
# Page. 1

![Page Image](https://bcdn.docswell.com/page/2JVVZLZ3JQ.jpg)

SECURITY DOCKER / SECRETS / LAYERS あなたの .env は Dockerイメージに 焼き込まれている。 .gitignore では守れない。docker save で誰でも見える。 ken imoto エンジニア / Propel-lab / kenimoto.dev .envはDockerイメージに焼き込まれる kenimoto.dev 01 / 12

# Page. 2

![Page Image](https://bcdn.docswell.com/page/5EGL4X4YJL.jpg)

秘密の漏れ方は経路ごとに対策が違う。 Gitに上げなくても、コンテナビルドがイメージのレイヤーに固定してしまう。 経路 どこに残るか 本デッキ git 履歴の残存 VCSのコミットオブジェクト 別軸 依存パッケージ攻撃 第三者パッケージ 別軸 ローカルの窃取 開発機の.env 別軸 イメージへの焼き込み ビルドで生成したレイヤー 本デッキ .envはDockerイメージに焼き込まれる kenimoto.dev 02 / 12

# Page. 3

![Page Image](https://bcdn.docswell.com/page/4JQYG8G67P.jpg)

Dockerイメージはレイヤーの積み重ね。 RUN・COPY・ADD ごとに変更分のレイヤーが1枚できて、あとから消せない。 CMD [&quot;python&quot;, &quot;main.py&quot;] RUN rm .env ←消したつもり COPY .. COPY .env ←秘密がここに焼かれる WORKDIR /app FROM python:3.12-slim 地層と同じ。 下に埋めたものは下に残る。 各レイヤーはtarballとして保存され、内容ハッシュで管理され る。 上に土を盛っても、下の地層はそのまま。 .envはDockerイメージに焼き込まれる kenimoto.dev 03 / 12

# Page. 4

![Page Image](https://bcdn.docswell.com/page/K74W525ME1.jpg)

RUN rm .env でも秘密は消えない。 削除も「新しいレイヤーを1枚積むだけ」。下の.env レイヤーはそのまま残る。 Layer N COPY .env で秘密を焼き込み = 下に埋まる地層 → Layer N+1 RUN rm .env = 上に「削除しました」の紙を貼る 後続 RUN 最終ファイル一覧から見えないだけ。レイヤーを展開すれば中身は出る。 .envはDockerイメージに焼き込まれる kenimoto.dev 04 / 12

# Page. 5

![Page Image](https://bcdn.docswell.com/page/LJ1YWMWYEG.jpg)

ARG と ENV は docker history で丸見え。 ビルド時に渡した値はメタデータに記録される。誰でも読める。 $ docker history --no-trunc myapp:latest CREATED BY SIZE ENV API_KEY= sk-live-abcd1234efgh5678 0B COPY .env # buildkit 112B RUN /bin/sh -c rm .env # buildkit 0B ENV の値が平文で見える COPY と RUN rm は別レイヤーで別々に記録 .envはDockerイメージに焼き込まれる kenimoto.dev 05 / 12

# Page. 6

![Page Image](https://bcdn.docswell.com/page/GJWG636172.jpg)

誰でも docker save で抜ける。実演。 tarに展開すれば、rmで消したはずの.envはレイヤー内にそのまま残っている。 # イメージをtarに書き出す $ docker save myapp:latest \ -o myapp.tar $ mkdir extract &amp;&amp; \ tar -xf myapp.tar -C extract # レイヤーtarを片端から展開して .env を探す $ find extract -name &quot;*.tar&quot; \ -exec tar -tf {} \; | grep .env # 見つけたレイヤーtarを展開 → .env が出る 攻撃者がやることは、 これだけ。 1 公開レジストリから docker pull 2 docker save で tar化 3 レイヤー tar を展開して grep .envはDockerイメージに焼き込まれる kenimoto.dev 06 / 12

# Page. 7

![Page Image](https://bcdn.docswell.com/page/4EZLYVYX73.jpg)

これは理論上の話じゃない。 公開レジストリで実測された認証情報漏れ。誰でも踏みうる構造的な罠。 10,000 件超 公開イメージからの認証情報漏れ なぜこれほど 起きるのか? ▶ ローカルで動く .env をそのままCOPY が最短ルート ▶ 動くので気づかない。docker history を叩くまで表に出ない ▶ 一部の不注意でなく、Dockerで動かす人全員が踏みうる ▶ 動くコードほど見直されない = 真面目な人ほどはまる .envはDockerイメージに焼き込まれる kenimoto.dev 07 / 12

# Page. 8

![Page Image](https://bcdn.docswell.com/page/Y76WD5DP7V.jpg)

正解: BuildKit secret mount。 秘密を「そのRUNの間だけ」ファイルとしてマウントする。レイヤーにも history にも残らない。 # syntax=docker/dockerfile:1 FROM python:3.12-slim WORKDIR /app COPY .. # 秘密はこのRUNの間だけマウントされ、レイヤーに残らない RUN --mount=type=secret,id=pipconf,\ target=/root/.pip/pip.conf \ pip install -r requirements.txt $ docker build \ --secret id=pipconf,src=$HOME/.pip/pip.conf \ -t myapp . レイヤーにも docker history にも残らない。 .envはDockerイメージに焼き込まれる kenimoto.dev 08 / 12

# Page. 9

![Page Image](https://bcdn.docswell.com/page/G75M3Y3P74.jpg)

秘密は焼かない・入れない・検出する。 secret mount と合わせる4本柱。優先順にビルドコンテキストから遠ざけていく。 - 01 .dockerignore .env やキー類を書き、COPY .. で巻き込まない。.gitignore と は別ファイルなので両方に書く。 - 02 マルチステージビルド ビルド用ステージで秘密を使い、最終ステージには成果物だけコ ピー。secret mount と必ず併用する。 - 03 実行時に注入 認証情報はイメージに入れず、docker run --env-file やオーケ ストレータのsecret機能で起動時に渡す。 - 04 Trivy でスキャン trivy image --scanners secret をpush前のCIに入れる。人は見 落とすが、機械は毎回全レイヤーを走査する。 .envはDockerイメージに焼き込まれる kenimoto.dev 09 / 12

# Page. 10

![Page Image](https://bcdn.docswell.com/page/9J29ZGZZER.jpg)

安全な Dockerfile の全体像。 ビルドステージで使った秘密が、最終イメージに一切渡らない。イメージは「鍵の入っていない箱」に保つ。 # syntax=docker/dockerfile:1 ―― ビルドステージ ―― FROM python:3.12-slim AS builder WORKDIR /app COPY requirements.txt . RUN --mount=type=secret,id=pipconf,\ target=/root/.pip/pip.conf \ pip install --prefix=/install -r requirements.txt ―― 実行ステージ(成果物のみ) ―― FROM python:3.12-slim WORKDIR /app COPY --from=builder /install /usr/local COPY .. # 認証情報は起動時に渡す CMD [&quot;python&quot;, &quot;main.py&quot;] ここが 効いているのは? ✔ ビルドの秘密は secret mount のRUN中だけ ✔ 実行ステージには 成果物 (/install) だけが渡る ✔ 認証情報は 起動時注入。イメージには入れない ✔ イメージ = 鍵の入っていない箱 .envはDockerイメージに焼き込まれる kenimoto.dev 10 / 12

# Page. 11

![Page Image](https://bcdn.docswell.com/page/DEY4RVRNJM.jpg)

仕組みを知る 側に回る。 「レイヤーは積み重ね」を知っているだけで、COPY .env という1行が一生書けなくなる。 01 COPY .envした秘密は RUN rmしても 下のレイヤーに残る 02 ARG・ENV の値は docker historyで誰でも読める 03 docker save で展開すれば焼き込まれた秘密はそのまま取り出せる 04 公開イメージから1万件超の認証情報漏れが実測されている 05 守り方 = secret mount + .dockerignore + 実行時注入 + Trivyスキャン .envはDockerイメージに焼き込まれる kenimoto.dev 11 / 12

# Page. 12

![Page Image](https://bcdn.docswell.com/page/VJNYDMDV78.jpg)

もっと実践記事は kenimoto.dev。 Docker / Claude Code / LLMO / MCP セキュリティの実装検証ノート。 ↓ 関連トピック kenimoto.dev / read - DOCKER コンテナ運用の落とし穴 .env焼き込み・レイヤー・BuildKitの実践検 証ノート - CLAUDE CODE AIコーディング実装記 Claude Code で書く自律運用ハーネスの設計 と運用 - LLMO AI検索最適化フレーム 生成AI時代の site optimization。5コアコン ポーネント公開 - MCP SECURITY MCP実践セキュリティ 本番導入で躓かないためのMCPガイド。無料 公開 K ken imoto エンジニア / Propel-lab 代表 一 一次情報 100%・借り物ゼロ Web kenimoto.dev Qiita/Zenn/X @kenimo49 .envはDockerイメージに焼き込まれる 12 / 12

