この記事は、NTTテクノクロス Advent Calendar 2021 の18日目です。
NTTテクノクロスの竹内 光治です。普段は AWS関連案件のマネージャーをしています。最近は GCPと Salesforceを中心に触っています。
はじめに
今回は、DockerソフトウェアでのSSL化対応方法についてのお話です。色々探したんですがしっくりくる記事が見つけられなかったので、ならば備忘録として書き残しておきます。
記事の要約
DockerのVolumeマウント設定を活用してSSL証明書(TLS証明書)を割り当てます。
- 今回の環境条件
- HOST OSはCentOS
- コンテナにイメージとして(たまたま)mediawikiを使用
- コンテナのOSはDebian
- コンテナのWebサーバーはAapche2
記事の背景
WebサイトのSSL化について私がよく実施するのは次の方法です。
- フロントにLBを配置しSSLを終端させる。LBからインスタンスへの通信は非SSLのプレーン通信。
しかし「そんなにアクセストラヒックが無いから冗長構成もLoad BalancerもKubernetesクラスタもいらないよ。ランニングコスト抑えたいし。」とのお題が。そうです、いつもの(?)節約プロジェクトからの打診です。であれば、Dockerコンテナ単品を立てて、直接 コンテナ内のWebサーバーをSSL化することで十分でしょう。
設定の手順
じゃ具体的にどうやるの?ということで、DebianにおけるApacheのSSL化の手順は次の通りです。
(1) a2enmod にて SSLモジュールを有効にする
モジュールの有効化にはa2enmod
コマンドを使用します。これにより、mods-availableに登録されているApacheモジュールに対し、mods-enabledにリンクが張られます。mods-availableに登録が無ければ、moduleをインストールする必要があります。今回のイメージには既にSSLモジュールが登録されてるので、そのまま利用しました。
このコマンドはDockerイメージをビルドするDockerfileに記述します。
RUN a2enmod ssl
(2) サイト設定と SSL証明書を配置する
この記事では証明書の準備には触れませんが、用意した証明書は以下の構成で配置しました。
(ホスト側)
mediawiki/
├ mediawiki_ssl.conf ----- サイト設定config(SSL証明書へのPATHを記述)
└ certs/
├ server.crt ----------- 設定するSSL証明書(サーバー証明書)
└ server.key ----------- 設定するSSL証明書(SSL秘密鍵)
(3) a2ensite にて SSLサイトを有効にする
サイトの有効化にはa2ensite
コマンドを使用します。これにより、sites-availableに登録されている設定ファイルに対し、sites-enabledにリンクが張られます。sites-availableに登録が無ければ、設定を準備する必要があります。
素直に考えると、ホスト側で用意した証明書類をコンテナ内にコピーして、a2ensite
コマンドを発行する、と思うじゃないですか。いえいえ、もう少し簡単になります。ここがこの記事の主題でして、用意したサイト設定はHOST側には既に存在しているので、a2ensite
の代わりにDockerのボリュームマウントを使用してしまえば良いのです。
volumes:
- ./mediawiki/mediawiki_ssl.conf:/etc/apache2/site-enabled/mediawiki_ssl.conf
- ./mediawiki/certs:/etc/ssl/mediawiki
(4) コンテナを起動し設定を確認する
さて、まずはcurl
で接続確認をしてみます。「SSL certificate verify ok.」が返りました。 大丈夫ですね。
curl -s -v https://***.***.***.*** --proxy http://***.***.***.***:****
:
(中略)
:
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use http/1.1
* Server certificate:
* subject: CN=***.***.***.***
* start date: Jul 29 07:39:03 2021 GMT
* expire date: Aug 30 07:39:03 2022 GMT
* subjectAltName: host "***.***.***.***" matched cert's "***.***.***.***"
* issuer: C=BE; O=GlobalSign nv-sa; CN=GlobalSign GCC R3 DV TLS CA 2020
* SSL certificate verify ok.
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
ブラウザからも確認してみます。「この証明書は問題ありません」と表示されました。大丈夫ですね。
まとめ
Dockerfile、docker-compose.yaml 全体像は以下のようになりました。これで無事にコンテナ内のApacheがSSL化されました。
FROM mediawiki
ENV LANG C.UTF-8
RUN a2enmod ssl
# 関連個所を抜粋しています
service:
mediawiki:
container_name: myWiki
build: .
restart: always
ports:
- '8443:443'
networks:
- wiki-net
volumes:
- ./mediawiki/mediawiki_ssl.conf:/etc/apache2/site-enabled/mediawiki_ssl.conf
- ./mediawiki/certs:/etc/ssl/mediawiki
おわりに
a2ensiteのコマンドを使用しても実態はsites-availableからsites-enabledへのリンク設定です。であればDockerのVolumeマウントを使用してHOST側のディレクトリを、コンテナのsites-enabledディレクトリにマウントすればa2ensiteと同様の効果が得られます。定期的に更新されるSSL証明書はHOST側に置くのが便利ですしね。今後は、SSL証明書の自動更新として ACMEプロトコルを組み込みたいと思います(できればお手軽に)。
NTTテクノクロス Advent Calendar 2021、明日は @subutakahiroさんです。お楽しみに!
参考
- Docker and the Docker logo are trademarks or registered trademarks of Docker, Inc. in the United States and/or other countries. Docker, Inc. and other parties may also have trademark rights in other terms used herein.
- Kubernetes® は The Linux Foundation の登録商標です。
- https://manpages.debian.org/buster/apache2/index.html
- https://www.mediawiki.org/wiki/MediaWiki/ja