はじめに
いままで社内向けのチーム活動のブログとして Wordpress を Azure 上で運用しておりました。ところが、諸事情により Azure 上での運用が難しくなったため、Google Cloud に移行することとしました。そこで、Azure 上では AppService で運用していたため、Google Cloud でも PaaS として Cloud Run で動かすことを目指しました。
この記事では、社内向け EntraID 認証付の Wordpress を Cloud Run で構築する際のポイントをまとめたいと思います。
構成
ここで、ポイントとして Google Cloud IAP を使っているところです。Azure 環境では Easy Auth を使って、Wordpress に手を加えずに認証機能を実現していたので、Google Cloud でも同様な構成を行いたいと思い、IAP がそれに該当するとして導入しました。
IAP (Identity Aware Proxy) を利用したサービス構築
IAP 公式: https://cloud.google.com/iap/docs/concepts-overview?hl=ja
IAP を簡単に説明すると、ノーコードで認証プロキシを立ててくれるサービスです。もちろん、カスタマイズのためにコードを書く事もできます。Google アカウントの他、OIDC, SAML, Facebook, Apple, Github, Basic認証など様々なIDに対応しています。今回は、OIDC を使って、EntraID に対応しました。
では、サービス構築にあたって、それぞれのポイントを述べたいと思います。
事前準備
事前準備として、公式の案内に従って以下のリソースを作成します。
-
VPC ネットワークを作成
Cloud SQL (MySQL) を利用するため、あらかじめ VPC ネットワークを作成します。
-
Cloud SQL (MySQL) を作成
-
ロードバランサ用の外部 IP アドレスを取得 (Google Cloud で取得可能)
-
ロードバランサ用のドメインを取得、Cloud DNS に登録
Cloud Run (Wordpress)
さて、Wordpress を動かす Cloud Run ですが、大きくは以下の2点がポイントになります。また、ポイントとして挙げていないですが、Cloud SQL につなげるために VPC への接続が必要です。イメージは、Wordpress のオフィシャルイメージを使います。
イメージ: https://hub.docker.com/_/wordpress
ポイント
-
認証は、「公開アクセスを許可する」
今回は、IAP による認証を行うので、Cloud Run 自身で認証を行いません。
-
Ingress は、「内部 + 外部アプリケーションロードバランサからのトラフィックを許可する」
Cloud Run に外部から直接アクセスすることはないので、本設定にした方がセキュリティ的に安全です。
Cloud Load Balancing
ロードバランサを作成します。Google Cloud コンソール画面ではロードバランサ作成の中で IAP も作れますが、ここでは作りません。まずは、ロードバランサと Cloud Run がしっかりつながっているのかを確認したほうが良いです。
アクセス確認にあたって、バックエンド側の Cloud Run の動作を確認したい場合に、Wordpress を公開するのは危ないので、Google Cloud 公式の hello イメージなど活用すると安全です。
イメージ: us-docker.pkg.dev/cloudrun/container/hello:latest
Cloud Run (Login)
さて、ここから IAP を使ったログイン用の Cloud Run を立てます。SDK を使って自作することもできますが、今回は公式のイメージを使用します。
イメージ: gcr.io/gcip-iap/authui
ポイント
-
認証は、「公開アクセスを許可する」
未認証でアクセスするので公開アクセスを許可します。
-
Ingress は、「すべて」
どうも認証リダイレクト時は、自身のアドレスが使用されるので、外部アクセスを許可します。
EntraID を設定
ここだけ、Azure 側の設定になります。Login 用の Cloud Run の認証用 URL を EntraID 側アプリケーションの、WebリダイレクトURIに登録します。
例: Cloud Run のホストが test.com
の場合、リダイレクトURIはhttps://test.com/__/auth/handler
となります。
プロバイダを設定
Google Cloud の Identity Platform このソールから、プロバイダ追加を行います。
ポイント
プロバイダ登録時に、承認済みドメイン項目にログイン用 Cloud Run のホストを追加します。
IAP
ローバランサを作成すると、Google Cloud コンソールの IAP の画面に該当ロードバランサが表示されるようになります。ここで IAP を ON にして、外部 ID の使用を開始します。
ポイント
ここで、先ほど作成したログイン用 Cloud Run の URL を入力します。ApiKey に関する記述が説明されておりますが、特に気にする必要はありません。リダイレクト URL ではないので、注意してください。
firebase
ここまでを行えば、ロードバランサのドレスから、認証が行われるようになると思います。もし、ログインできない場合は、firebase の Authentication を確認してください。例えば、ユーザーアクションで作成が許可されていないことがあります。
永続化ストレージ対応
まず端的に言うと、/var/www/html
ディレクトリは永続化ストレージに配置しないといけないです。Cloud Run でこれを実現するには、Google Cloud Storage の Storage FUSE 機能を使って、GCS を Cloud Run にマウントします。
公式: https://cloud.google.com/run/docs/configuring/services/cloud-storage-volume-mounts?hl=ja
ポイント
永続化ストレージとしてマウントしたほうが良い理由は以下の通りです。
- 現時点での公式 Dockerfile を見ると、該当ディレクトリを VOLUME 指定している
- Wordpress の言語ファイルダウンロード先ディレクトリの所有者確認において、ソースコードディレクトリと異なる所有者だと FTP 転送の設定を強制される
- Wordpress コンテナ起動時に該当ディレクトリにファイルがあれば、Wordpress インストール処理が回避されるので、起動が早くなる
このため、Wordpress インストール先である /var/www/html
を丸々永続化ストレージにするのが良いです。
大容量ファイルのアップロード対応
Wordpress を公開するだけなら、永続化ストレージ対応までで完了です。ここから、Wordpress に大容量ファイルのアップロードできるようにするための対応を入れます。
ブログ移行の場合、移行ファイルが大容量になることがあります。しかし、本構成においては2つのファイル上限が存在します。
- PHP に設定されているアップロードファイル上限
- Cloud Run のアップロード上限
移行ファイルがこれらの上限を超える場合には、引き上げが必要になります。
PHP のアップロード上限の引き上げ
こちらは簡単で、上限値を設定した php.ini ファイル作成し、/usr/local/etc/php/
ディレクトリに配置してあげれば解決します。このため、公式イメージをベースにした独自の Dockerfile を作りました。Dockerfile と php.ini のサンプルは後述します。
Cloud Run のアップロード上限の引き上げ
こちらは手間です。そもそも、Cloud Run のアップロード上限は以下のようになっています。
公式: https://cloud.google.com/run/quotas?hl=ja#networking_limits
- HTTP/1 サーバを使用する場合は 32 MiB
- HTTP/2 サーバを使用する場合は無制限
このため、アップロード上限を引き上げるためには、HTTP/2 サーバとして構築する必要があります。そこで、Cloud Run のマルチコンテナ機能を利用しました。(もちろん、apache を HTTP/2 化する案もありますが、Wordpress のイメージが変わったときの対応が手間なので、あまり手を入れない方法を取りました。)
公式: https://cloud.google.com/run/docs/deploying?hl=ja#multicontainer-yaml
つまり、以下のような形で HTTP/2 サーバとしてのリバースプロキシとして NGINX を動かし、Wordpress の実処理は HTTP/1 で行うようにします。
ポイント
-
Login サーバ側も HTTP/2 化が必要なので同様の構成する
詳細は省きますが、IAP 側の Login サーバも HTTP/2 化しないと wordpress 側にアクセスできないようなので、同じような構成にします。
-
リバースプロキシを設定しても、以下の問題が発生する
- 認証のリダイレクト URL が localhost になってしまう
- ホーム画面にアクセスすると、localhost にリダイレクトされる
- ポート80番が使えないために Wordpress コンテナが起動しない
認証のリダイレクト URL が localhost になってしまう問題を解決する
Login サーバをリバースプロキシ化したので、自ホスト名が localhost になってしまうのですね。
IAPコンテナは GCS から設定ファイルを読み込むことができるので、そこにリダイレクト先ホスト名を指定することができます。
対応手順
-
IAP コンテナから現在の設定を取得する (gcloud CLI 必須。以下 PowerShell の場合)
$url = "(Login サーバの URL)/get_admin_config" $token = (gcloud auth print-access-token) $response = Invoke-WebRequest -Uri $url -Headers @{"Authorization"="Bearer $token"} -Method Get $response.Content
-
設定の authDomain に、Login サーバの URL (リダイレクト URL のホストまで) を設定する
-
新規に GCS にバケットを作成し、設定ファイルを、"config.json" の名前で配置する
-
IAP コンテナに環境変数
GCS_BUCKET_NAME
として、設定ファイルのバケット名を設定する
公式: https://cloud.google.com/iap/docs/cloud-run-sign-in?hl=ja#setting_environment_variables
ホーム画面にアクセスすると、localhost にリダイレクトされる問題を解決する
Wordpress のホーム画面にアクセスすると、localhost にリダイレクトされる現象に見舞われました。詳細は省きますが、Wordpress の apache のホスト名が localhost で動いていることが原因のようです。Wordpress をリバースプロキシで動かすと、同様な現象に見舞われるそうです。
そこで、NGINX のプロキシ設定から、HOST ヘッダを本来のドメインに設定すればこの問題は解決します。
ポート80番が使えないため Wordpress コンテナが起動しない問題を解決する
capability というものがあるらしく、1024 番ポート以下は、利用できないことがある様です。
Docker 公式: https://docs.docker.jp/v1.12/engine/security/security.html#linux
このため、80 番ポート以外で wordpress を起動するように、apache に設定を追加します。結局、apache の設定は免れないのですね。
設定箇所
注意点として、php:8.4-apache イメージを使っていることをご留意ください。
-
/etc/apache2/
の posts.conf に Listen ポート番号を変更する -
/etc/apache2/sites-available/
に Wordpress 用の設定として、上記ポート番号に対するVirtualHost を作成する
動作ファイル
以下が動作した設定ファイルになります。最終的なデプロイは、docker-compose の yaml ファイルを作成しておりますので、ご留意ください。
NGINX のリバースプロキシ設定 (LoginServer, Wordpress 両方ある)
nginx.conf
server {
listen (待ち受けポート);
http2 on;
client_max_body_size 1G;
send_timeout 3600s;
proxy_connect_timeout 3600s;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
proxy_set_header Host (Wordpress 側は Host の設定を入れて、ロードバランサのホスト名を入れる);
location / {
proxy_pass http://localhost:(各アプリコンテナ側ポート);
}
}
Dockerfile
FROM nginx:1.29.1-alpine-slim
EXPOSE (NGINX 待ち受けポート)
COPY ./nginx.conf /etc/nginx/conf.d/nginx.conf
Wordpress 側設定
php.ini
upload_max_filesize = 2G
post_max_size = 3G
memory_limit = 4G
max_execution_time = 3600
max_input_time = 0
upload_tmp_dir = /var/www/html/wp-content/temp
port.conf
Listen (Wordpress 待ち受けポート)
<IfModule ssl_module>
Listen 443
</IfModule>
<IfModule mod_gnutls.c>
Listen 443
</IfModule>
wordpress.conf
<VirtualHost *:(Wordpress 待ち受けポート)>
ServerAdmin webmaster@localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Dockerfile
FROM wordpress:6.8.2-php8.4
# カスタム php.ini を適用
COPY php.ini /usr/local/etc/php/
# apache2 のポート変更
COPY (ports.conf へのパス) /etc/apache2/
COPY (wordpress.conf へのパス) /etc/apache2/sites-available/
EXPOSE (Wordpress 待ち受けポート)
おわりに
全体感として、実現はできたけれどもHTTP/2の利用などは過渡期で時期尚早だなという感じがしました。また、不満点として認証トークン切れすると、Wordpress 単体では復帰できないので、こういった点を何とかしたいなと思います。