4703 文字
24 分

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 = 200M
upload_max_filesize = 200M

environment セクション#

環境変数である environment について説明します。

以下の設定はSQLiteなので不要なのですが、WordPress側が公式にサポートしていないということもあり何かしらの値を設定する必要があるのでダミーの文字列を設定しています。ちょっとかっこ悪いですがこれがないと動きません😅

WORDPRESS_DB_HOST: dummy
WORDPRESS_DB_NAME: dummy
WORDPRESS_DB_USER: dummy

WordPressのデータベース上には自分のサイトのURLを記録する必要がありますが、それを環境ごとに外部から指定するために上の2つの環境変数を設定します。本番環境では、プラグインなどの自動更新は不要なので、WP_AUTO_UPDATE_COREfalse にします。また、ローカルといった開発環境ではデバッグ関連の出力を多く出すために WP_DEBUG_LOGWP_DEBUG_DISPLAYtrue にします。

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=501
GID=20
WP_HOME="http://localhost:8080"

その他のファイル#

db.php ファイルはこちらのファイルです。

Makefile にはこちらののような内容を入れています。なくてもよいのですが、docker関連の地味な権限周りの修正などを行うためにあったほうが楽です。

起動方法#

一通りファイルを揃えて、以下のコマンドを打てば立ち上がるはずです。

Terminal window
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-8
ENV LANGUAGE=ja_JP:ja
ENV 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ユーザー作成#

Terminal window
# 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": "*"
}
]
}

ポリシーの作成とアタッチ:

Terminal window
# ポリシーファイルを作成
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/LightsailFullAccess

Lightsail Container Service の作成#

ステージング環境の作成#

Terminal window
# ステージング用コンテナサービスを作成
aws lightsail create-container-service \
--region ap-northeast-1 \
--service-name mysite-staging \
--power nano \
--scale 1

本番環境の作成#

Terminal window
# 本番用コンテナサービスを作成
aws lightsail create-container-service \
--region ap-northeast-1 \
--service-name mysite-production \
--power nano \
--scale 1

サービス状態の確認#

Terminal window
# サービス一覧を確認
aws lightsail get-container-services --region ap-northeast-1
# 特定のサービスの詳細を確認
aws lightsail get-container-service \
--region ap-northeast-1 \
--service-name mysite-staging

カスタムドメインの設定#

SSL証明書の作成#

Terminal window
# ステージング用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に追加してください。

カスタムドメインの有効化#

Terminal window
# ステージング環境にカスタムドメインを設定
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-cert

GitHub Secrets の設定#

GitHubリポジトリのSettings > Secrets and variables > Actionsで以下のSecretsを設定してください:

AWS認証情報#

  • AWS_ACCESS_KEY_ID: 作成したIAMユーザーのアクセスキーID
  • AWS_SECRET_ACCESS_KEY: 作成したIAMユーザーのシークレットアクセスキー

WordPress認証キー#

generatorなどで作成したキーを設定します。

  • WORDPRESS_AUTH_KEY
  • WORDPRESS_SECURE_AUTH_KEY
  • WORDPRESS_LOGGED_IN_KEY
  • WORDPRESS_NONCE_KEY
  • WORDPRESS_AUTH_SALT
  • WORDPRESS_SECURE_AUTH_SALT
  • WORDPRESS_LOGGED_IN_SALT
  • WORDPRESS_NONCE_SALT

GitHub CLIを使用したSecrets登録#

GitHub CLIを使用してコマンドラインからSecretsを登録できます:

Terminal window
# 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 list

DNS設定#

Route53での設定#

Terminal window
# ホストゾーンの作成(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コンテナサービスのパブリックドメインを確認:

Terminal window
aws lightsail get-container-service \
--region ap-northeast-1 \
--service-name mysite-production \
--query 'containerService.url'

このURLをCNAMEレコードとして設定してください。

既存IAMユーザーへの権限追加#

既にIAMユーザーが作成済みで、Lightsailのみを追加したい場合:

Terminal window
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 周りの気になることを調査したり、実際の運用で得た知見も記事にしていきますので、良かったら ZennTwitterのフォローをお願いします! 🙌

WordPressをSQLite対応してGitで管理し、AWS Lightsail Containerへデプロイする構成
https://blog.teraren.com/posts/wordpress-sqlite-repository-lightsail/
作者
Yuki Matsukura
公開日
2025-06-06
ライセンス
CC BY-NC-SA 4.0
この記事が役に立ったら
GitHub Sponsorsで応援できます

コメント