馬とテニスのIT革命
馬とテニスとリラックマが好きな IT 系のエンジニアです。
Docker

PHP+ApacheのDockerコンテナをSSL通信に対応させる

以前紹介した、PHP と Apache がセットになった Docker イメージ。

あわせて読みたい
Dockerコンテナ上のファイルをローカルにコピーするコンテナのビルド時に、コンテナ上のサーバにファイルを配備するには Dockerfile を利用すると楽です。 RUN でコマンドを...

サクっと PHP が動作するサーバを立てるなら、Nginx と php-fpm を導入するよりは楽です。

そこで今回は、このコンテナで SSL のサーバ認証をさせる方法を紹介します。

クライアント証明書を使った認証については別の機会にまとめます。

コンテナの用途

今回、このコンテナを使う目的はローカルや開発サーバの検証用を想定しています。

よって、サーバ証明書にオレオレ証明書(自己証明書)を使い、クライアント証明書も同様となります。

クライアント証明書を使うケースはそれほどないかもしれませんが、VPN を使うほどでもないけど IP 固定ができないからという状況では利用することがあります。

本番で利用するなら有償のサービスでクライアント証明書を発行というパターンが多いと思いますが、運用費を考えると開発環境やローカルで同じようにクライアント証明書の環境を用意する場合、自己証明書でカバーするのがベターでしょうね。

SSLサーバ証明書の導入

冒頭で紹介した Docker イメージではデフォルトで SSL が有効になっていないので、コンテナのビルド時に以下の処理もまとめて行ってみます。

サーバ証明書の作成
Apacheの設定

ローカルや開発サーバなら無理に SSL にすることはないって思う人もいるかも知れませんが、本番に近い環境に持っていった際にプロトコルの違いで挙動が異なることもあるので、証明書の違いはあれど少しは近い状態で開発を進めた方が無難です。

最近では Google のセキュリティー対策の啓蒙活動につられるように、SSL(https)化されたサイトが一気に増えました。

少し前まではレンタルサーバなどで Let’s Encrypt の導入がされていなかったので、やりたくてもできないユーザがいましたが、主要なブログサービスやレンタルサーバでサービスが開始されています。

ローカル環境でも Docker ならすぐに SSL 通信可能なコンテナが立ち上げられるので、なるべく環境の差異が少なくなるようにしておきましょう。

スクリプトの作成

Dockerfile にすべて定義できなくもないですが、後々クライアント証明書を設定することを想定して別スクリプトに抜き出します。

まずはサーバ証明書の設定から。これを entrypoint.sh として保存しておきます。

#!/bin/sh

# サーバのホスト名(名前をつけてhostsファイルで解決させてもOK)
SSL_HOST_NAME="localhost"
# サーバ証明書や秘密鍵を配備するディレクトリ
SSL_PKI_DIR="/etc/pki/ssl"
# 証明書の所有者の情報
SERVER_SUBJECT="/C=JP/ST=Tokyo/L=Shibuya/O=Rilakkuma Ltd./OU=Dev/CN=${SSL_HOST_NAME}"
# 証明書の有効期間(10年)
DAYS=3650

mkdir -p ${SSL_PKI_DIR}
openssl genrsa -out ${SSL_PKI_DIR}/server.key 2048
openssl req -new -key ${SSL_PKI_DIR}/server.key -out ${SSL_PKI_DIR}/server.csr -subj "${SERVER_SUBJECT}"
openssl x509 -in ${SSL_PKI_DIR}/server.csr -days ${DAYS} -req -signkey ${SSL_PKI_DIR}/server.key -out ${SSL_PKI_DIR}/server.crt

Dockerfileの作成

次に Dockerfile の作成です。

コンテナのビルド時に vi を使えるようにする記事を書いたときと同様に、ここにメインとなる処理を定義します。

あわせて読みたい
Dockerコンテナのビルド時にvi(vim)をインストールする以前、Docker コンテナ上のファイルをローカルにコピーする記事を書きました。 https://kumanotemo.com/a...

実は、RUN についてはワンライナーで定義した方がイメージの容量節約になるようなのでバックスラッシュで改行しつつ && で繋ぐ方法がベターなようです。

COPY はどうなんだろうか。

FROM php:7.1.9-apache

ENV APACHE_DOCUMENT_ROOT /var/www/html

COPY conf/apache2.conf /etc/apache2/apache2.conf
COPY conf/ssl.conf /etc/apache2/sites-available/ssl.conf
COPY conf/entrypoint.sh /tmp/

RUN mkdir -p /etc/pki/ssl
RUN chmod a+x /tmp/entrypoint.sh
RUN /bin/bash -c "source /opt/entrypoint.sh"
RUN a2enmod ssl
RUN a2ensite ssl

CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]

apache2.conf や ssl.conf についてはあらかじめ必要な情報を書いておき、それをサーバにコピーする手段を今回は選択しました。

Dockerfile の書き方で注意しておきたいことは以下にまとめられているので参考にしてみましょう。

と言いつつ、上の Dockerfile はあえてわかりやすいように 1 行ずつ RUN も定義しています。

443番ポートをポートフォワードする

通常だとコンテナの 80 番ポートを localhost の特定のポートにポートフォワードしますが、今回は SSL に対応したので 443 番も忘れずに設定しておきます。

docker-compose の yaml ファイルでコンテナを定義している場合はそこに追記します。

ports:
  - "10080:80"
  - "10443:443"

これで https でアクセスが可能となりますが、サーバ証明書がオレオレ証明書なので、ブラウザでアクセスする際は警告を例外として扱うようにしましょう。

次回はクライアント証明書の認証も、コンテナビルド時に設定する方法を紹介していきます。

Web API The Good Parts

オライリーの「Web API」に特化した本です。最近の多くの Web サービスは API が活用されていますが、その技術はこれまでの Web サイトとそれほど大きく変わりません。

今後、マイクロサービス化が進む中で知っておいて損はない内容が詰め込まれており、現場のエンジニアやこれから Web 系のエンジニアを目指す人にもオススメの一冊です。

created by Rinker
¥2,376
(2018/10/20 14:06:04時点 Amazon調べ-詳細)