はじめに
CloudRunでWordPressのプロダクション環境を構築する機会があったので、構築した際の方法を公開します。
ゴール
・手元の環境でWordPressを開発することができる
・CI/CDを回すことができる
・WordPressのコンテンツデータを保存できる
利用したサービス類
・Apache
・PHP
・WordPress
・CloudRun
・CloudSQL for MySQL
・CloudStorage
・CircleCI
・GitHub
構築した環境
ディレクトリ構成
今回は下記のディレクトリ構成で環境を構築しました。
|-+ .circleci/ - circleciのconfigを保存するディレクトリ
+ credential/ - GCPのcredentialキーを保存するディレクトリ
+ src/ - WordPressのソースコードを保存するディレクトリ
+ dockerfile
+ docker-compose.yaml
構築手順
権限設定
次に、GCPにアクセスするためにいくつか必要な権限があるため、権限を設定していきます。
GCPの権限を設定する
CloudRunからCloudSQLに接続するために、CloudRunのサービスエージェントにCloudSQLクライアントの権限を追加しておきます。
また、docker-composeで起動したWordPressからCloudSQLに接続するために、CloudSQLクライアントの権限を持ったサービスアカウントを1個準備し、json形式のキーをcredential.jsonという名前で事前にダウンロードしておきます。
CircleCIの権限を設定する
CircleCIではContainer RegistryとCloud Runを操作するため、ストレージ管理とCloud Run 管理者の権限を持ったサービスアカウントを1個準備し、こちらもjson形式のキーを事前にダウンロードしておきます。
次にCircleCIの環境変数にGCLOUD_SERVICE_KEYという名前で先程ダウンロードしたjsonキーを設定します。
Dockerfileを準備する
権限設定が終わったので、WordPressが稼働するコンテナを準備していきます。
最終的なDockerfileはこちらです。
ベースとなるコンテナを選択する
Docker Hubで公式のコンテナが提供されているので、適切なものを選択します。
今回はphp:apacheを選択しました。
FROM php:apache
Apacheを設定を調整する
CloudRun上ではデフォルトでは8080ポートをListenしておく必要があるため、apacheが8080ポートでListenするように設定します。
ARG PORT=8080
RUN sed -i'' -e "s/^Listen 80/Listen ${PORT}/g" /etc/apache2/ports.conf \
&& sed -i'' -e "s/:80/:${PORT}/g" /etc/apache2/sites-enabled/000-default.conf
PHPのMySQLライブラリをインストールする
PHP7からmysql extensionが削除されたため、mysqliとPDOをインストールします。
RUN docker-php-ext-install mysqli pdo_mysql
エントリーポイントをカスタマイズする
CloudRun上のWordPressからCloudSQLに接続するために、CloudSQL Proxyを使います。
CloudSQL Proxyのバイナリが提供されているので、コンテナの中にダウンロードしておきます。
RUN wget https://dl.google.com/cloudsql/cloud_sql_proxy.linux.amd64 -O /usr/local/bin/cloud_sql_proxy \
&& chmod +x /usr/local/bin/cloud_sql_proxy
またコンテナ上でCloudSQL Proxyを起動させておく必要があるため、エントリーポイントをカスタマイズしていきます。
COPY docker/cloud-run-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["cloud-run-entrypoint.sh","docker-php-entrypoint"]
CMD ["apache2-foreground"]
カスタムしたエントリーポイントではcloud_sql_proxyを起動しておきます。
この際に、環境変数でCLOUDSQL_INSTANCEを受け取って接続先を変更できるようにしてます。
また、docker-composeで起動した際にCloudSQLに接続できるようにcredential.jsonを読み込むように設定しておきます。
#!/usr/bin/env bash
CREDENTIAL_FILE=/credential/credential.json
SQL_OPTION="${CLOUDSQL_INSTANCE}=tcp:3306"
if [ -e ${CREDENTIAL_FILE} ]; then
SQL_OPTION="${SQL_OPTION} -credential_file=${CREDENTIAL_FILE}"
fi
cloud_sql_proxy -instances=${SQL_OPTION} &
exec "$@"
WordPressを準備する
WordPressの接続先を設定する
WordPressのソースコードはsrcディレクトリに格納しておきます。
DBの接続先を環境変数で受け取るように、wp-config.phpのを設定します。
define('DB_NAME', getenv('DB_NAME'));
define('DB_USER', getenv('DB_USER'));
define('DB_PASSWORD', getenv('DB_PASSWORD'));
define('DB_HOST', getenv('DB_HOST'));
CircleCIを準備する
CircleCIではsrcディレクトリで開発したソースコードをpushした際にCloudRunに反映するところまでを構築していきます。
最終的なconfig.yamlはこちらです。
デプロイまでの流れ
成果物をGitHubにpush
↓
CircleCIでコンテナを作成し、ContainerRegistryにpush
↓
pushしたコンテナを CloudRun にデプロイ
デプロイまでの流れ
CircleCIからGCPリソースを操作できるように、GCPにログインするコマンドを準備します。
ここでは事前に登録していた環境変数GCLOUD_SERVICE_KEYに登録されているサービスアカウントのjsonキーを使います。
commands:
authenticate_gcloud:
steps:
- run:
name: Authenticate gcloud
command: |
echo ${GCLOUD_SERVICE_KEY} | gcloud auth activate-service-account --key-file=-
gcloud auth configure-docker
次にビルドからCloudRunにデプロイするまでのコマンドを準備します。
この際に、ブランチごとにCloudRunのDBへの接続先情報を変更できるように、接続先をパラメータ化しておきます。
commands:
build_image:
steps:
- run:
name: Build the image
command: |
docker build -t ${IMAGE}:${CIRCLE_BRANCH} .
push_image:
steps:
- run:
name: Push the image
command: |
docker push ${IMAGE}:${CIRCLE_BRANCH}
deploy_image:
parameters:
CLOUDRUN_INSTANCE:
type: string
DB_NAME:
type: string
CLOUDSQL_INSTANCE:
type: string
steps:
- deploy:
name: Deploy the image
command: |
gcloud run deploy << parameters.CLOUDRUN_INSTANCE >> \
--platform=managed \
--project=${GOOGLE_PROJECT_ID} \
--region=${REGION} \
--memory=1Gi \
--cpu=2 \
--allow-unauthenticated \
--image=${IMAGE}:${CIRCLE_BRANCH} \
--add-cloudsql-instances=<< parameters.CLOUDSQL_INSTANCE >> \
--set-env-vars CLOUDSQL_INSTANCE=<< parameters.CLOUDSQL_INSTANCE >> \
--set-env-vars DB_NAME=<< parameters.DB_NAME >> \
--set-env-vars DB_HOST=127.0.0.1 \
--set-env-vars DB_USER=*** \
--set-env-vars DB_PASSWORD=***
最後に今まで準備してきたコマンドを使って実際にジョブを構築します。
この際にDBへの接続先と実行したいブランチを指定します。
jobs:
build_and_deploy:
executor: default
steps:
- checkout
- setup_remote_docker:
version: 18.06.0-ce
- build_image
- authenticate_gcloud
- push_image
- deploy_image:
CLOUDRUN_INSTANCE: cloudrun
DB_NAME: cloudsql
CLOUDSQL_INSTANCE: project-id:region:dbname
workflows:
version: 2
build_and_deploy:
jobs:
- build_and_deploy:
filters:
branches:
only:
- master
これでソースコードをGitHubにPushすることでCloudRunが起動するようになりました。
ブランチごとにCloudRunを起動するようにすれば開発環境など複数の環境を簡単に立ち上げることができます。
WordPressのコンテンツをCloudStorageに保存する
これでCloudRunでWordPressを動かしつつ、コンテンツを保存できるようになりました。
ただし、画像データについてはまだ永続化されていないです。
ここについてはWP-Statelessなどのプラグインを利用することでデータをCloudStorage上に保存できるようになります。
docker-composeを準備する
最後にdocker-composeではPC上でWordPressが稼働できるように設定していきます。
最終的なdocker-compose.yamlはこちらです。
環境変数の準備
PHPとCircleCIで待ち受けている環境変数にDBの接続先を指定していきます。
environment:
- DB_NAME=cloudsql
- DB_USER=***
- DB_PASSWORD=***
- DB_HOST=127.0.0.1
- CLOUDSQL_INSTANCE=project-id:region:dbname
ディレクトリをマウントする
次にcredentialディレクトリとsrcディレクトリをマウントします。
volumes:
# 事前に準備しておいたcredential.jsonをdocker上から見えるようにする
- ./credential:/credential
# srcディレクトリを
- ./src:/var/www/html
コンテナイメージを起動する
設定が終わったので、docker-composeでコンテナイメージを起動できれば構築完了です。
docker-compose up -d
参考記事