006: サービスポート設定のリファクタリング
コンテキスト (Context)
本プロジェクトの初期実装では、サービスポートが複数の場所にハードコードされていました:docker-compose.yml、nginx.conf、Dockerfile (EXPOSE)、およびアプリケーション固有の設定ファイル(50-server.cnf、www.conf)。
このアプローチにはいくつかの課題がありました:
- 柔軟性: ポートを変更するには複数のファイルを編集する必要がありました。
- 環境の独立性: 複数のインスタンスを実行したり、ホストマシン上のポート衝突を回避したりすることが困難でした。
- 冗長性: ポート番号が設定ファイル間で繰り返されており、不整合が生じる可能性がありました。
- リダイレクトループ:
.env経由でパブリックポートを変更(例:443から8443へ)しても、WordPressが適切に設定されていないとデフォルトのポートへリダイレクトしてしまい、アクセス問題が発生していました。
決定 (Decision)
ポート設定を完全に動的にし、.env ファイルで定義された環境変数によって制御されるようにリファクタリングすることを決定しました。
主な変更点 (Key Changes)
- 環境変数:
.envにNGINX_PORT、MARIADB_PORT、WP_PORTを導入しました。 - Dockerfile
ARG&EXPOSE:- Nginx、MariaDB、WordPressのDockerfileを更新し、ポート番号をビルド引数 (
ARG) として受け取るようにしました。 EXPOSE ${PORT_VAR}を使用して、イメージメタデータ内の公開ポートを動的にドキュメント化しました。- これらの引数を
docker-compose.yml経由で渡すようにしました。
- Nginx、MariaDB、WordPressのDockerfileを更新し、ポート番号をビルド引数 (
- 実行時の設定注入 (Runtime Configuration Injection):
- Nginx:
entrypoint.shでenvsubstを使用し、実行時にテンプレートからnginx.confを生成するようにしました。 - MariaDB/WordPress: それぞれの起動スクリプト(
initial_db.sh,setup.sh)でsedを使用し、サービス開始前に設定ファイル(50-server.cnf,www.conf)へ設定されたポートを注入するようにしました。
- Nginx:
- WordPressサイトURLロジック:
- 非標準ポート使用時のリダイレクトループを防ぐため、WordPressサイトURL生成時に
NGINX_PORTを使用するようにsetup.shを更新しました。
- 非標準ポート使用時のリダイレクトループを防ぐため、WordPressサイトURL生成時に
結果 (Consequences)
メリット (Pros)
- 信頼できる唯一の情報源 (Single Source of Truth): すべてのポート設定が
.envで管理されます。 - 変更の容易さ: ポート変更(例:Nginxを8443へ)は、
.envの更新とdocker compose up --buildの実行だけで済みます。 - 整合性: Dockerイメージ内の
EXPOSE命令が実際の設定と一致します。
デメリット (Cons)
- ビルドへの依存:
.envでポート変数を変更した場合、イメージ内のEXPOSEメタデータを更新するためにリビルド(--build)が必要になります(ただし、実行時設定注入があるため、技術的にはリビルドなしでもサービスは動作します)。 - 複雑性: Dockerfileや
docker-compose.ymlに間接的な層(ARG渡し)が追加されました。
実装の詳細 (Detailed Implementation)
Dockerfileパターン
EXPOSE が環境変数を尊重するように、以下のパターンを採用しました:
dockerfile
# Dockerfile
ARG SERVICE_PORT=default_value
EXPOSE ${SERVICE_PORT}yaml
# docker-compose.yml
services:
myservice:
build:
args:
SERVICE_PORT: ${SERVICE_PORT}ボーナス: WebsiteサービスのコールバックURL設定
Website サービス (Node.js/Express) では、OAuthコールバックURLが当初ハードコードされているか、デフォルトの443ポートになっていました。 NGINX_PORT が変更された場合(例:8443へ)、OAuth APIへ送信されるコールバックURLもこの変更を反映する必要があり、そうでないと認証後のリダイレクトに失敗します。
NGINX_PORT を使用して callbackURL を動的に構築するように server.js を更新しました:
javascript
const NGINX_PORT = process.env.NGINX_PORT || 443;
const portSuffix = (NGINX_PORT == 443) ? '' : `:${NGINX_PORT}`;
const callbackURL = `https://${DOMAIN_NAME}${portSuffix}${BASE_URL}/auth/42/callback`;これにより、.env で設定されたポートに関わらず、認証フローが正しく動作することが保証されます。