Dock Stay
機密情報を安全に扱う - secrets の使い方・オプション・サンプル

機密情報を安全に扱う - secrets

API キー・DB パスワード・証明書などの機密情報をイメージや環境変数に平文で埋め込まず、専用の仕組みで注入する運用。Docker secrets・Compose secrets・Vault・クラウド KMS などを使い分ける。

概念図

secrets diagram

構文

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 権限が過剰だと「シークレットストアを導入したのに全員が読める」状態になる

関連トピック