WordPressをSQLite対応してGitで管理し、AWS Lightsail Containerへデプロイする構成
3秒まとめ
- WordPressをSQLiteで運用することで、すべてをファイルで管理できるようになる
- Git + Docker + Lightsail Containerで使うべきではない言葉なので修正してくださいの運用ワークフローが構築できる
- 管理画面を無効化してセキュリティリスクを大幅削減
- 月$7で本格的なコンテナ運用が可能
どんな人向けの記事?
- WordPress の運用でバージョン管理に困っている方
- 開発環境・ステージング・本番環境の同期が大変だと感じている方
- コーポレートサイトなどの更新頻度が少ない WordPress をよりモダンな開発フローで運用したい方
- セキュリティを重視した WordPress 運用を考えている方
- コンテナ技術で WordPress を運用してみたい方
背景
WordPress で運用されているサイトは大量に存在しますよね。用途は多種多様ですが、今回は開発環境、ステージング環境、本番環境などの複数の環境が存在するようなコーポレートサイト、プラグイン開発、テーマ開発をしている方を対象としています。
問題
WordPress の表示はファイル × データベースの内容の組み合わせになっています。 開発環境でテーマファイルやプラグインを変更した場合は、各環境でファイルとデータベースの内容を同期する必要があるのですが、これがかなり運用上大変なんですよね…😅

具体的には、次のような問題があります。
- バージョン管理ができなくて辛い
- 不具合が起きたときに、ファイルが原因なのか入稿されているデータが原因か特定するのが難しい
- 環境間でのデータ同期が煩雑
- ロールバックが困難
アプローチ
WordPress の バックアップを難しくしているのは データベース内に入っているデータと ファイルシステム上にあるファイルが存在していて一緒にバックアップを取る必要がありますが、データベースのバックアップを取得するのが面倒です。そのデータベースをファイルとして扱えるように SQLite を使ってサイトを構築します。

そうすれば、ファイルとしてバックアップするだけでスナップショットが取れます。スナップショットがファイルとして簡単に取得できるということはそれを様々な環境へ適用できます。 そのデータファイルもテーマファイルやプラグインとバージョン管理システムに入れることでスナップショットとして管理することが可能になります。

