機密情報を安全に扱う - secrets
API キー・DB パスワード・証明書などの機密情報をイメージや環境変数に平文で埋め込まず、専用の仕組みで注入する運用。Docker secrets・Compose secrets・Vault・クラウド KMS などを使い分ける。
概念図
構文
bash
echo "s3cret" | docker secret create db_pass -
docker service create --secret db_pass myapp実例
Swarm モードで secret を作成
bash
echo "s3cret" | docker secret create db_pass -環境変数ファイルから注入(開発用)
bash
docker run --rm --env-file .env.local appファイルマウントで機密情報を渡す
bash
docker run --rm -v $PWD/secrets:/run/secrets:ro app概要
コンテナで最もやってはいけないのが、Dockerfile に ENV DB_PASSWORD=... と書き込むことです。
イメージレイヤーは削除してもレジストリに残り、docker history で中身が見えてしまいます。
Git にコミットすれば、誰でも履歴から取り出せます。
代わりに、実行時に外から注入する仕組みを使います。
用途別に次のような選択肢があります。
| 方式 | 適した場面 |
|---|---|
| Docker secrets(Swarm) | Swarm クラスタ。/run/secrets/<name> に tmpfs マウント |
| Compose secrets | ローカル開発 / 単一ホスト Compose |
| Kubernetes Secret + External Secrets Operator | k8s 本番。外部の金庫と同期 |
| HashiCorp Vault | 動的シークレット・詳細なアクセス制御が必要 |
| AWS Secrets Manager / GCP Secret Manager / Azure Key Vault | クラウドマネージドで IAM と統合 |
| SOPS / age / git-crypt | リポジトリに暗号化したまま含めたいケース |
典型的な用途
- DB パスワード・API キー・TLS 秘密鍵をコンテナに渡す
- マルチ環境(dev / staging / prod)で同じイメージを流用し、環境ごとに別の秘密情報を注入する
- 短命な動的シークレット(Vault で都度発行する DB 認証情報)を使う
- OAuth クライアントシークレットを CI / 本番に配布する
- リポジトリに含める必要のあるシークレットを SOPS で暗号化する
コマンド例
# Swarm で secret を作ってサービスに渡す
echo "s3cret" | docker secret create db_pass -
docker service create --name api --secret db_pass myapp:1.0
# アプリは /run/secrets/db_pass を読み取る
# Compose(compose.yml)
# services:
# api:
# image: myapp:1.0
# secrets:
# - db_pass
# secrets:
# db_pass:
# file: ./secrets/db_pass.txt
# ビルド時のみ必要なシークレット(BuildKit)
# syntax=docker/dockerfile:1.7
# RUN --mount=type=secret,id=npm,target=/root/.npmrc npm ci
docker build --secret id=npm,src=$HOME/.npmrc -t app .
ベストプラクティス
- イメージに秘密情報を焼き込まない。ビルド時も BuildKit の
--secretを使いレイヤーに残さない - 環境変数よりファイルマウント(
/run/secrets/...)を選ぶ。環境変数はpsや子プロセス経由で漏れやすい - 本番では専用のシークレットストア(Vault / クラウド KMS / k8s External Secrets)を使い、ローテーションを自動化する
.envファイルは.gitignoreに入れ、誤コミットを防ぐため pre-commit フックで検査する- シークレットアクセスは監査ログに残し、誰がいつ取得したかを追える状態にする
注意点
- Kubernetes Secret はデフォルトで base64 エンコードのみ。etcd 暗号化や External Secrets Operator を併用する
docker inspectにコンテナの環境変数がそのまま出るため、ログや issue スクリーンショットに混入しないよう注意- BuildKit 以外のビルドで
--build-argに秘密情報を渡すと、履歴に平文で残る - Swarm の secret は Swarm モードが前提で、単体
docker runでは使えない(代わりに bind mount) - クラウドのマネージドシークレットを使う場合、IAM 権限が過剰だと「シークレットストアを導入したのに全員が読める」状態になる
関連トピック
trivy / grype- コンテナイメージに含まれる OS パッケージや言語ライブラリの既知脆弱性(CVE)を検出するツール。Trivy と Grype が代表格で、CI に組み込んでビルド時やプル時に自動実行するのが標準運用。 rootless- コンテナランタイムとコンテナ内プロセスを非特権ユーザーで動かす方式。万一コンテナから脱出されてもホスト側で root を奪われない構成にできる。Podman はデフォルト、Docker もオプションで対応。 --read-only- コンテナのルートファイルシステムを読み取り専用で起動し、書き込みが必要な部分だけ tmpfs や volume に分離する構成。マルウェアの書き込みや改ざんを防ぎ、Immutable Infrastructure を強化する。 