概要
Dockerの本番環境で秘密情報を使う際に、環境変数を使うことは推奨されてません。
秘密情報を扱うには、コンテナオーケストレーションのsecret supportを使うことが推奨されてます。
Docker Composeには秘密情報を扱うために、secretsがあります。(Docker ComposeのsecretsはDocker Swarmと併用することが前提の機能です)
環境変数で秘密情報を扱う時の問題点
秘密情報を扱う時に、よくある方法として、環境変数を使う方法があります。
(この記事において、秘密情報とはパスワード、APIキーを想定します。)
environment:
MYSQL_USER: root
MYSQL_PASSWORD: password
しかし、Dockerのドキュメントhttps://docs.docker.com/get-started/07_multi_container/ には
While using env vars to set connection settings is generally ok for development, it is HIGHLY DISCOURAGED when running applications in production. Diogo Monica, the former lead of security at Docker, wrote a fantastic blog post explaining why.
A more secure mechanism is to use the secret support provided by your container orchestration framework. In most cases, these secrets are mounted as files in the running container. You’ll see many apps (including the MySQL image and the todo app) also support env vars with a _FILE suffix to point to a file containing the variable.
著者訳
環境変数を使って接続の設定をすることは開発時には一般的にOKですが、本番環境では非常にお勧めできません。Dockerの元セキュリティーリードのDiogo Monicaは、理由について素晴らしい投稿をしてます。
より安全な方法は、コンテナオーケストレーションフレームワークによって提供されるsecret supportを使うことです。ほとんどの場合、これらの秘密情報は実行中のコンテナにファイルとしてマウントされます。多くのアプリ(MySQLのイメージやtodo app(DockerのGet Startedで作成するアプリのこと)を含む)では、環境変数に_FILE
接尾辞ををつけて、変数を含むファイルを示すことができます。
Diogo Monicaの記事では、環境変数で秘密情報を扱う問題点として
- 環境はプロセスで暗黙的に利用可能のため、アクセスや利用を追跡することが困難である。
- アプリケーションが環境をデバッグやエラー報告のために出力することはよくある。
- 環境変数は子プロセスに引き継がれるため、意図しないアクセスが可能になる。これは、最小権限の原則を破る。
- アプリケーションがクラッシュした時、デバッグのために、環境変数をログファイルに保存することは一般的であり、これはディスク上に平文の秘密情報があることを意味する。
- 環境変数に秘密情報を入れると、それはすぐにtribal knowledgeになる。特定の環境変数がデリケートをであると認識していない新人のエンジニアは、適切に処理できない。
とあり、コンテナオーケストレーションツールであるDocker SwarmやKubernetesの機能を使って秘密情報を扱うことが推奨されています。
また、余談ですが
Dockerfile(docker-compose.yamlではない)で
ENV
やARG
を使い環境変数を設定すると、Docker imageに変数の中身まで焼き付いてしまうため注意が必要です。
Docker composeのsecretsで秘密情報を扱う
注意 (2022/8/23追記)
Docker Composeのsecrets
はあくまで、開発用にDocker Swarmの動作結果を模倣しているだけ(マウントしているだけ)で、暗号化などがされていません。本番環境でそのまま使うことはあまりないと思いますが、本番環境で秘密情報は、Docker Swarmやkubernetes(k8s)などの機能を使って取り扱ってください。また、Docker Swarmで秘密情報を扱う場合は、file
プロパティではなくdocker secret
コマンドを併用してください。
@yuicho さんコメントありがとうございました。
Docker SwarmやKubernetesを使わない方法を調べると
Docker Composeには秘密情報を扱うsecrets
というものがあることがわかります。
詳細はhttps://docs.docker.com/compose/compose-file/compose-file-v3/ を参照してください。ここでは1例を紹介します。
使用した環境
- docker desktop version 3.5.2
- macOS 11.4
Docker Composeのファイルフォーマットver3.1以上が必要になります。
version: "3.9"
services:
app:
image: busybox:latest
command: cat -n /run/secrets/my_secret
secrets:
- my_secret
secrets:
my_secret:
file: my_secret.txt
hogehoge
ファイル構造
├── docker-compose.yaml
└── my_secret.txt
実行結果
⋊> docker compose up
[+] Running 1/1
⠿ Container xxxx_app_1 StartedAttaching to app_1
app_1 | 1 hogehoge
app_1 exited with code 0
秘密情報を書いたファイルをsecrets
で指定すると、secretsで指定した名前(例では、my_secret)で、コンテナの/run/secrets/
以下にマウントされます(例では、/run/secrets/my_scretにマウントされれます)。
マウントされた後は、例えばMySQLでは環境変数に_FILE
接尾辞をつけて秘密情報のファイルの場所(/run/secrets/ 以下)を指定したり、環境変数で指定できない場合は、ファイルから秘密情報を読み込む処理を書くことで秘密情報を取り扱うことができます。