WordPress を SQLite で運用する詳細な方法については、こちらの記事で解説しています! https://zenn.dev/matsubokkuri/articles/wordpress-sqlite
アプローチの評価を以下にまとめます。メリットが多いので新規で構築する際はこの方法を取ることを強く推奨します!
メリット
- すべての状態をファイルで管理することが可能になり、差分が明確になるしロールバックも容易に行える
- 開発環境はDocker composeで立ち上げることが可能になる(めちゃくちゃ楽!)
- 本番環境はコンテナで運用できるようになり、スケールアウトが可能になる
- SQLiteのデータファイルはバイナリデータではあるがポータビリティがあるので OS のアーキテクチャ非依存
- 本番はコンテナの運用なので管理画面を無効化できるのでログイン画面へのアタックがなくなる(セキュリティ使うべきではない言葉なので修正してください! 🛡️)
- WordPressの本体は公式イメージを使うのでコア機能の更新が容易
デメリット
- Webでコンテンツの更新ができなくなる。コンテンツを更新する際はローカルなどで行う必要がある
- データベース上のデータはバイナリファイルなので差分がテキストではわからない(コミットフックで差分を毎回取ってファイルとして dump しても良いがやり過ぎ感がある)
- AWS Lightsail Containerがちょっと高い。具体的には月に$7 USD/month かかる
Web でのコンテンツ更新ができなくなるのは一見デメリットに見えますが、実際にはコンテンツの変更履歴が残るので、むしろメリットと考えることもできます!
設定方法
まず、ローカルでDocker composeでWordPress + SQLiteが立ち上がる環境を作ります。
ディレクトリ構成は以下のようになります。
.├── docker-compose.yml├── Makefile├── themes/ # WordPressテーマ├── plugins/ # WordPressプラグイン├── uploads/ # アップロードファイル├── database/ # データベースファイル├── db.php # SQLiteを使うためのドロップイン└── custom.ini # PHP設定のオーバーライドWordPressの本体はdocker imageを利用するのでカスタマイズする部分だけを管理します。これがポイントです!
次に重要なファイルを解説していきます。
docker-compose.yml
中身は以下のようになります。
services: wordpress: image: wordpress:latest user: "${UID:-1000}:${GID:-1000}" restart: always volumes: - ./themes:/var/www/html/wp-content/themes - ./plugins:/var/www/html/wp-content/plugins - ./uploads:/var/www/html/wp-content/uploads - ./database:/var/www/html/wp-content/database - ./db.php:/var/www/html/wp-content/db.php - ./custom.ini:/usr/local/etc/php/conf.d/custom.ini ports: - "8080:80" environment: # 日本語ロケール設定 LANG: ja_JP.UTF-8 LANGUAGE: ja_JP:ja LC_ALL: ja_JP.UTF-8 WORDPRESS_DB_HOST: dummy WORDPRESS_DB_NAME: dummy WORDPRESS_DB_USER: dummy WORDPRESS_CONFIG_EXTRA: | define('WP_HOME', '${WP_HOME}'); define('WP_SITEURL', '${WP_HOME}'); define('WP_AUTO_UPDATE_CORE', ${WP_AUTO_UPDATE_CORE:-false}); define('WP_DEBUG_LOG', ${WP_DEBUG_LOG:-true}); define('WP_DEBUG_DISPLAY', ${WP_DEBUG_DISPLAY:-true}); WORDPRESS_AUTH_KEY: ${WORDPRESS_AUTH_KEY:-dummy} WORDPRESS_SECURE_AUTH_KEY: ${WORDPRESS_SECURE_AUTH_KEY:-dummy} WORDPRESS_LOGGED_IN_KEY: ${WORDPRESS_LOGGED_IN_KEY:-dummy} WORDPRESS_NONCE_KEY: ${WORDPRESS_NONCE_KEY:-dummy} WORDPRESS_AUTH_SALT: ${WORDPRESS_AUTH_SALT:-dummy} WORDPRESS_SECURE_AUTH_SALT: ${WORDPRESS_SECURE_AUTH_SALT:-dummy} WORDPRESS_LOGGED_IN_SALT: ${WORDPRESS_LOGGED_IN_SALT:-dummy} WORDPRESS_NONCE_SALT: ${WORDPRESS_NONCE_SALT:-dummy}上記のファイルがすべてのスタートとなるので重要です。コンテナは1つだけなのでシンプルな構成になっています。公式のWordPressのイメージはApache + PHPという構成になっています。
次に主要なセクションを解説します。
volumes セクション
volumes セクションで公式のWordPressでは空っぽになる部分を、自分で管理するためにローカルのファイルシステムをマウントします。
PHPの設定は適切な場所にファイルを置けば、勝手に読んでくれるので、そのまま使います。
custom.ini には以下の設定を入れています。初期設定では大きな画像がアップロードできないので、大きめに設定しています。
post_max_size = 200Mupload_max_filesize = 200Menvironment セクション
環境変数である environment について説明します。
以下の設定はSQLiteなので不要なのですが、WordPress側が公式にサポートしていないということもあり何かしらの値を設定する必要があるのでダミーの文字列を設定しています。ちょっとかっこ悪いですがこれがないと動きません😅
WORDPRESS_DB_HOST: dummyWORDPRESS_DB_NAME: dummyWORDPRESS_DB_USER: dummyWordPressのデータベース上には自分のサイトのURLを記録する必要がありますが、それを環境ごとに外部から指定するために上の2つの環境変数を設定します。本番環境では、プラグインなどの自動更新は不要なので、WP_AUTO_UPDATE_CORE を false にします。また、ローカルといった開発環境ではデバッグ関連の出力を多く出すために WP_DEBUG_LOG と WP_DEBUG_DISPLAY を true にします。
WORDPRESS_CONFIG_EXTRA: | define('WP_HOME', '${WP_HOME}'); define('WP_SITEURL', '${WP_HOME}'); define('WP_AUTO_UPDATE_CORE', ${WP_AUTO_UPDATE_CORE:-false}); define('WP_DEBUG_LOG', ${WP_DEBUG_LOG:-true}); define('WP_DEBUG_DISPLAY', ${WP_DEBUG_DISPLAY:-true});秘密鍵を設定するために WORDPRESS_AUTH_KEY などの環境変数を設定します。この設定はなくても良いのですが、設定しないとコンテナの起動のたびにランダムな英数字が設定されます。それによって、ログインしているセッションがすべて破棄されるので何かしらを設定しておいたほうが便利です。
WORDPRESS_AUTH_KEY: ${WORDPRESS_AUTH_KEY:-dummy}WORDPRESS_SECURE_AUTH_KEY: ${WORDPRESS_SECURE_AUTH_KEY:-dummy}WORDPRESS_LOGGED_IN_KEY: ${WORDPRESS_LOGGED_IN_KEY:-dummy}WORDPRESS_NONCE_KEY: ${WORDPRESS_NONCE_KEY:-dummy}WORDPRESS_AUTH_SALT: ${WORDPRESS_AUTH_SALT:-dummy}WORDPRESS_SECURE_AUTH_SALT: ${WORDPRESS_SECURE_AUTH_SALT:-dummy}WORDPRESS_LOGGED_IN_SALT: ${WORDPRESS_LOGGED_IN_SALT:-dummy}WORDPRESS_NONCE_SALT: ${WORDPRESS_NONCE_SALT:-dummy}.envファイル
.envファイルの最低限の設定は以下のような感じになります。
UID=501GID=20WP_HOME="http://localhost:8080"その他のファイル
db.php ファイルはこちらのファイルです。
Makefile にはこちらののような内容を入れています。なくてもよいのですが、docker関連の地味な権限周りの修正などを行うためにあったほうが楽です。
起動方法
一通りファイルを揃えて、以下のコマンドを打てば立ち上がるはずです。
make upそして、http://localhost:8080 にアクセスするとWordPressが表示されます! 🎉
デプロイメント
ここまででWordPressをしっかりとファイルで管理できるようになったらどこにでも簡単にデプロイできます。rsyncでサーバに同期しても良いです。ここでは、より柔軟な方法を使ってインフラを運用するのでコンテナ環境でデプロイします。
lightsailではTLSのターミネーションをしてくれるので証明書の更新も自動化できます。
ファイルの準備
デプロイするイメージを作るためのDockerfileを用意します。
FROM wordpress:latest
# 日本語ロケールのインストールと設定RUN apt-get update && apt-get install -y locales \ && sed -i '/ja_JP.UTF-8/s/^# //g' /etc/locale.gen \ && locale-gen \ && apt-get clean \ && rm -rf /var/lib/apt/lists/*
ENV LANG=ja_JP.UTF-8ENV LANGUAGE=ja_JP:jaENV LC_ALL=ja_JP.UTF-8
# カスタムPHP設定をコピーCOPY custom.ini /usr/local/etc/php/conf.d/custom.ini
# WordPressファイルをコピー(日本語ファイル名対応)COPY themes/ /var/www/html/wp-content/themes/COPY plugins/ /var/www/html/wp-content/plugins/COPY uploads/ /var/www/html/wp-content/uploads/COPY database/ /var/www/html/wp-content/database/COPY db.php /var/www/html/wp-content/db.php
# WordPress管理機能の無効化RUN rm -f /usr/src/wordpress/wp-login.php \ /usr/src/wordpress/wp-config-sample.php \ /usr/src/wordpress/readme.html \ /usr/src/wordpress/license.txt \ /usr/src/wordpress/wp-trackback.php \ /usr/src/wordpress/wp-comments-post.php
# ポート80を公開EXPOSE 80
# WordPressを起動CMD ["apache2-foreground"]簡単に解説すると、docker composeでやっていることとほとんど同じです。デプロイする環境ではWordPressの管理機能は使わせられないので管理画面に必要なファイルや運用に関係ないファイルを削除しています。
GitHub Actions設定
ステージング環境へデプロイするGitHub Actionsのワークフローファイルを以下に記載します。developブランチにpushするとlightsailのステージング環境へデプロイします。
.github/workflows/deploy-staging.yml
name: Deploy to Staging
on: push: branches: [develop] workflow_dispatch:
env: AWS_REGION: ap-northeast-1 LIGHTSAIL_SERVICE_NAME: mysite-staging IMAGE_NAME: wordpress-staging DOMAIN_NAME: example.com CONTAINER_NAME: wordpress CONTAINER_PORT: 80
jobs: deploy: runs-on: ubuntu-latest environment: Staging
steps: - name: Set up locale for Japanese filenames run: | sudo apt-get update sudo apt-get install -y locales sudo locale-gen ja_JP.UTF-8 echo "LANG=ja_JP.UTF-8" >> $GITHUB_ENV echo "LC_ALL=ja_JP.UTF-8" >> $GITHUB_ENV echo "LANGUAGE=ja_JP:ja" >> $GITHUB_ENV
- name: Checkout code uses: actions/checkout@v4
- name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ env.AWS_REGION }}
- name: Install AWS CLI Lightsail plugin run: | curl "https://s3.us-west-2.amazonaws.com/lightsailctl/latest/linux-amd64/lightsailctl" -o "lightsailctl" sudo mv lightsailctl /usr/local/bin/lightsailctl sudo chmod +x /usr/local/bin/lightsailctl
- name: Build Docker image run: | export LANG=ja_JP.UTF-8 export LC_ALL=ja_JP.UTF-8 export LANGUAGE=ja_JP:ja docker build -t ${{ env.IMAGE_NAME }}:latest .
- name: Push image to Lightsail id: push-image run: | IMAGE_LABEL="${{ env.LIGHTSAIL_SERVICE_NAME }}" aws lightsail push-container-image \ --region ${{ env.AWS_REGION }} \ --service-name ${{ env.LIGHTSAIL_SERVICE_NAME }} \ --label $IMAGE_LABEL \ --image ${{ env.IMAGE_NAME }}:latest echo "image_label=$IMAGE_LABEL" >> $GITHUB_OUTPUT
- name: Create deployment files run: | cat > containers.json << EOF { "${{ env.CONTAINER_NAME }}": { "image": ":${{ env.LIGHTSAIL_SERVICE_NAME }}.${{ steps.push-image.outputs.image_label }}.latest", "environment": { "WORDPRESS_DB_HOST": "dummy", "WORDPRESS_DB_NAME": "dummy", "WORDPRESS_DB_USER": "dummy", "WORDPRESS_CONFIG_EXTRA": "define('WP_HOME', 'https://${{ env.DOMAIN_NAME }}'); define('WP_SITEURL', 'https://${{ env.DOMAIN_NAME }}'); define('WP_AUTO_UPDATE_CORE', false); define('WP_DEBUG_LOG', true); define('WP_DEBUG_DISPLAY', false);", "WORDPRESS_AUTH_KEY": "${{ secrets.WORDPRESS_AUTH_KEY }}", "WORDPRESS_SECURE_AUTH_KEY": "${{ secrets.WORDPRESS_SECURE_AUTH_KEY }}", "WORDPRESS_LOGGED_IN_KEY": "${{ secrets.WORDPRESS_LOGGED_IN_KEY }}", "WORDPRESS_NONCE_KEY": "${{ secrets.WORDPRESS_NONCE_KEY }}", "WORDPRESS_AUTH_SALT": "${{ secrets.WORDPRESS_AUTH_SALT }}", "WORDPRESS_SECURE_AUTH_SALT": "${{ secrets.WORDPRESS_SECURE_AUTH_SALT }}", "WORDPRESS_LOGGED_IN_SALT": "${{ secrets.WORDPRESS_LOGGED_IN_SALT }}", "WORDPRESS_NONCE_SALT": "${{ secrets.WORDPRESS_NONCE_SALT }}" }, "ports": { "${{ env.CONTAINER_PORT }}": "HTTP" } } } EOF
cat > public-endpoint.json << EOF { "containerName": "${{ env.CONTAINER_NAME }}", "containerPort": ${{ env.CONTAINER_PORT }}, "healthCheck": { "healthyThreshold": 2, "unhealthyThreshold": 2, "timeoutSeconds": 5, "intervalSeconds": 30, "path": "/", "successCodes": "200-499" } } EOF
- name: Deploy to Lightsail run: | aws lightsail create-container-service-deployment \ --region ${{ env.AWS_REGION }} \ --service-name ${{ env.LIGHTSAIL_SERVICE_NAME }} \ --containers file://containers.json \ --public-endpoint file://public-endpoint.json
- name: Get deployment status run: | aws lightsail get-container-services \ --region ${{ env.AWS_REGION }} \ --service-name ${{ env.LIGHTSAIL_SERVICE_NAME }}
- name: Notify deployment completion run: | echo "🚀 Staging deployment completed successfully!" echo "Site URL: https://${{ env.DOMAIN_NAME }}"簡単に説明すると、imageをbuildして、pushして、登録するだけです。秘密鍵などが必要になりますのでGitHub側に必要に応じて登録しておく必要があります。
環境変数の登録例

