Github ActionsでCloudRunにWordPressをデプロイし運用する

2020-07-28

GCPのCloudRunについて。私自身もいくつかの案件で既に本番運用を経験しており、ある特定の要件の場合を除き十分に本番運用可能だと感じている。特に、小規模なサービスを複数運用する場合などは向いていると思われる。

需要はあまりなさそうだが、CloudRun + Github Actions + WordPressの環境構築を紹介。

コンテナ環境やCI環境の基本について

WordPressを使用する個人や中小企業の多くはサクッとレンタルサーバーでWPを構築して運用していると思われる。そのため、GitとかDockerとかCIとか正直どうでも良い技術と思う。GitやDocker,CI環境についてほとんど知らない方は以降を読んでも意味がわからないのでオススメしない。

今回の構築は、Github ActionでApacheコンテナを作成してCloudRunにデプロイする。そしてDBはCloudSQLとしSocket接続を行う。また、WP内からのファイルのアップロードについてもGCPStorage(GCS)を使用する。

CloudRun、GCS、CloudSQLの設定

既にGCPでこれらの利用がある場合は別だが、それぞれAPIを有効にする必要がある。また、バケットを作成したり、CloudSQLインスタンスを立ち上げたりする。
[GCS]
https://cloud.google.com/storage/docs/creating-buckets?hl=ja

[CloudSQL]
https://cloud.google.com/sql/docs/mysql/quickstarts

[CloudRun]
https://cloud.google.com/run/docs/quickstarts/prebuilt-deploy

Docker、ApacheConf、UnixSocketの準備

まずはDockerファイルを含むWPのプロジェクトとApache関連のファイル、socket接続のための設定を用意する。
ディレクトリの構造は以下の様にする

├── Dockerfile
├── src (wpのプロジェクトDIR)
├── apache
│   ├── proxy.sh
│   ├── ports.conf
│   └── 000-default.conf
│   └── wp-config.php
└── .github/workflows
    └── master.yml

Dockerfileとwp-config.php

以下の様なDockerfileを用意する。ポイントはcloud_sql_proxyのダウンロードと、ソースのコピーの際に「–chown=www-data」とするところ。

FROM wordpress:latest

EXPOSE 8080

ADD ./apache/ports.conf /etc/apache2
ADD ./apache/000-default.conf /etc/apache2/sites-available

RUN apt-get update && apt-get install -y net-tools wget && \
    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
    
COPY ./apache/proxy.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/proxy.sh

COPY --chown=www-data:www-data src /var/www/html

ENTRYPOINT ["proxy.sh"]
CMD ["apache2-foreground"]

wp-config.phpは一般的にgitignore対象なので、以下の様なwp-config.phpを用意する。今回の例ではapacheディレクトリに配置していることに注意。またDB接続情報は環境変数としているのでこのままコピペでOK。(WPのデフォルトのconfファイルでOK)

<?php
define( 'DB_NAME', getenv('WORDPRESS_DB_DATABASE')  );
define( 'DB_USER', getenv('WORDPRESS_DB_USER')  );
define( 'DB_PASSWORD', getenv('WORDPRESS_DB_PASSWORD')  );
define( 'DB_HOST', getenv('WORDPRESS_DB_HOST') );
define( 'DB_CHARSET', 'utf8mb4' );
define( 'DB_COLLATE', '' );
define( 'AUTH_KEY',         'put your unique phrase here' );
define( 'SECURE_AUTH_KEY',  'put your unique phrase here' );
define( 'LOGGED_IN_KEY',    'put your unique phrase here' );
define( 'NONCE_KEY',        'put your unique phrase here' );
define( 'AUTH_SALT',        'put your unique phrase here' );
define( 'SECURE_AUTH_SALT', 'put your unique phrase here' );
define( 'LOGGED_IN_SALT',   'put your unique phrase here' );
define( 'NONCE_SALT',       'put your unique phrase here' );

$table_prefix = 'wp_';

define( 'WP_DEBUG', false );
if($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
  $_SERVER['HTTPS'] = 'on';
  $_ENV['HTTPS'] = 'on';
}
define('FORCE_SSL_LOGIN', true);
define('FORCE_SSL_ADMIN', true);

if ( ! defined( 'ABSPATH' ) ) {
    define( 'ABSPATH', dirname( __FILE__ ) . '/' );
}

require_once( ABSPATH . 'wp-settings.php' );

Apache関連

ports.conf

Listen 8080

<IfModule ssl_module>
    Listen 443
</IfModule>

<IfModule mod_gnutls.c>
    Listen 443
</IfModule>

000-default.conf

<VirtualHost *:8080>
        ServerName _
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        <Files admin-ajax.php>
            Satisfy any
            allow from all
        </Files>
</VirtualHost>

Socket接続

proxy.shは以下の様にする。前述のDockerfileに記載しているが、ENTRYPOINTとしてproxy.shを実行することでsocket接続できる。

#!/usr/bin/env bash

cloud_sql_proxy -instances=[ご自身の]:[GSQL]:[を設定]=tcp:3306 &
exec "$@"

GitHub Actions

まず今回のプロジェクトのリポジトリをGithubで作成する。

