はじめに
docker build --build-arg http_proxy=...
で認証プロキシを設定すると危険だよ、という情報があまり広まっていない気がしたので書いておく。
なにが問題か?
Dockerのドキュメントより引用です。
Warning: It is not recommended to use build-time variables for passing secrets like github keys, user credentials etc. Build-time variable values are visible to any user of the image with the docker history command.
そう、--build-arg
で渡した環境変数はイメージには保存されていないから安全 と思ってはいけない。docker history
で参照できるメタデータにはバッチリ渡した環境変数が保存されているのである。
例えばdocker build --build-arg http_proxy=http://foo:bar@proxy.example.org
のようにプロキシの認証情報を設定してビルドしていると、そのイメージをpullした環境でdocker history
するとプロキシ接続に利用したユーザID/パスワードが丸分かりになっちゃう、ということ。
この話、Qiitaで docker build-arg proxy で検索すると引っかかる記事では、触れられているものがなさそうで不安になった。
また、Qiita以外の日本語情報をググって探してみると、teratailに docker build で指定する http_proxy が履歴に残らないようにしたい というズバリそのものの質問があった。ぱっと目についたのはこの1件くらいと、気にしている人はかなり少なそうな印象。
で、どうすればいい?
いくつか対策はある。
対策1: Dockerをバージョンアップする
この問題、本家のISSUEでも扱われて実は新しめのDockerだと既に解決済みになっている。具体的には、Exclude “default” build-args from image historyというプルリクエストにより、下記のデフォルトのbuild-argsはhistoryから除外されるようになった。
HTTP_PROXY
http_proxy
HTTPS_PROXY
https_proxy
FTP_PROXY
ftp_proxy
NO_PROXY
no_proxy
Dockerのリリースノートを見ると、
- Docker CEの場合は 17.05.0-ce (2017-05-04) 以上
- Docker EEの場合は 17.06.1-ee (2017-08-16) 以上
ならこの修正が入っており大丈夫そう。ただし、リリースノートの下記記載のとおり、Dockerfileの中に ARG http_proxy
みたいに書いてしまうと駄目なので注意。
The values of default build time arguments (e.g HTTP_PROXY) are no longer displayed in docker image history unless a corresponding ARG instruction is written in the Dockerfile. #31584
というわけで、新しいDockerに移行できるなら、これが一番簡単な対策方法。
(もちろんコンテナの再ビルドは必要。あと、過去のコンテナイメージはすでにpullされて広まっている可能性があるので、やってしまった方はパスワード変更をまず先にすべきでしょう)
対策:2 認証なしのプロキシを中継用に構築する
これは、teratailの回答 で示されていた方法の1つだが、認証なしのプロキシをDockerと認証プロキシの間に配置し、そこから認証プロキシに接続するようにするという方式。これだと、--build-arg
で渡すプロキシ情報には認証情報は入れなくて済む(プロキシを使っていることは分かってしまうが)。
自分は試していないが、認証ありHTTPプロキシを認証なしでプロキシするDockerfileでsquidを使って簡単にこのような中継プロキシを構築できるかも。
対策:3 透過プロキシを利用する
これも、teratailの回答 で示されていた方法の1つ。Dockerホスト側で透過プロキシを構築して、透過的に認証プロキシを経由させるという方法。これだと、--build-arg
でプロキシ情報は一切渡さなくて済む。Dockerのバージョンを上げれない場合はこの方法が個人的にはよいと思う。
なお、先日書いた プロキシとの戦いに疲れたのでgoで透過プロキシを作ってみた で紹介している透過プロキシを使うことで簡単に対応できる。
まとめ
- Docker CE 17.05.0-ce未満を使っている場合、
docker build --build-arg http_proxy=...
で認証プロキシを設定するのは今すぐ止めよう (パスワード変更も忘れずに)。 - Docker CE 17.05.0-ce以上にバージョンアップできる場合はそれでOK。コンテナの再ビルドは忘れずに。
- バージョンアップできない場合は、透過プロキシ等を使って、少なくとも直接認証プロキシ情報を
--build-arg
には設定しないようにすること。
おまけ
プロキシ関連で、Docker CE 17.07.0-ce (2017-08-29) 以上だと、下記のリリースノート内容のとおり、$HOME/.docker/config.json
でプロキシ情報を設定できるようになっているので、--build-arg
で毎回渡す手間を省けるようになっている。
Add support for proxy configuration in config.json docker/cli#93
なお、この設定はdocker build
だけでなく、docker run
時にも有効だそうで。設定方法はドキュメントに書かれているが、残念ながら実装と違うというISSUEが報告されており、正しくは以下のように設定する必要がある模様。
{
"proxies":
{
"default":
{
"httpProxy": "http://127.0.0.1:3001",
"noProxy": "*.test.example.com,.example2.com"
}
}
}