本番環境用のワークフロー
production側もほぼ同等です。
name: Deploy to Production
on: push: branches: [ main ] release: types: [ published ] workflow_dispatch:
env: AWS_REGION: ap-northeast-1 LIGHTSAIL_SERVICE_NAME: mysite-production IMAGE_NAME: wordpress-production DOMAIN_NAME: example.com CONTAINER_NAME: wordpress CONTAINER_PORT: 80
jobs: deploy: runs-on: ubuntu-latest environment: Production
steps: - name: Checkout code uses: actions/checkout@v4
- name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ env.AWS_REGION }}
- name: Install AWS CLI Lightsail plugin run: | curl "https://s3.us-west-2.amazonaws.com/lightsailctl/latest/linux-amd64/lightsailctl" -o "lightsailctl" sudo mv lightsailctl /usr/local/bin/lightsailctl sudo chmod +x /usr/local/bin/lightsailctl
- name: Build Docker image run: docker build -t ${{ env.IMAGE_NAME }}:latest .
- name: Push image to Lightsail id: push-image run: | IMAGE_LABEL="${{ env.LIGHTSAIL_SERVICE_NAME }}" aws lightsail push-container-image \ --region ${{ env.AWS_REGION }} \ --service-name ${{ env.LIGHTSAIL_SERVICE_NAME }} \ --label $IMAGE_LABEL \ --image ${{ env.IMAGE_NAME }}:latest echo "image_label=$IMAGE_LABEL" >> $GITHUB_OUTPUT
- name: Create deployment files run: | cat > containers.json << EOF { "${{ env.CONTAINER_NAME }}": { "image": ":${{ env.LIGHTSAIL_SERVICE_NAME }}.${{ steps.push-image.outputs.image_label }}.latest", "environment": { "WORDPRESS_DB_HOST": "dummy", "WORDPRESS_DB_NAME": "dummy", "WORDPRESS_DB_USER": "dummy", "WORDPRESS_CONFIG_EXTRA": "define('WP_HOME', 'https://${{ env.DOMAIN_NAME }}'); define('WP_SITEURL', 'https://${{ env.DOMAIN_NAME }}'); define('WP_AUTO_UPDATE_CORE', false); define('WP_DEBUG_LOG', false); define('WP_DEBUG_DISPLAY', false); define('SCRIPT_DEBUG', false); define('CONCATENATE_SCRIPTS', true);", "WORDPRESS_AUTH_KEY": "${{ secrets.WORDPRESS_AUTH_KEY }}", "WORDPRESS_SECURE_AUTH_KEY": "${{ secrets.WORDPRESS_SECURE_AUTH_KEY }}", "WORDPRESS_LOGGED_IN_KEY": "${{ secrets.WORDPRESS_LOGGED_IN_KEY }}", "WORDPRESS_NONCE_KEY": "${{ secrets.WORDPRESS_NONCE_KEY }}", "WORDPRESS_AUTH_SALT": "${{ secrets.WORDPRESS_AUTH_SALT }}", "WORDPRESS_SECURE_AUTH_SALT": "${{ secrets.WORDPRESS_SECURE_AUTH_SALT }}", "WORDPRESS_LOGGED_IN_SALT": "${{ secrets.WORDPRESS_LOGGED_IN_SALT }}", "WORDPRESS_NONCE_SALT": "${{ secrets.WORDPRESS_NONCE_SALT }}" }, "ports": { "${{ env.CONTAINER_PORT }}": "HTTP" } } } EOF
cat > public-endpoint.json << EOF { "containerName": "${{ env.CONTAINER_NAME }}", "containerPort": ${{ env.CONTAINER_PORT }}, "healthCheck": { "healthyThreshold": 2, "unhealthyThreshold": 2, "timeoutSeconds": 5, "intervalSeconds": 30, "path": "/", "successCodes": "200-499" } } EOF
- name: Deploy to Lightsail run: | aws lightsail create-container-service-deployment \ --region ${{ env.AWS_REGION }} \ --service-name ${{ env.LIGHTSAIL_SERVICE_NAME }} \ --containers file://containers.json \ --public-endpoint file://public-endpoint.json
- name: Get deployment status run: | aws lightsail get-container-services \ --region ${{ env.AWS_REGION }} \ --service-name ${{ env.LIGHTSAIL_SERVICE_NAME }}
- name: Notify deployment completion run: | echo "🚀 Production deployment completed successfully!" echo "Site URL: https://${{ env.DOMAIN_NAME }}"
release: needs: deploy runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Release Drafter uses: release-drafter/release-drafter@v6 with: publish: true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}ステージングと異なるところは、release-drafterを利用して本番へのデプロイのたびに自動的にリリースノートの作成と、タグを付けるようにしています。誰がいつどのように本番サイトを変更したかを記録することが可能になります。
AWS側の設定
前提条件
- AWSアカウントが作成済み
- AWS CLIがインストール済み
- GitHubリポジトリへのアクセス権限
IAMユーザーの作成
GitHub Actions用のIAMユーザーを作成します。
IAMユーザー作成
# AWS CLIでIAMユーザーを作成aws iam create-user --user-name github-actions-lightsail
# プログラマティックアクセス用のアクセスキーを作成aws iam create-access-key --user-name github-actions-lightsail必要な権限を付与
以下のポリシーをユーザーにアタッチします:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lightsail:*" ], "Resource": "*" } ]}ポリシーの作成とアタッチ:
# ポリシーファイルを作成cat > lightsail-policy.json << EOF{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lightsail:*" ], "Resource": "*" } ]}EOF
# ポリシーを作成aws iam create-policy \ --policy-name LightsailFullAccess \ --policy-document file://lightsail-policy.json
# AWSアカウントIDを取得ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
# ユーザーにポリシーをアタッチaws iam attach-user-policy \ --user-name github-actions-lightsail \ --policy-arn arn:aws:iam::${ACCOUNT_ID}:policy/LightsailFullAccessLightsail Container Service の作成
ステージング環境の作成
# ステージング用コンテナサービスを作成aws lightsail create-container-service \ --region ap-northeast-1 \ --service-name mysite-staging \ --power nano \ --scale 1本番環境の作成
# 本番用コンテナサービスを作成aws lightsail create-container-service \ --region ap-northeast-1 \ --service-name mysite-production \ --power nano \ --scale 1サービス状態の確認
# サービス一覧を確認aws lightsail get-container-services --region ap-northeast-1
# 特定のサービスの詳細を確認aws lightsail get-container-service \ --region ap-northeast-1 \ --service-name mysite-stagingカスタムドメインの設定
SSL証明書の作成
# ステージング用SSL証明書aws lightsail create-certificate \ --region ap-northeast-1 \ --certificate-name mysite-staging-cert \ --domain-name staging.example.com
# 本番用SSL証明書aws lightsail create-certificate \ --region ap-northeast-1 \ --certificate-name mysite-production-cert \ --domain-name example.comドメインの検証
証明書作成後、DNS検証が必要です。出力されたCNAMEレコードをDNSに追加してください。
カスタムドメインの有効化
# ステージング環境にカスタムドメインを設定aws lightsail attach-certificate-to-distribution \ --region ap-northeast-1 \ --certificate-name mysite-staging-cert
# 本番環境にカスタムドメインを設定aws lightsail attach-certificate-to-distribution \ --region ap-northeast-1 \ --certificate-name mysite-production-certGitHub Secrets の設定
GitHubリポジトリのSettings > Secrets and variables > Actionsで以下のSecretsを設定してください:
AWS認証情報
AWS_ACCESS_KEY_ID: 作成したIAMユーザーのアクセスキーIDAWS_SECRET_ACCESS_KEY: 作成したIAMユーザーのシークレットアクセスキー
WordPress認証キー
generatorなどで作成したキーを設定します。
WORDPRESS_AUTH_KEYWORDPRESS_SECURE_AUTH_KEYWORDPRESS_LOGGED_IN_KEYWORDPRESS_NONCE_KEYWORDPRESS_AUTH_SALTWORDPRESS_SECURE_AUTH_SALTWORDPRESS_LOGGED_IN_SALTWORDPRESS_NONCE_SALT
GitHub CLIを使用したSecrets登録
GitHub CLIを使用してコマンドラインからSecretsを登録できます:
# GitHub CLIのインストール(macOS)brew install gh
# GitHub CLIのインストール(Ubuntu/Debian)sudo apt install gh
# GitHubにログインgh auth login
# AWS認証情報を登録gh secret set AWS_ACCESS_KEY_ID --body "your-access-key-id"gh secret set AWS_SECRET_ACCESS_KEY --body "your-secret-access-key"
# WordPress認証キーを登録(.envファイルから)gh secret set WORDPRESS_AUTH_KEY --body "$(grep WORDPRESS_AUTH_KEY .env | cut -d'=' -f2 | tr -d '"')"gh secret set WORDPRESS_SECURE_AUTH_KEY --body "$(grep WORDPRESS_SECURE_AUTH_KEY .env | cut -d'=' -f2 | tr -d '"')"gh secret set WORDPRESS_LOGGED_IN_KEY --body "$(grep WORDPRESS_LOGGED_IN_KEY .env | cut -d'=' -f2 | tr -d '"')"gh secret set WORDPRESS_NONCE_KEY --body "$(grep WORDPRESS_NONCE_KEY .env | cut -d'=' -f2 | tr -d '"')"gh secret set WORDPRESS_AUTH_SALT --body "$(grep WORDPRESS_AUTH_SALT .env | cut -d'=' -f2 | tr -d '"')"gh secret set WORDPRESS_SECURE_AUTH_SALT --body "$(grep WORDPRESS_SECURE_AUTH_SALT .env | cut -d'=' -f2 | tr -d '"')"gh secret set WORDPRESS_LOGGED_IN_SALT --body "$(grep WORDPRESS_LOGGED_IN_SALT .env | cut -d'=' -f2 | tr -d '"')"gh secret set WORDPRESS_NONCE_SALT --body "$(grep WORDPRESS_NONCE_SALT .env | cut -d'=' -f2 | tr -d '"')"
# 登録されたSecretsの確認gh secret listDNS設定
Route53での設定
# ホストゾーンの作成(example.comが未作成の場合)aws route53 create-hosted-zone \ --name example.com \ --caller-reference $(date +%s)
# Aレコードの作成(Lightsailのパブリックドメインを指定)aws route53 change-resource-record-sets \ --hosted-zone-id YOUR_HOSTED_ZONE_ID \ --change-batch file://dns-records.json外部DNSプロバイダーでの設定
Lightsailコンテナサービスのパブリックドメインを確認:
aws lightsail get-container-service \ --region ap-northeast-1 \ --service-name mysite-production \ --query 'containerService.url'このURLをCNAMEレコードとして設定してください。
既存IAMユーザーへの権限追加
既にIAMユーザーが作成済みで、Lightsailのみを追加したい場合:
cat > lightsail-policy.json << EOF{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "lightsail:*" ], "Resource": "*" } ]}EOF
# Lightsail権限ポリシーを作成aws iam create-policy \ --policy-name LightsailContainerAccess \ --policy-document file://lightsail-policy.json
# AWSアカウントIDを取得ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)この環境が構築できれば、数クリックでスケールアウト可能な環境になります。