https://github.com/

そしてGithubのSecretsに2つの環境変数を登録する。「Settings」→「Secrets」→「New Secret」で新規に登録できる。

  • GCP_PROJECT_ID : GCPプロジェクトID
  • GCP_SA_KEY : サービスアカウントキーjson文字列のbase64文字列(*1)

(*1) GCPのサービスアカウントキーをjsonファイルでDLしてbase64化したものを保存する。以下のようにbase64文字列を出力できる。


cat key.json | base64

GithubActionでのCIの設定を行う。今回は簡単にmasterブランチへのプッシュをトリガーとする。envの部分を変えるだけで動くはずだ。

name: CI-master
on:
  push:
    branches: [ master ]
env:
  PROJECT: ${{ secrets.GCP_PROJECT_ID }}
  HOSTNAME: asia.gcr.io
  REGION: asia-northeast1
  SERVICE: prod-${{ secrets.GCP_PROJECT_ID }}
  GSQL: [ご自身の]:[GSQL]:[を設定]
  WORDPRESS_DB_DATABASE: [DB名]
  WORDPRESS_DB_USER: [ユーザー名]
  WORDPRESS_DB_PASSWORD: [パスワード]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: GoogleCloudPlatform/github-actions/setup-gcloud@master
        with:
          version: '290.0.1'
          project_id: ${{ secrets.GCP_PROJECT_ID }}
          service_account_key: ${{ secrets.GCP_SA_KEY }}
          export_default_credentials: true

      - name: Config
        run: |
          gcloud config set project ${PROJECT}
          gcloud config set run/region ${REGION}
          gcloud auth configure-docker
          rm -f ./src/wp-config.php
          cp ./apache/wp-config.php ./src/wp-config.php
  
      - name: Build
        run: |
          docker build -t ${HOSTNAME}/${PROJECT}/${SERVICE} .

      - name: Publish
        run: |
          docker push ${HOSTNAME}/${PROJECT}/${SERVICE}

      - name: Deploy
        run: |
          gcloud run deploy ${SERVICE} --image ${HOSTNAME}/${PROJECT}/${SERVICE} --platform managed --allow-unauthenticated --add-cloudsql-instances ${GSQL} --set-env-vars WORDPRESS_DB_HOST=:/cloudsql/${GSQL},WORDPRESS_DB_DATABASE=${WORDPRESS_DB_DATABASE},WORDPRESS_DB_USER=${WORDPRESS_DB_USER},WORDPRESS_DB_PASSWORD=${WORDPRESS_DB_PASSWORD}

ここでmasterブランチにpushするとGithub ActionsのCIが起動してCloudrunにコンテナがデプロイされるはずだ。

コンソール画面で自動的に発行されるURLでWPの初期表示がされるか確認してみる。

うまくいっていれば、今後git pushするだけでcloudrunにデプロイされる。

CloudRunの設定について

CloudRunのコンソール画面(新しいリビジョンのデプロイ)では、CPUやメモリ、最大コンテナ数などを変更することができる。WPの場合はメモリを少し多めに使用する様なので、最低でも512MBにすることをオススメする。やり方は簡単で、以下の様に画面上から変更して保存するだけ。

独自ドメインについて

CloudRunは独自ドメインも簡単に設定できる。もちろんSSLも自動で設定される。
https://cloud.google.com/run/docs/mapping-custom-domains?hl=ja

WPからGCSへのファイルアップロード

CloudRunはあらかじめビルドしたイメージをコンテナとしてデプロイしている。そしてもし稼働しているコンテナ数が0になった場合、次回の起動コンテナは同じビルド済みのイメージを使用して構築される。
つまり、CloudRunコンテナ内へのビルド時にはなかったファイルや、既存のファイルの書き換えはなかったことにされてしまう。なので特にファイルのアップロードについてはCloudRun外のストレージに保存する必要がある。今回はGCSと連携するプラグインを使用する。

https://wordpress.org/plugins/wp-stateless/

これを使用してGCSの特定のバケットをWPのuploadsフォルダと連携することができる。

まとめ

そもそもWordpressをコンテナ環境で運用する必要はあまりないかもしれない。しかし、膨大なアクセスを捌ける環境を作りたいけど、運用初期は大きな集客が見込めない場合など、アクセスの稼働域がとても大きい想定の場合に本領を発揮すると思われる。(このケースではCloudSQLはフルマネージドではないので注意)
もし、アクセスがかなり少ない場合(月に10,000PV以下)、ほとんどのケースでCloudRunの料金は10円以下となるのもメリットの一つ。
また、デフォルトの設定だとCloudRunは80リクエストを一つのコンテナで捌く。そして最大1000コンテナまでスケールアップするので、計算上同時に80,000セッションまで取り扱えるということになる。同時に80,000セッションが継続するWebサイトって世の中に数えるほどしか存在しないほどの巨大なものである。つまりWebサーバーがダウンしてしまうという心配は全く必要ないと考える。
注意点としては、膨大なアクセスがあるサイトなどの場合は当然料金もかなり高くなる。GCPの料金計算ツールで概算を見積もれるので要確認。