安全な秘密管理は、コンテナセキュリティの重要な側面です。パスワードとAPIキーを環境変数として挿入すると、意図しない情報の漏洩のリスクがあります。多くの場合、シェル変数はログに記録されたり、子プロセスに渡されたり、知らないうちにエラー報告サービスにリークされたりします。
専用の秘密として値を注入すると、これらのリスクが軽減されます。 Dockerには、DockerComposeでフックできる安全なシークレット管理のサポートが組み込まれています。シークレットへのアクセスは、サービスごとに許可されます。
Docker CLIにはシークレット管理コマンドのバッチがありますが、これらはSwarmクラスターでのみ機能します。 DockerCLIのみを使用してスタンドアロンコンテナにシークレットを追加することはできません。
Docker Composeは、クラスターなしでこれらの機能をワークロードにもたらすために「偽の」シークレットを追加しました。 Composeの実装は、Docker Swarmの機能と同様に機能し、任意のComposeファイルで機能します。
シークレットは、コンテナにバインドマウントされた通常のテキストファイルとして作成されます。アプリケーションは、ファイルの内容を読み取ることによってシークレットの値にアクセスします。このモデルでは、永続的に表示される環境変数とは異なり、コンテナ内で明示的に使用されるまで値を不活性に保つことができます。
シークレットをコンテナに取り込むのは2段階のプロセスです。まず、トップレベルのsecrets
を使用して、シークレットを定義する必要があります 作成ファイルのフィールド。次に、サービス定義を更新して、必要なシークレットを参照します。
シークレットを使用してサービスにパスワードを安全に提供する例を次に示します。
version: "3" services: app: image: example-app:latest secrets: - db_password secrets: db_password: file: ./db_password.txt
シークレットの値は、作業ディレクトリのdb_password.txt
から読み取られます。 docker-compose up
を実行したときのファイル 。 Composeはファイルを/run/secrets/db_password
にマウントします コンテナ内。アプリは、シークレットファイルの内容を読み取ることでデータベースのパスワードにアクセスできます。
Composeでは、ファイルベースのシークレットだけでなく、既存のDockerSwarmシークレットを参照することもできます。このメカニズムを使用する場合は、Dockerでシークレットを前に作成する必要があります。 docker-compose up
を実行します 。 docker secrets
コマンドスペースは、アクティブなDockerエンドポイントがSwarmマネージャーノードである場合にのみ機能します。
Docker CLIを使用してシークレットを作成します:
# take value from standard input echo P@55w0rd | docker secret create db_password - OR # take value from a file docker secret create db_password ./db_password.txtから値を取得します
次に、Docker Composeファイルを更新して、シークレットを参照します。
version: "3" services: app: image: example-app:latest secrets: - db_password secrets: db_password: external: true
シークレットのexternal
を設定する フィールドは、既存のDockerシークレットから値を取得するようにComposeに指示します。シークレットが存在する前にスタックを開始しようとすると、スタックはエラーで失敗します。
インジェクションプロセスをよりきめ細かく制御する必要がある場合、Composeはより長いシークレット構文をサポートします。この構文に切り替えると、ファイルのアクセス許可をカスタマイズしたり、シークレットのマウントされた名前を変更したりできます。
5つのオプションフィールドを使用できます:
source
–参照するシークレットの名前–これは、作成ファイルのsecrets
で定義されている値の1つである必要があります セクション。target
–シークレットがコンテナにマウントされるときに使用するファイル名。-
uid
–マウントされたシークレットファイルに設定するUID。デフォルトは0です。 -
gid
–マウントされたシークレットファイルに設定するGID。デフォルトは0です。 mode
–マウントされたシークレットファイルに適用するファイルシステムのアクセス許可。8進表記で表されます。デフォルトは0444です。シークレットファイルは常にコンテナの一時ファイルシステムにマウントされるため、書き込み可能になることはありません。
マウントされたシークレットファイルの名前を変更し、その権限を変更する変更された例を次に示します。
version: "3" services: app: image: example-app:latest secrets: - source: db_password target: database_password_secret mode: 0440 secrets: db_password: external: true
通常、ほとんどの展開では単純な構文で十分です。より具体的な要件がある場合は、拡張バージョンで必要な制御が可能になります。個々のシークレット参照は、同じ作成ファイル内で2つの構文を組み合わせて一致させることができます。
多くの人気のあるコミュニティDockerイメージは、環境変数ではなくシークレットをサポートするようになりました。画像の作成者として、秘密を提供することは、ユーザーのデータを保護するためのベストプラクティスのアプローチです。
環境変数をファイルパスに設定できるようにすることで、両方のメカニズムをサポートできます。画像にデータベース接続が必要な場合は、ユーザーがDB_PASSWORD
を設定できるようにします P@55w0rd
のいずれかに環境変数 または/run/secrets/db_password
。コンテナは、変数の値が有効なファイルを参照しているかどうかを確認する必要があります。含まれている場合は、それを破棄して、ファイルから最終値を読み取ります。
このモデルにより、ユーザーは展開に最も適切なメカニズムを柔軟に選択できます。すべてのユーザーがシークレットを採用できるわけではないことに注意してください。SwarmとComposeの両方が利用できない場合、それらのユーザーは価値を提供する方法がありません。
通常の環境変数の代わりにシークレットを使用すると、意図しない情報開示のリスクが軽減されます。コンテナが環境変数を侵害されたサードパーティのロギングサービスに送信するという最悪のシナリオを想像してみてください。攻撃者はデータベースのパスワードとAPIキーを入手できるようになりました。
シークレットデータをファイルシステムアクセスに制限することで、値は環境の永続的な機能ではないため、誤って読み取られることはありません。ただし、シークレットファイルには独自のリスクがあることを忘れないでください。それらをソース管理にコミットしたくなるかもしれません。つまり、リポジトリにアクセスできる人なら誰でもそれらの値を読み取ることができます。
シークレットは、コンテナのライフサイクル全体を通じて「シークレット」である必要があります。本番環境へのデプロイでは、通常、CIシステムを使用してビルドを自動化するのが最適です。 CIプロバイダーのパイプライン設定でシークレットを設定し、ビルドスクリプトを使用して、Composeがアクセスできるファイルにシークレットを書き込みます。これにより、CIツールのインターフェースを介して実際の値にアクセスできるのはあなただけになります。