Dockerfileでプライベートリポジトリからレポジトリをclone。 わかります??
以下の記事を参考にしました。 vsupalov.com
通常このように書けばいいと思われがち。
というか自分はこれでいいと思っていた。
ARG SSH_PRIVATE_KEY RUN mkdir /root/.ssh/ RUN echo "${SSH_PRIVATE_KEY}" > /root/.ssh/id_rsa # [...] RUN rm /root/.ssh/id_rsa
やっていることはいたってシンプル。
SSH_PRIVATE_KEY
としてコンテナ作成時に秘密鍵を渡すだけ。
甘い。甘すぎるよkimoton。
何がまずいの??
試しに上記のやばいDockerfileを使用して、以下のようにイメージを作成してみる。
SSH_PRIVATE_KEY
はdocker build
コマンドの実行時に--build-arg
引数として渡すか、docker-compose.yml
のbuildセクションに記述することでコンテナに渡すことができます。
$ docker build --build-arg SSH_PRIVATE_KEY=testtesttest -t kimoton/yabai . Sending build context to Docker daemon 2.048kB Step 1/6 : FROM centos ---> 1e1148e4cc2c Step 2/6 : ARG SSH_PRIVATE_KEY ---> Running in fa59663a1496 Removing intermediate container fa59663a1496 ---> 1bb440bceb04 Step 3/6 : RUN mkdir /root/.ssh/ ---> Running in eb0f4f35b42e Removing intermediate container eb0f4f35b42e ---> b1dc93116422 Step 4/6 : RUN echo "${SSH_PRIVATE_KEY}" > /root/.ssh/id_rsa ---> Running in 7370ef573596 Removing intermediate container 7370ef573596 ---> f12c7d9e29a9 Step 5/6 : RUN rm /root/.ssh/id_rsa ---> Running in ba2e6a4797e8 Removing intermediate container ba2e6a4797e8 ---> df0c2ddc75c9 Step 6/6 : CMD tail -f /dev/null ---> Running in 4a34c83ba114 Removing intermediate container 4a34c83ba114 ---> 9d62a050705f Successfully built 9d62a050705f Successfully tagged kimoton/yabai:latest
ここでdocker history
を打ってみると、、
$ docker history kimoton/yabai IMAGE CREATED CREATED BY SIZE COMMENT 9d62a050705f 3 minutes ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "tail… 0B df0c2ddc75c9 3 minutes ago |1 SSH_PRIVATE_KEY=testtesttest /bin/sh -c r… 0B f12c7d9e29a9 3 minutes ago |1 SSH_PRIVATE_KEY=testtesttest /bin/sh -c e… 13B b1dc93116422 3 minutes ago |1 SSH_PRIVATE_KEY=testtesttest /bin/sh -c m… 0B 1bb440bceb04 3 minutes ago /bin/sh -c #(nop) ARG SSH_PRIVATE_KEY 0B 1e1148e4cc2c 5 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 5 weeks ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> 5 weeks ago /bin/sh -c #(nop) ADD file:6f877549795f4798a… 202MB```
SSH_PRIVATE_KEY=testtesttest
が丸見え。
さらに言えば、実体まで残ってます。
$ docker run -it f12c7d9e29a9 cat /root/.ssh/id_rsa
testtesttest
この鍵ファイルを含むイメージを、不特定多数のユーザが参照可能なレジストリにpushした日にはもう大惨事です。
GitやS3などのアクセス権限を奪取される恐れがあります。絶対にやめましょう。
要するに単にRUN rm
しても無駄なんですね。
dockerイメージはマルチレイヤで構成されている & デフォルトで過去のレイヤは保持されるため、セキュリティー的にまずいものは意図的に消さねばなりません。
じゃあどうするか。
第1の選択肢。押しつぶす。
※これは微妙な解です。微妙な解を知りたくない人は次の項目まで飛ばしてください。
squashって押しつぶすって意味なんですね。
Docker 1.13から、--squash
という引数が実験的に使用できるようになりました。
このオプションを使用するには、Experimentalモードにしなければなりません。
Docker for WindowsをDockerデーモンに使用している場合、のSettings > DeamonからExperimental featuresにチェックを入れてください。
通常のDockerデーモンを使用している場合、以下を参考にしてください。 qiita.com
docker version
コマンドを実行した際にDocker Engineが
Experimental: true
となっていればOKです。
$ docker version Client: Version: 18.09.0 API version: 1.39 Go version: go1.10.4 Git commit: 4d60db4 Built: Wed Nov 7 00:49:01 2018 OS/Arch: linux/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 18.09.0 API version: 1.39 (minimum version 1.12) Go version: go1.10.4 Git commit: 4d60db4 Built: Wed Nov 7 00:55:00 2018 OS/Arch: linux/amd64 Experimental: true
この--squash
オプションは、複数レイヤからなるイメージを、オリジナルと最新のステージのレイヤのみを残すことで、イメージのサイズを小さくするのに使われます。
参考:docker buildのsquashオプションを試す - Qiita
これを使用してDockerイメージを作ると、、
docker history kimoton/squash IMAGE CREATED CREATED BY SIZE COMMENT 707a78e1ce12 About an hour ago 0B merge sha256:d94c9209e30829d49f6e18c84330a24b99ef43593d91b72358e74df48d6d62d9 to sha256:1e1148e4cc2c148c6890a18e3b2d2dde41a6745ceb4e5fe94a923d811bf82ddb <missing> About an hour ago /bin/sh -c #(nop) CMD ["/bin/sh" "-c" "tail… 0B <missing> About an hour ago |1 SSH_PRIVATE_KEY=testtesttest /bin/sh -c r… 0B <missing> About an hour ago |1 SSH_PRIVATE_KEY=testtesttest /bin/sh -c e… 0B <missing> About an hour ago |1 SSH_PRIVATE_KEY=testtesttest /bin/sh -c m… 0B <missing> About an hour ago /bin/sh -c #(nop) ARG SSH_PRIVATE_KEY 0B <missing> 5 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 5 weeks ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> 5 weeks ago /bin/sh -c #(nop) ADD file:6f877549795f4798a… 202MB
見事にcredentialな情報が入っている不要な中間レイヤが消えました!
これで中間レイヤに入ってid_rsa
を見に行くことはできなくなります。
しかし実行時に渡しているSSH_PRIVATE_KEY=testtesttest
は相変わらず見えてしまっています。。
さらに、この方法は毎回忘れずにこの引数を使う必要があるという何とも微妙な解決策となっています。
マルチステージビルド
Docker17.05以上ではマルチステージビルドという機能が使えます。
この機能を使うと、複数のイメージを連鎖的に使用し、あるイメージの生成物を別のイメージへと引き継ぐことができます。
なお、最後に作成したイメージ以外は記録が残らず、ほかのイメージはそのイメージを作成する手助けをするために使用されます。
すなわち、中間イメージの1つにSSH鍵を渡しそのイメージの中で依存ライブラリや必要なデータのダウンロードを行いコンパイルを行ってしまった上で、最終的に使用するイメージに必要なディレクトリだけを渡せば、イメージサイズを節約しながら、安全にcredentialなデータを扱うことができます。
例えば以下のようなDockerfileを使用します。
このDockerfileを使用して作成したDockerイメージを見てみると、、
当たり前ですが、最終的に作成したイメージ内の~/.ssh/
以下にはファイルが存在しません。
$ docker run -it kimoton/multistage ls ~/.ssh/ ls: cannot access /home/kimoton/.ssh/: No such file or directory
また、このイメージではcredentialな情報を示した引数は使用されていないため、docker history
コマンドで参照されてしまう恐れもありません。
実際にdocker history
コマンドを実行した結果は以下のようになります。
$ docker history kimoton/multistage IMAGE CREATED CREATED BY SIZE COMMENT 032b29cab9f5 33 seconds ago 18kB merge sha256:49dabbbee1dd809ce19e20971c2968c56cf0dd24cf3ebf3f5d81c1e112d11997 to sha256:1e1148e4cc2c148c6890a18e3b2d2dde41a6745ceb4e5fe94a923d811bf82ddb <missing> 33 seconds ago /bin/sh -c #(nop) COPY dir:429b124a8f606daaa… 0B <missing> 5 weeks ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0B <missing> 5 weeks ago /bin/sh -c #(nop) LABEL org.label-schema.sc… 0B <missing> 5 weeks ago /bin/sh -c #(nop) ADD file:6f877549795f4798a… 202MB
イメージサイズを大幅に節約できる上にcredentialなデータを安全にできるという何ともかっちょいいビルドが行えるんですね。
Secure Mount
Docker 18.09から、Secure Mountという機能が加わったみたいです。
今はこちらを使う方が良いのかもしれません。
今度試してみます。。