DockerでApacheのSSL接続
こんにちは!今回は、Docker環境でのSSL接続設定について詳しく解説します。SSL(Secure Sockets Layer)は、インターネット上での通信を暗号化し、セキュリティを向上させる重要な技術です。Dockerを使用した開発環境でも、SSL接続を適切に設定することで、より本番環境に近い安全な環境を構築できます。
Contents
自己署名証明書を使用する場合
https://localhostとしてブラウザで確認すると警告がでます
警告ページで「詳細」や「続行」などのオプションを探します。 リスクを理解した上で、「Webサイトへ進む」などのオプションを選択します。 ブラウザは警告を表示しつつも、ページの表示を許可します。
注意点:この方法は開発環境でのみ推奨されます。
1. docker-compose.ymlの設定
まず、docker-compose.yml
ファイルでSSL接続用のポートを公開する必要があります。以下のように設定します:
services:
app:
ports:
- "0.0.0.0:8082:80"
- "443:443"
この設定により、ホストマシンのポート443がDockerコンテナ内のポート443にマッピングされます。これにより、外部からのHTTPS接続(ポート443)をコンテナ内のApacheサーバーで受け付けることができます。
2. Dockerfileでの設定
次に、Dockerfileで以下のようなSSL関連の設定を行います:
1)SSLモジュールの有効化:
RUN a2enmod ssl
2)デフォルトのSSLサイト設定の有効化:
RUN a2ensite default-ssl
3)自己署名SSL証明書の生成:
RUN echo '#!/bin/bash
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/ssl/private/apache-selfsigned.key \
-out /etc/ssl/certs/apache-selfsigned.crt \
-subj "/CN=localhost"
sed -i "s|SSLCertificateFile.*|SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt|" /etc/apache2/sites-available/default-ssl.conf
sed -i "s|SSLCertificateKeyFile.*|SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key|" /etc/apache2/sites-available/default-ssl.conf' > /usr/local/bin/generate_ssl_cert.sh
RUN chmod +x /usr/local/bin/generate_ssl_cert.sh && /usr/local/bin/generate_ssl_cert.sh
DockerfileのRUN
コマンドがデフォルトでroot権限で実行されるため、追加の権限設定なしでopenssl
コマンドを実行できます。複雑な権限設定なしで、システムレベルの操作を容易に行えます。
openssl
コマンドを使用して自己署名証明書を生成しています。-x509
:自己署名証明書を生成することを指定します。-nodes
:秘密鍵をパスワードで保護しないことを指定します。-days 365
:証明書の有効期間を1年に設定します。-newkey rsa:2048
:2048ビットのRSA鍵を新しく生成します。-keyout
と-out
:鍵と証明書の出力先を指定します。-subj "/CN=localhost"
:証明書のサブジェクト(ここではCommon Name)を設定します。…証明書が保護するドメイン名または IP アドレスを指定します
- sed は “stream editor” の略で、テキストの変換や置換に使用
- 置換パターン:
s|旧パターン|新パターン|
の形式で、|
はデリミタ(区切り文字)として機能
- 置換パターン:
4)ポート443の公開:
EXPOSE 80 443
PHP環境にLet’s Encryptを統合する手順
ローカルDocker開発環境では難しい、、、?
DockerPHP開発環境構築:mkcertを使用したSSL接続の設定
mkcertを使用することで、自己署名証明書の警告なしに安全な開発環境を構築できます。
1. mkcert「エムケイサート」のインストールと使用
1)Windows PowerShell”を右クリックし、“管理者として実行”を選択します。
2)Chocolateyがインストールされていない場合は、まずChocolateyをインストール
Chocolateyは、Windowsのためのパッケージマネージャーです。
Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
3)mkcertをインストール:
choco install mkcert
インストールの確認
mkcert --version
4)ローカル認証局のインストール
mkcert -install
インストールの確認
mkcert -CAROOT
5)証明書の生成:
プロジェクトディレクトリに移動し、以下のコマンドを実行:
mkdir certs
cd certs
mkcert localhost 127.0.0.1 ::1
→ファイル生成
・証明書ファイル: [最初のドメイン名]+[追加エントリ数].pem
(公開鍵を含む)
・秘密鍵ファイル: [最初のドメイン名]+[追加エントリ数]-key.pem
6)各ファイルを編集
鍵ファイルを作成したら下記を実施します
- Apache設定ファイルでは、SSLエンジンを有効にし、証明書と秘密鍵のパスを正しく指定しています。
- Dockerfileでは、Apacheの SSL モジュールを有効化しています。
- docker-compose.ymlでは、443ポートをホストにマッピングし、必要なボリュームをマウントしています。
project_root/
│
├── local-mysite/
│ ├── certs/
│ │ ├── localhost+2.pem
│ │ └── localhost+2-key.pem
│ ├── env_vars/
│ │ └── localhost
│ ├── sites-available/
│ │ └── 000-default.conf
│ ├── .htaccess
│ ├── docker-compose.yml
│ ├── Dockerfile
│ ├── php.ini
│ └── ssl_cert_gen.sh
│
└── mysite/
└── (PHPアプリケーションファイル)
▼docker-compose.yml
version: "3.4"
services:
app:
# Dockerfileからイメージをビルド
build:
context: .
dockerfile: Dockerfile
# ボリュームマウントの設定
volumes:
# 環境変数ファイルをマウント
- ./env_vars:/var/www/env_vars
# PHPアプリケーションのソースコードをマウント
- ../0824_mysite:/var/www/html
# SSL証明書をマウント(読み取り専用)
- ./certs/localhost+2.pem:/etc/ssl/certs/localhost+2.pem:ro
# SSL秘密鍵をマウント(読み取り専用)
- ./certs/localhost+2-key.pem:/etc/ssl/private/localhost+2-key.pem:ro
# Apache設定ファイルをマウント
- ./sites-available:/etc/apache2/sites-available
# ポートマッピングの設定
ports:
# HTTP: ホストの8082ポートをコンテナの80ポートにマッピング
- "0.0.0.0:8082:80"
# HTTPS: ホストの443ポートをコンテナの443ポートにマッピング
- "443:443"
# 環境変数の設定(必要に応じて追加)
environment:
- APACHE_DOCUMENT_ROOT=/var/www/html
▼Dockerfile
# SSL対応PHP開発環境のDockerfile
# PHP 8.1とApacheをベースとした公式イメージを使用
FROM php:8.1-apache
# カスタムApache設定ファイルをコンテナ内の指定された場所にコピー
COPY ./sites-available/000-default.conf /etc/apache2/sites-available/000-default.conf
# PDO_MySQL拡張をインストールし、Apacheのrewrite、proxy、proxy_httpモジュールを有効化
RUN docker-php-ext-install pdo_mysql && a2enmod rewrite proxy proxy_http
# SSLモジュールを有効化
RUN a2enmod ssl
# デフォルトのSSLサイト設定を有効化
RUN a2ensite default-ssl
# 必要なパッケージをインストール
RUN apt-get update && apt-get install -y \
curl \
gnupg \
git \
unzip \
openssl \
# Node.jsのセットアップスクリプトを取得して実行
&& curl -sL https://deb.nodesource.com/setup_18.x | bash - \
# Node.jsをインストール
&& apt-get install -y nodejs \
# パッケージリストを削除してイメージサイズを削減
&& rm -rf /var/lib/apt/lists/*
# Composerをコンテナ内にコピー
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# コンテナ内の作業ディレクトリを設定
WORKDIR /var/www/html
# Composerの設定
ENV COMPOSER_HOME /var/www/.composer
RUN mkdir -p $COMPOSER_HOME && chown -R www-data:www-data $COMPOSER_HOME
# Apache実行ユーザーの設定
ENV APACHE_RUN_USER www-data
ENV APACHE_RUN_GROUP www-data
# Apacheの設定を変更し、.htaccessが機能するようにAllowOverrideをAllに設定
RUN sed -i '/<Directory \/var\/www\/>/,/<\/Directory>/ s/AllowOverride None/AllowOverride All/' /etc/apache2/apache2.conf
# コンテナのポート80(HTTP)と443(HTTPS)を公開
EXPOSE 80 443
# .htaccessファイルをコンテナ内にコピー
COPY .htaccess /var/www/html/.htaccess
# .htaccessファイルの所有権と権限を設定
RUN chown www-data:www-data /var/www/html/.htaccess && chmod 644 /var/www/html/.htaccess
# カスタムphp.iniをコンテナ内にコピー
COPY ./php.ini /usr/local/etc/php/php.ini
# PHPエラーログファイルを作成し、適切な権限を設定
RUN touch /var/log/php_errors.log && chmod 666 /var/log/php_errors.log
# mkcertで生成した証明書をコンテナ内にコピー
COPY ./certs/localhost+2.pem /etc/ssl/certs/localhost.crt
COPY ./certs/localhost+2-key.pem /etc/ssl/private/localhost.key
# 証明書のパーミッションを適切に設定
RUN chmod 644 /etc/ssl/certs/localhost.crt && \
chmod 600 /etc/ssl/private/localhost.key
# Apacheをフォアグラウンドで実行
CMD ["apache2-foreground"]
▼000-default.conf
<VirtualHost *:80>
ServerName localhost
DocumentRoot /var/www/html
Redirect permanent / https://localhost/
# HTTPのアクセスログとエラーログ(必要に応じてコメントを外す)
# ErrorLog ${APACHE_LOG_DIR}/error.log
# CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:443>
ServerName localhost
DocumentRoot /var/www/html
SSLEngine on
SSLCertificateFile /etc/ssl/certs/localhost+2.pem
SSLCertificateKeyFile /etc/ssl/private/localhost+2-key.pem
<Directory /var/www/html>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
```
この設定は、HTTPからHTTPSへのリダイレクトと、SSL/TLS接続の基本的な設定を提供します。
mkcertとopenssl、Let’s Encryptを使用したSSL設定の比較
mkcertとopenssl、Let’s Encryptを使用したSSL設定の主な違いは、使いやすさと生成される証明書の性質にあります。
mkcertは開発環境に特化しており、簡単な操作で信頼されたSSL証明書を生成できます。一方、opensslはより汎用的で、詳細な設定が可能ですが、使用にはより深い知識が必要です。
開発環境では、mkcertの使用が推奨されます:
- セットアップが簡単で、チーム全体で一貫した環境を構築しやすい。
- ブラウザ警告がなく、よりスムーズなテストが可能。
- 開発者が証明書の詳細な管理に時間を割く必要がない。
一方、以下の場合はopensslの使用が適切です:
- 本番環境用の証明書生成。
- カスタムな証明書要件がある場合。
- 証明書生成プロセスの詳細な制御が必要な場合。
重要なポイントは、開発環境と本番環境で異なるアプローチを取ることが多いということです。開発ではmkcertの簡便性を活かし、本番ではopensslやLet’s Encryptなどを使用して、より厳格なセキュリティを確保することが一般的です。
セキュリティの考慮事項
開発環境でのmkcert使用
利点:
- 簡単にローカルでHTTPS環境を構築できる
- 開発者の生産性向上
- 本番環境に近い条件でのテストが可能
制限:
- ローカルマシンでのみ信頼される証明書
- 公的に認証された証明書ではない
mkcertはローカル環境に最適化されているため、本番環境特有の問題を見逃す可能性がある
一般的な本番環境要件:
- 信頼された認証局(CA)による証明書の使用
- 強力な暗号化アルゴリズムの採用
- 定期的な証明書の更新
- 適切なサーバー設定(TLSバージョン、暗号スイートなど)