TLS/SSLサーバ証明書をDockerイメージで管理してみないか?

TLS/SSLサーバ証明書あるじゃないですか。アレ、Dockerイメージで管理して運用してみる方法もありじゃないか?という雑エントリです。

Data Volume Container

Dockerコンテナにファイルやディレクトリを供給する方法は色々あって

  1. docker build のときにイメージに閉じ込めてしまう
  2. ホストディレクトリをコンテナにマウントする
  3. 他のコンテナをデータボリュームとして参照する

といった手法。1のdocker buildで閉じ込める手法はお手軽だが、アプリケーションと特定の証明書が密結合になるのでなるべく避けたい。2のホストからマウントの手法もホストのメンテが入るのでポータビリティに乏しい。

このような用途では3の手法が良いと考えている。Data Volume Containerについては以下のリファレンスを参照すると良いです。

Manage data in containers

要は必要なファイル(やディレクトリ)だけのdockerイメージを作成して、それを必要とするコンテナから参照するし、そのパスを環境変数で与えればいいよねという話。

証明書を閉じ込めただけのdockerイメージ

Dockerfileにするとこんな感じになる。非常に軽量なbusyboxイメージをベースに利用する。

FROM busybox:latest 

RUN mkdir /cert
ADD server.pem /cert
ADD server.key /cert

VOLUME /cert

docker buildするホストから必要なファイルを追加すればいい。ここで追加するファイル名はserver.pemやserver.keyみたいにシンプルな名前にしておいた方がよく、証明書が更新されても同じファイル名でいい。その方が参照するアプリケーション(コンテナ)側で証明書のパスを変える必要がなくなるため。

タグ

証明書には期限があるので、日付で切っておくと良いと思う。発行日だったり、もしくは有効期限にしておくと更新を時期を意識できる。

$ docker build -d stormcat24/testcert:20170519 .
$ docker tag stormcat24/testcert:20170519 your_registry/stormcat24/testcert:20170519

このようにタグを運用しておけば、証明書を変えたい場合は参照するデータボリュームコンテナをすげ替えればいいだけの話になる。

注意事項

証明書という性質上、当然証明書や秘密鍵の漏洩を防止できるようにしておく必要がある。PublicなDockerレジストリに置くなんてのはもってのほかなので、最低限でもPrivateなDockerレジストリを用意して適切なACLを施されている状態という前提が必要。

その他応用

この手法は証明書以外にも色々とテクニックがあって、例えばWebフロントエンドのDockerイメージがあって、そのassetsをその前段に置くWebサーバ(Nginxとか最近だとVarnish)から配信させたいみたいな場合なんかでも使える。かなり前のエントリを参照してみてください。

WebアプリをDocker構成にした場合にフロントエンドリソースを扱うためのデザインパターン - tehepero note(・ω<)