最近Dockerを試してみて、いじくりまわすサービスを構築していますが、Dockerfileにパスワードを入れておくのが厄介です。私は開発者ですので、ソースにパスワードを保存するのは面倒な感じがします。これも心配ですか? Dockerfilesでパスワードを処理する方法に関する良い規則はありますか?
間違いなく心配です。 Dockerfileは通常、リポジトリにチェックインされ、他の人と共有されます。別の方法は、資格情報(ユーザー名、パスワード、トークン、機密性の高いもの)を提供することです 実行時の環境変数として 。これは、-e
引数(CLIの個々の変数の場合)または--env-file
引数(ファイル内の複数の変数の場合)を介してdocker run
に可能です。 docker-composeで環境を使用するには this を読んでください。
--env-file
を使用する場合、ps
またはログに表示される秘密から保護するため、set -x
の使用は間違いなく安全なオプションです。
ただし、env変数も特に安全ではありません。 docker inspect
を介して表示されるため、docker
コマンドを実行できるすべてのユーザーが使用できます。 (もちろん、ホスト上のdocker
にアクセスできるユーザーは ルートを持っています とにかく。)
私の優先パターンは、ENTRYPOINT
またはCMD
としてラッパースクリプトを使用することです。ラッパースクリプトは、実行時に最初に外部ロケーションからコンテナにシークレットをインポートし、次にアプリケーションを実行してシークレットを提供できます。これの正確なメカニズムは、実行時環境によって異なります。 AWSでは、IAMロール、 Key Management Service 、およびS3の組み合わせを使用して、暗号化されたシークレットをS3バケットに保存できます。 HashiCorp Vault または credstash のようなものも別のオプションです。
知る限り、ビルドプロセスの一部として機密データを使用するための最適なパターンはありません。実際、このトピックについて SOの質問 があります。 docker-squash を使用して、画像からレイヤーを削除できます。ただし、Dockerにはこの目的のためのネイティブ機能はありません。
Shykes コンテナ内の設定に関するコメント が便利かもしれません。
私たちのチームは、リポジトリに資格情報を配置することを避けているため、Dockerfile
で資格情報が許可されていません。アプリケーション内でのベストプラクティスは、環境変数のcredsを使用することです。
docker-compose
を使用してこれを解決します。
docker-compose.yml
内で、コンテナの環境変数を含むファイルを指定できます。
env_file:
- .env
必ず.env
を.gitignore
に追加してから、.env
ファイル内で資格情報を次のように設定してください。
SOME_USERNAME=myUser
SOME_PWD_VAR=myPwd
.env
ファイルをローカルに保存するか、チームの他のメンバーが取得できる安全な場所に保存します。
参照: https://docs.docker.com/compose/environment-variables/#/the-env-file
Docker(バージョン1.13または17.06以降)は、秘密情報の管理をサポートしています。 概要 およびより詳細な ドキュメント
同様の機能が kubernetes および DCOS に存在します
イメージをダウンロードできる人に資格情報をブロードキャストしても問題ない限り、資格情報をコンテナに追加しないでください。特に、ADD creds
以降のRUN rm creds
は、credsファイルが中間ファイルシステムレイヤーの最終イメージに残るため、安全ではありません。画像にアクセスできる人は誰でも簡単に抽出できます。
依存関係をチェックアウトするために信任状が必要なときに見た典型的なソリューションは、あるコンテナを使用して別のコンテナを構築することです。つまり、通常、ベースコンテナーにビルド環境があり、アプリコンテナーをビルドするためにそれを呼び出す必要があります。そのため、簡単な解決策は、アプリのソースを追加してからRUN
ビルドコマンドを追加することです。そのRUN
に資格情報が必要な場合、これは安全ではありません。代わりに、ソースをローカルディレクトリに配置し、(docker run
のように)コンテナを実行して、ローカルソースディレクトリをボリュームとしてマウントし、credsを別のボリュームとして挿入またはマウントしてビルドステップを実行します。ビルド手順が完了したら、ビルドされたアーティファクトを含むローカルソースディレクトリをADD
ingするだけで、最終的なコンテナをビルドします。
Dockerがこのすべてを簡素化する機能を追加することを望んでいます!
更新:今後の方法では、ビルドをネストするようになります。要するに、dockerfileは、ランタイム環境を構築するために使用される最初のコンテナーを記述し、次に、すべてのピースを最終的なコンテナーにアセンブルできる2番目のネストされたコンテナービルドを記述します。このように、ビルド時のものは2番目のコンテナーにはありません。これはJavaアプリです。アプリのビルドにはJDKが必要ですが、実行にはJREのみが必要です。多くの提案が議論されていますが、 https://github.com/docker/docker/issues/7115 から始めて、いくつかの代替提案のリンクをたどってください。
環境変数を使用する代わりに、環境変数がたくさんあると面倒になる可能性がありますが、ボリュームを使用してホスト上のディレクトリをコンテナでアクセス可能にすることです。
すべての資格情報をそのフォルダー内のファイルとして配置すると、コンテナーはファイルを読み取り、必要に応じて使用できます。
例えば:
$ echo "secret" > /root/configs/password.txt
$ docker run -v /root/configs:/cfg ...
In the Docker container:
# echo Password is `cat /cfg/password.txt`
Password is secret
多くのプログラムは、別のファイルから資格情報を読み取ることができるため、この方法では、プログラムをファイルの1つに向けることができます。
Docker v1.9では、ARG命令を使用して引数をフェッチできますビルドアクションのイメージにコマンドラインで渡されます。 -build-argフラグを使用するだけです。そのため、Dockerfileに明示的なパスワード(またはその他の賢明な情報)を保持して、その場で渡すことを避けることができます。
ソース: https://docs.docker.com/engine/reference/commandline/build/http://docs.docker.com/engine/reference/builder/#arg
例:
Dockerfile
FROM busybox
ARG user
RUN echo "user is $user"
build imageコマンド
docker build --build-arg user=capuccino -t test_arguments -f path/to/dockerfile .
ビルド中に印刷します
$ docker build --build-arg user=capuccino -t test_arguments -f ./test_args.Dockerfile .
Sending build context to Docker daemon 2.048 kB
Step 1 : FROM busybox
---> c51f86c28340
Step 2 : ARG user
---> Running in 43a4aa0e421d
---> f0359070fc8f
Removing intermediate container 43a4aa0e421d
Step 3 : RUN echo "user is $user"
---> Running in 4360fb10d46a
**user is capuccino**
---> 1408147c1cb9
Removing intermediate container 4360fb10d46a
Successfully built 1408147c1cb9
それが役に立てば幸い!またね.
実行時のみの解決策
docker-composeは、非スウォームモードソリューションも提供します(v1.11: バインドマウントを使用したシークレット )。
秘密はdocker-composeによって/run/secrets/
の下にファイルとしてマウントされます。これにより、/run/secrets/
がビルド時にマウントされないため、実行時(コンテナーの実行)で問題が解決されますが、ビルド時(イメージのビルド)では解決されません。さらに、この動作は、docker-composeでコンテナーを実行することに依存します。
例:
Dockerfile
FROM Alpine
RUN cat /run/secrets/password
CMD sleep inifinity
docker-compose.yml
version: '3.1'
services:
app:
build: .
secrets:
- password
secrets:
password:
file: password.txt
ビルドするには、次を実行します。
docker-compose up -d
参考文献:
私のアプローチはうまくいくようですが、おそらく素朴です。なぜ間違っているのか教えてください。
Dockerビルド中に設定されたARGは、historyサブコマンドによって公開されるため、そこには行きません。ただし、コンテナを実行する場合、runコマンドで指定された環境変数はコンテナで使用できますが、イメージの一部ではありません。
そのため、Dockerfileで、秘密データを含まないセットアップを行います。 /root/finish.sh
のようなもののCMDを設定します。 runコマンドで、環境変数を使用して秘密データをコンテナに送信します。 finish.sh
は、本質的に変数を使用してビルドタスクを完了します。
秘密データの管理を容易にするために、--env-file
スイッチを使用してdocker runによってロードされるファイルに入れます。もちろん、ファイルを秘密にしておきます。 .gitignore
など。
私にとって、finish.sh
はPythonプログラムを実行します。以前に実行されていないことを確認してから、セットアップを終了します(たとえば、データベース名をDjangoのsettings.py
にコピーします)。
「秘密」管理用の新しいdockerコマンド[1]がありますが、それはswarmクラスターに対してのみ機能します。
docker service create
--name my-iis
--publish target=8000,port=8000
--secret src=homepage,target="\inetpub\wwwroot\index.html"
Microsoft/iis:nanoserver
単純な解決策はないことに完全に同意します。単一障害点が引き続き存在します。 dockerfile、etcdなどのいずれか。 Apceraには相棒のような計画があります-二重認証。つまり、Apcera構成ルールがない限り、2つのコンテナーは通信できません。デモでは、uid/pwdはクリアであり、管理者がリンクを設定するまで再利用できませんでした。ただし、これが機能するためには、おそらくDockerまたは少なくともネットワークプラグイン(そのようなことがある場合)にパッチを適用する必要がありました。
12-Factorアプリの方法論 は、すべての構成を環境変数に保存する必要があることを示しています。
Docker composeは、構成で 変数置換 を実行できます。そのため、ホストからdockerにパスワードを渡すために使用できます。