SSL 自己署名証明書と Docker レシピ その2
日立グループ OSS AdventCalendar #2 24日目は、OSSソリューションセンタ 神山 から投稿します。
前回記事(1枚目1日目)にて、Dockerイメージに証明書を組み込む方法を記載しました。今回は、その応用編をいくつか書いていきたいと思います。
応用編: マルチステージ・ビルドで組み込む
マルチステージ・ビルドとは、Docker 17.05 移行で導入された機能で、イメージのビルドを複数のステージに分けて実行できる機能です。マルチステージ・ビルド登場以前は、ビルド時のみ必要なパッケージもイメージに含まれてしまい、イメージの小容量化が難しかったのですが、マルチステージ・ビルドでは、多段階にビルドを分離することで、最終的に配布するイメージ(実行環境)からビルド時にのみ必要なパッケージを分離することが容易となります。
どのOSにしても、ca-certificates パッケージなど、何かしら インストールする必要があり、最小主義で環境を作りたい場合は、ちょっと気持ち悪い状態になります。
そんな時は、Docker のマルチステージ・ビルド を用いるときれいなイメージを作れます。
FROM ubuntu as certs
RUN apt-get update -y && apt-get install -y ca-certificates
COPY self-signed.cert /usr/local/share/ca-certificates/extra/self-signed.crt
RUN update-ca-certificates
FROM ubuntu
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
これは、1回目のビルドで通常通り証明書の登録ツール(update-ca-certificates)のインストールとオレオレ証明書のコピー及び登録をします。
そして2回目のビルドでは、update-ca-certificates の出力結果(/etc/ssl/certs/ca-certificates.crt) のみを新しいイメージに持ってきます。
最終的なイメージは、次のようなきれいなイメージになります。
- オレオレ証明書を含む、システムが信頼する証明書(/etc/ssl/certs/ca-certificates.crt) は存在する
- update-ca-certificates はインストールされていない
- 登録のための一時ファイル(/usr/local/share/ca-certificates/extra/self-signed.crt) は存在しない
マルチステージ・ビルドはきれいなイメージを作りたいにはとても便利です。
応用編: 初見のイメージに証明書を登録する(Jenkins イメージ の例)
ここまでOSやミドルウェアをベースとする場合に、どうやって証明書を登録するかを扱ってきましたが…
実際は特定のサービス(Jenkinsなど…)で証明書を登録したいことも多いかと思います。
自己流なのでもしかしたら効率悪い・邪道な方法かもしれないです。もしもっと良い方法があればコメントでご指摘ください!
試しに Jenkins を例に、証明書を登録する方法を調べてみます。
証明書の登録は root 権限で行う必要がありますが、多くのイメージは、実行権限が root 以外になっています。
そこでまずはイメージの作りを見ていくのですが…
Docker Hub で Jenkins を見ると Dockerfile が公開されておりません。
こういうときは、Docker イメージ自体を調べてみます。
docker pull jenkins
docker history jenkins | grep "USER"
このように、jenkins イメージを取得し、history コマンドでどのようにイメージが作られたかを確認します。
この際、今回知りたいコンテナの実行ユーザーを設定している "USER" で絞り込みます。
すると、
<missing> 2 years ago /bin/sh -c #(nop) USER [jenkins] 0B
このような形で、"jenkins" ユーザーに設定されていることがわかります。
次にOSを特定したいのですが、Dockerfile が公開されていない場合、あたりを付けて調べてみるしかないです。
私はよく、
docker run jenkins apt
といった具合に、パッケージマネージャをたたいてみて、コマンドの有無で調べています。
たまにパッケージマネージャすらも消してしまうような、ギリギリを攻めたイメージがあり、この方法で特定できないこともありますが…経験的にはこの方法でほぼ特定できました。
ここまでわかると、後は 次のような Dockerfile を書いて、ビルドしてあげればOKです。
FROM jenkins
USER root
COPY self-signed.cert /usr/local/share/ca-certificates/extra/self-signed.crt
RUN update-ca-certificates
USER jenkins
- ユーザをroot に戻す
- OSに合わせた方法で証明書をインストール(この場合は debian)
- ここでは ca-certificates パッケージはインストールしていません(jenkins イメージではインストール済)
- 多くの場合 ca-certificates パッケージが既にインストールされているため、まずは存在すること前提で呼び出すのがおすすめです。稀にインストールされていない場合がありエラーとなりますので、その場合は、 ca-certificates パッケージ のインストールも手順に組み込むと良いです
- ユーザを元に戻す
- 元のイメージと使用感を合わせるために、実行ユーザは元に戻しておいた方が良いです
これで、正しくオレオレ証明書を認識するイメージが出来上がります。
さいごに
今回は、SSL証明書の登録を行う際に、イメージを小さくする方法や、初見イメージに対して組み込む流れを書いてみました。
この辺りは手探りな部分もあるので、もっと良い方法があれば、改善していきたいです。