DockerでApacheのSSL接続

こんにちは!今回は、Docker環境でのSSL接続設定について詳しく解説します。SSL(Secure Sockets Layer)は、インターネット上での通信を暗号化し、セキュリティを向上させる重要な技術です。Dockerを使用した開発環境でも、SSL接続を適切に設定することで、より本番環境に近い安全な環境を構築できます。

自己署名証明書を使用する場合

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サーバーで受け付けることができます。

ホストマシン(Dockerを実行しているPC) Dockerコンテナ 80 443 80 443 ポートマッピング: 80:80 と 443:443

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
  • 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

localhost+2.pem 証明書 (公開情報) 公開鍵 localhost+2-key.pem 秘密鍵 対応 秘密 – 共有しないこと!

6)各ファイルを編集

鍵ファイルを作成したら下記を実施します

  • Apache設定ファイルでは、SSLエンジンを有効にし、証明書と秘密鍵のパスを正しく指定しています。
  • Dockerfileでは、Apacheの SSL モジュールを有効化しています。
  • docker-compose.ymlでは、443ポートをホストにマッピングし、必要なボリュームをマウントしています。
DockerPHP開発環境でのSSL設定(mkcert使用) ホストマシン Dockerコンテナ mkcert SSL証明書 Apache PHP 証明書のコピー 1. mkcertインストール 2. 証明書生成 3. Dockerfile設定 4. docker-compose.yml設定 5. Apache SSL設定 6. PHP設定(必要に応じて) 7. アプリケーション開発 HTTPSアクセス
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接続の基本的な設定を提供します。
🐳 PHP 🔒 DockerPHP SSL設定

mkcertとopenssl、Let’s Encryptを使用したSSL設定の比較

mkcertとopenssl、Let’s Encryptを使用したSSL設定の主な違いは、使いやすさと生成される証明書の性質にあります。

mkcertは開発環境に特化しており、簡単な操作で信頼されたSSL証明書を生成できます。一方、opensslはより汎用的で、詳細な設定が可能ですが、使用にはより深い知識が必要です。

開発環境では、mkcertの使用が推奨されます:

  1. セットアップが簡単で、チーム全体で一貫した環境を構築しやすい。
  2. ブラウザ警告がなく、よりスムーズなテストが可能。
  3. 開発者が証明書の詳細な管理に時間を割く必要がない。

一方、以下の場合はopensslの使用が適切です:

  1. 本番環境用の証明書生成。
  2. カスタムな証明書要件がある場合。
  3. 証明書生成プロセスの詳細な制御が必要な場合。

重要なポイントは、開発環境と本番環境で異なるアプローチを取ることが多いということです。開発ではmkcertの簡便性を活かし、本番ではopensslやLet’s Encryptなどを使用して、より厳格なセキュリティを確保することが一般的です。

SSL/TLS証明書ツールの比較 mkcert Let’s Encrypt OpenSSL ・ローカル開発用 ・簡単な操作 ・自動的にCA作成 ・ブラウザ警告なし ・無料の公的証明書 ・自動更新可能 ・Webサーバー必要 ・ドメイン名必須 ・汎用的なツール ・詳細な設定可能 ・自己署名証明書 ・高度な知識必要 開発環境 本番環境 カスタム要件

セキュリティの考慮事項

開発環境でのmkcert使用

利点:

  1. 簡単にローカルでHTTPS環境を構築できる
  2. 開発者の生産性向上
  3. 本番環境に近い条件でのテストが可能

制限:

  1. ローカルマシンでのみ信頼される証明書
  2. 公的に認証された証明書ではない

mkcertはローカル環境に最適化されているため、本番環境特有の問題を見逃す可能性がある

一般的な本番環境要件:

  1. 信頼された認証局(CA)による証明書の使用
  2. 強力な暗号化アルゴリズムの採用
  3. 定期的な証明書の更新
  4. 適切なサーバー設定(TLSバージョン、暗号スイートなど)