Skip to content

Run WordPress on Google Cloud Run — no MySQL, no persistent disk, no fuss.

License

Notifications You must be signed in to change notification settings

ku-suke/wordpress-serverless-cloudrun

Repository files navigation

wordpress-serverless-cloudrun

Run WordPress on Google Cloud Run — no MySQL, no persistent disk, no fuss.

This project combines SQLite, Litestream, and GCS FUSE to run WordPress as a truly stateless container. Everything is managed through Composer, deployed with a single script, and designed to be secure, low-cost, and low-maintenance.

✨ Project Goals

  • 🚫 No MySQL — Uses the official SQLite Database Integration plugin
  • 📦 Composer-managed WordPress — Core, plugins, and themes are all declared in composer.json
  • 🪣 GCS FUSE for media — Uploaded files are stored in a GCS bucket, not on local disk
  • 🔄 Litestream for durability — SQLite is continuously replicated to GCS, restored on cold start
  • FrankenPHP — Fast cold-start spin-up, ideal for serverless containers
  • 🏗️ Single-command deploy — One script builds images and deploys to Cloud Run
  • 💰 Cost-effective — No always-on database servers; pay only for what you use

🏛️ Architecture

┌─────────────────────── Cloud Run Service ───────────────────────┐
│                                                                  │
│  ┌──────────────┐    shared volume     ┌───────────────────┐    │
│  │  WordPress    │◄──── (in-memory) ───►│  Litestream       │    │
│  │  FrankenPHP   │     /data/db.sqlite  │  (sidecar)        │    │
│  │  + SQLite     │                      │  restore → watch  │    │
│  └──────┬───────┘                      └─────────┬─────────┘    │
│         │                                         │              │
└─────────┼─────────────────────────────────────────┼──────────────┘
          │                                         │
          ▼                                         ▼
   ┌─────────────┐                          ┌─────────────┐
   │  GCS Bucket  │                          │  GCS Bucket  │
   │  (media)     │                          │  (db backup) │
   └─────────────┘                          └─────────────┘

How it works:

  1. On container startup, the Litestream sidecar restores the latest SQLite snapshot from GCS.
  2. Once the database is ready, the WordPress container starts serving requests via FrankenPHP.
  3. New uploads are written directly to GCS through GCS FUSE — no local storage needed.
  4. Litestream continuously replicates SQLite changes to GCS, so the container stays stateless.

📋 Prerequisites

  • Google Cloud SDK (gcloud)
  • A GCP project with billing enabled
  • Two GCS buckets — one for media uploads, one for database backups
  • Docker (for local development)

📁 Project Structure

├── composer.json              # WordPress core + plugins + themes
├── wp-config.php              # WordPress configuration (reads env vars)
├── Dockerfile                 # Multi-stage: Composer build → FrankenPHP
├── docker-compose.yml         # Local development environment
├── .env.example               # Template for environment variables
├── themes/                    # Custom themes go here
└── cloudrun/
    ├── deploy.sh              # One-command build & deploy script
    ├── cloudbuild.yaml        # Cloud Build pipeline definition
    ├── service.yaml           # Cloud Run service template (Knative)
    ├── Dockerfile.litestream  # Litestream sidecar image
    ├── litestream.yml         # Litestream replication config
    └── start-litestream.sh    # Entrypoint: restore then replicate

🚀 Quick Start (Local)

Run WordPress locally with Docker Compose:

# Edit docker-compose.yml — for local dev, only AUTH_KEY…NONCE_SALT are needed

docker compose up

Visit http://localhost:8080 to complete the WordPress setup wizard.

Note: Locally, SQLite data is stored in local-wp-data/ and GCS FUSE is not used.

☁️ Deploy to Cloud Run

1. Configure environment variables

cp .env.example .env

Edit .env with your GCP project details:

Variable Description
PROJECT_ID Your GCP project ID
MEDIA_BUCKET GCS bucket name for media uploads
DB_BUCKET GCS bucket name for SQLite backups
WP_HOME Your site URL (e.g., https://example.com)

2. Create required GCP resources

source .env

# Create Artifact Registry repository (one-time)
gcloud artifacts repositories create "$REPOSITORY" \
  --repository-format=docker \
  --location="$REGION" \
  --project="$PROJECT_ID"

# Create GCS buckets (one-time)
gcloud storage buckets create "gs://$MEDIA_BUCKET" --project="$PROJECT_ID" --location="$REGION"
gcloud storage buckets create "gs://$DB_BUCKET" --project="$PROJECT_ID" --location="$REGION"

3. Deploy

bash cloudrun/deploy.sh

The deploy script will:

  1. Load your .env configuration
  2. Generate WordPress auth salts (or reuse cached salts from cloudrun/wp-salts.env)
  3. Build the WordPress and Litestream container images via Cloud Build
  4. Deploy the service to Cloud Run using the Knative template

Safety: The script validates that all placeholder values have been replaced before deploying. Running with default .env.example values will exit with an error.

🎨 Customizing WordPress

Add a plugin

Add it to composer.json via WordPress Packagist:

composer require wpackagist-plugin/your-plugin-name

Add a theme

composer require wpackagist-theme/your-theme-name

Or place custom theme files in the themes/ directory — they are copied into the image at build time.

Change WordPress version

Update the version constraint in composer.json:

"johnpbloch/wordpress": "^6.9"

Then run composer update and redeploy.

🔧 Configuration Reference

WordPress auth salts

The deploy script handles salts automatically:

  • Option A: Define AUTH_KEY through NONCE_SALT directly in .env — useful when sharing salts with local Docker Compose
  • Option B: Leave them empty — deploy.sh will fetch salts from the WordPress API and cache them in cloudrun/wp-salts.env

Composer-managed immutable mode

This project is configured for immutable operations:

  • DISALLOW_FILE_MODS is enabled in wp-config.php
  • Update checks for WordPress core/plugins/themes are disabled via MU plugin

Apply all WordPress/plugin/theme updates through composer.json + image rebuild/redeploy.

Cloud Run service settings

Key settings in cloudrun/service.yaml:

Setting Purpose
cpu-throttling: "false" Keeps CPU allocated so Litestream can flush writes immediately
container-dependencies Ensures Litestream restores the DB before WordPress starts
execution-environment: gen2 Required for GCS FUSE support

Important files not committed

These files are in .gitignore:

  • .env — your project-specific configuration
  • cloudrun/wp-salts.env — generated auth salts

🤝 Contributing

Contributions are welcome! Please open an issue or submit a pull request.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📄 License

This project is open source and available under the MIT License.

About

Run WordPress on Google Cloud Run — no MySQL, no persistent disk, no fuss.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published