運用上のアドバイス
静的解析
PHP の syntax check や画像の圧縮、難読化をGitHub Actionsで行うことで面倒なことを自動化できます。
最適化をとことん突き詰めたい方は、WordPress のテーマファイルの中身をチェックし、JavaScript, CSS, の難読化や画像の圧縮を行えます。
Claude Codeの利用
Claude Code を利用すれば、GitHub issue で起票して、それを Claude Code で実装させ、pull request を作って、merge するといったことができます。 軽微な修正であればこれでできます。
例:

日本語ファイル名はアップロードはすべきではない
macOS で Docker compose を使う場合、アップロードするファイル名はアルファベットにする必要があります。以下の記事で指摘されている問題にあたってしまって Docker container 上からファイルを参照できなくなります。
まとめ
WordPress をGitリポジトリで管理してスナップショットを保存できるようにし、Lightsail Containerにデプロイする方法を説明しました。
これにより、複雑でスナップショット管理ができなかったWordPressの運用を容易にし、スケールアウト可能なインフラを構築することが可能になりました。
特に以下の点がめちゃくちゃ便利です:
- すべてファイルで管理できるので差分が明確
- ロールバックが簡単
- セキュリティリスクの大幅削減
- モダンな開発フローでの運用
おまけ
実際にこの構成で運用してみて感じたのは、WordPress の運用がこんなに楽になるのか! ということでした。特に複数環境での同期の煩わしさから解放されたのは大きいです。
将来的に PHP の Serverless が登場した際は低コストに運用できると思います。
月$7 という費用も、従来の WordPress 運用にかかる手間を考えるとコスパ使うべきではない言葉なので修正してくださいだと思います。ぜひ試してみてください!
引き続き、WordPress 周りの気になることを調査したり、実際の運用で得た知見も記事にしていきますので、良かったら ZennやTwitterのフォローをお願いします! 🙌