Back to Dashboard

wordpress

7.1.3-alpine

WordPress with PHP-FPM, multi-version retention, ARM-native. Pre-built and SBOM-attested.

Trust posture

πŸ“‹ SBOM ATTESTEDπŸ›‘ 0 open alertsπŸ— AMD64 + ARM64 πŸ”— 2/2 deps tracked daily πŸ” REPRODUCE THESE CHECKS LOCALLY
PULLS 14.4K 10293 to 14491 pulls across 30 recorded days 2026-09-18: 10293 pulls2026-09-19: 10307 pulls2026-09-20: 10698 pulls2026-09-21: 10893 pulls2026-09-22: 11084 pulls2026-09-23: 11502 pulls2026-09-24: 11519 pulls2026-09-25: 11980 pulls2026-09-26: 12455 pulls2026-09-27: 12472 pulls2026-09-28: 12613 pulls2026-09-29: 12650 pulls2026-09-30: 12767 pulls2026-10-01: 12918 pulls2026-10-02: 13118 pulls2026-10-03: 13274 pulls2026-10-04: 13308 pulls2026-10-05: 13308 pulls2026-10-06: 13309 pulls2026-10-07: 13469 pulls2026-10-08: 13474 pulls2026-10-09: 13998 pulls2026-10-10: 14240 pulls2026-10-11: 14240 pulls2026-10-12: 14294 pulls2026-10-13: 14322 pulls2026-10-14: 14416 pulls2026-10-15: 14453 pulls2026-10-16: 14459 pulls2026-10-17: 14491 pulls
STARS 0

VERIFIABLE TRUST ARTIFACTS

Provenance

Build commit
43b72a4
Build digest
sha256:329c1020dcf3cb81d8bd793c32af2036fd0d6edad8b96a78f2872bb6e598d18e
Index digest
sha256:5861a29dc2c9dce5e4e747278ab338d7701abc40424675a3b309af0da1763fb1
Manifest digest (amd64)
sha256:767ae7fe226978b52fa38593131d25b78d9c80bbbedfa9779fa25cab0d9a96f2
Manifest digest (arm64)
sha256:b6311990120b46f74fe8282da2642c9026f1ab0c7e99f0fdc992c90cc8591bdc
SBOM attestation
54423108…
Trivy evidence
Code Scanning fetched 2026-10-17 11:24 UTC
Verify
gh attestation verify oci://ghcr.io/oorabona/wordpress:7.1.3-alpine --owner oorabona guide β†’

Security evidence

Trivy Β· Code Scanning for image 7.1.3-alpine fetched 2026-10-17

0 open Code Scanning alerts Β· fetched 2026-10-17 Β· advisory mode (does not block builds)

Code Scanning: 0 open alerts Β· fetched 2026-10-17Recorded scan: 2 findings Β· scanned 2026-10-09
0Critical
0High
0Medium
0Low
0Info

No open Code Scanning alerts as of 2026-10-17.

Top advisories (upstream, advisory)

    β†’ See verification steps.

    Explore

    Build lineage329c1020dcf3
    Build Lineage
    Build Digest sha256:329c1020dcf3cb81d8bd793c32af2036fd0d6edad8b96a78f2872bb6e598d18e
    PHP_TAG latest
    WPCLI_VERSION 2.12.0
    WPCLI_KEY_FPR 63AF7AA15067C05616FDDD88A3A2E8F226F0BC06
    SQLITE_PLUGIN_VERSION 3.1.0
    VERSION 7.1.3-alpine
    MAJOR_VERSION 7
    REMOTE_CR ghcr.io/oorabona
    Package summary 80 packages
    Recent changes
    Build history 4 builds
    Dependency health all up to date

    Dependency Health

    all up to date
    2/2 dependencies monitored
    Up-to-date dependencies
    WPCLI_VERSION 2.12.0 SQLITE_PLUGIN_VERSION 3.1.0

    Documentation

    README

    WordPress

    Production-ready WordPress container built on PHP-FPM with WP-CLI, auto-install, and security hardening.

    Docker Hub GHCR Build

    Verify this image

    Every build ships a Sigstore-signed SBOM and a full Trivy scan β€” verify them yourself, no login required:

    gh attestation verify oci://ghcr.io/oorabona/wordpress:latest --owner oorabona
    

    Full walkthrough (SBOM payload, Trivy findings, multi-arch manifest inspection, upstream dependency tracking) β†’ https://oorabona.github.io/docker-containers/verify-images/

    Quick Start

    services:
      openresty:
        image: ghcr.io/oorabona/openresty:latest
        ports:
          - "8080:8080"
        volumes:
          - ./nginx.conf:/usr/local/openresty/nginx/conf/nginx.conf:ro
        depends_on:
          wordpress:
            condition: service_healthy
    
      wordpress:
        image: ghcr.io/oorabona/wordpress:latest
        volumes:
          - wp_uploads:/var/www/html/wp-content/uploads
        environment:
          WORDPRESS_DB_HOST: mariadb
          WORDPRESS_DB_NAME: wordpress
          WORDPRESS_DB_USER: wordpress
          WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_pass
          WP_AUTO_INSTALL: "true"
          WP_SITE_URL: "https://example.com"
          WP_SITE_TITLE: "My Site"
          WP_ADMIN_USER: admin
          WP_ADMIN_EMAIL: admin@example.com
          WP_ADMIN_PASSWORD_FILE: /run/secrets/admin_pass
          WP_LOCALE: fr_FR
          WP_TIMEZONE: "Europe/Paris"
          WP_PLUGINS: "redis-cache,wordfence"
        depends_on:
          mariadb:
            condition: service_healthy
        healthcheck:
          test: ["CMD-SHELL", "php-fpm -t"]
          interval: 10s
          timeout: 5s
          retries: 5
          start_period: 30s
        security_opt:
          - no-new-privileges:true
    
      mariadb:
        image: mariadb:11
        environment:
          MARIADB_ROOT_PASSWORD_FILE: /run/secrets/db_root_pass
          MARIADB_DATABASE: wordpress
          MARIADB_USER: wordpress
          MARIADB_PASSWORD_FILE: /run/secrets/db_pass
        volumes:
          - mariadb_data:/var/lib/mysql
        healthcheck:
          test: ["CMD-SHELL", "healthcheck.sh --connect --innodb_initialized"]
          interval: 10s
          timeout: 5s
          retries: 5
    
    volumes:
      mariadb_data:
      wp_uploads:
    

    With WP_AUTO_INSTALL=true, the site is fully operational on first boot β€” no setup wizard needed.

    Important: This container runs PHP-FPM on port 9000. It requires a reverse proxy (OpenResty, Nginx, Caddy) to serve HTTP traffic.

    Features

    • Auto-install β€” WordPress installs itself on first boot via wp-cli (idempotent)
    • Security hardened β€” DISALLOW_FILE_MODS, non-root user, no file editor
    • Built on PHP image β€” Inherits its PHP extensions (gd, mysqli, sodium, zip, apcu, OPcache) from ghcr.io/oorabona/php
    • WP-CLI included β€” Full command-line WordPress management
    • Docker secrets β€” All sensitive env vars support _FILE suffix
    • Alpine-based β€” Small image, fast startup

    Auto-Install

    When WP_AUTO_INSTALL=true is set, the entrypoint automatically:

    1. Generates wp-config.php from database env vars
    2. Injects security constants (DISALLOW_FILE_MODS, DISALLOW_FILE_EDIT, etc.)
    3. Runs wp core install with the provided site settings
    4. Sets locale and timezone (if configured)
    5. Configures SEO-friendly permalinks (/%postname%/)
    6. Installs and activates plugins from WP_PLUGINS list
    7. Disables search engine indexing (enable when ready via wp-admin)

    The process is idempotent β€” restarting the container skips installation if WordPress is already set up.

    Environment Variables

    Database (required)

    Variable Description Default
    WORDPRESS_DB_HOST Database hostname β€”
    WORDPRESS_DB_NAME Database name wordpress
    WORDPRESS_DB_USER Database username root
    WORDPRESS_DB_PASSWORD Database password β€”

    Auto-Install (optional)

    Variable Description Default
    WP_AUTO_INSTALL Enable auto-install on first boot false
    WP_SITE_URL Site URL (with protocol) http://localhost
    WP_SITE_TITLE Site title WordPress Site
    WP_ADMIN_USER Admin username admin
    WP_ADMIN_PASSWORD Admin password β€” (required)
    WP_ADMIN_EMAIL Admin email β€” (required)
    WP_LOCALE Site locale (e.g. fr_FR) β€”
    WP_TIMEZONE Timezone (e.g. Europe/Paris) β€”
    WP_PLUGINS Comma-separated plugin slugs β€”

    All variables support the _FILE suffix for Docker secrets (e.g. WP_ADMIN_PASSWORD_FILE).

    Build Arguments

    Argument Description Default
    REMOTE_CR Registry root for the base PHP image docker.io/oorabona
    PHP_TAG Tag of the base PHP-FPM image latest
    WPCLI_VERSION WP-CLI version 2.12.0
    WPCLI_KEY_FPR Pinned WP-CLI release-signing key fingerprint 63AF7AA15067C05616FDDD88A3A2E8F226F0BC06
    SQLITE_PLUGIN_VERSION SQLite Database Integration plugin version 2.2.23
    VERSION WordPress version latest

    Security Model

    Application Layer

    The auto-generated wp-config.php includes:

    define('DISALLOW_FILE_MODS', true);    // No plugin/theme install via wp-admin
    define('DISALLOW_FILE_EDIT', true);    // No code editor in wp-admin
    define('WP_AUTO_UPDATE_CORE', false);  // Updates via image rebuild
    define('AUTOMATIC_UPDATER_DISABLED', true);
    

    This means:

    • No file modifications through WordPress β€” plugins, themes, and core updates can only happen by rebuilding the container image
    • No code editor β€” the theme/plugin editor in wp-admin is disabled
    • Predictable state β€” what’s in the image is what runs

    Container Layer

    wordpress:
      security_opt:
        - no-new-privileges:true
      # After first successful boot, add:
      # read_only: true
      # tmpfs:
      #   - /tmp
      #   - /run
    

    Reverse Proxy Layer (OpenResty/Nginx)

    # Block PHP execution in uploads β€” critical security rule
    location ~* /wp-content/uploads/.*\.php$ {
        deny all;
    }
    
    # Block access to sensitive files
    location ~* /(wp-config\.php|readme\.html|license\.txt) {
        deny all;
    }
    
    # Block XML-RPC (unless needed)
    location = /xmlrpc.php {
        deny all;
    }
    
    # Rate limit wp-login.php
    location = /wp-login.php {
        limit_req zone=login burst=3 nodelay;
        # ... fastcgi_pass
    }
    

    Update Workflow

    Traditional WordPress updates files in-place (risky). This image uses an immutable approach:

    Plugin/theme/core update needed
      β†’ Update WP_PLUGINS env var or image tag
      β†’ docker compose pull && docker compose up -d
      β†’ Container restarts with new versions
      β†’ Database is persistent, no data loss
    

    Credential Management

    # Docker secrets (recommended)
    secrets:
      db_pass:
        file: ./secrets/db_password.txt
      admin_pass:
        file: ./secrets/admin_password.txt
    
    services:
      wordpress:
        environment:
          WORDPRESS_DB_PASSWORD_FILE: /run/secrets/db_pass
          WP_ADMIN_PASSWORD_FILE: /run/secrets/admin_pass
        secrets:
          - db_pass
          - admin_pass
    

    Volumes

    Path Description Notes
    /var/www/html/wp-content/uploads Media uploads Only writable volume needed

    WordPress core, plugins, and themes are baked into the image. Only the uploads directory needs persistent storage.

    WP-CLI Usage

    # Site info
    docker exec wordpress wp core version
    docker exec wordpress wp option get siteurl
    
    # Database
    docker exec wordpress wp db check
    docker exec wordpress wp db export /tmp/backup.sql
    
    # Users
    docker exec wordpress wp user list
    
    # Plugins (read-only β€” informational)
    docker exec wordpress wp plugin list
    docker exec wordpress wp plugin status
    

    Note: wp plugin install and wp theme install are blocked by DISALLOW_FILE_MODS. Plugin installation is done via the WP_PLUGINS env var or at image build time.

    Performance

    OPcache and the PHP resource limits come from the base image’s conf.d/php.ini; this image adds no tuning of its own. Read the values a given tag actually runs with rather than a copy of them:

    docker run --rm --entrypoint php ghcr.io/oorabona/wordpress:latest -r \
      'foreach (["memory_limit","upload_max_filesize","post_max_size",
                 "opcache.memory_consumption","opcache.max_accelerated_files",
                 "opcache.validate_timestamps"] as $k) printf("%s=%s\n", $k, ini_get($k));'
    

    opcache.validate_timestamps=0 is the one worth knowing about: PHP never re-checks a file’s mtime, so changed code is picked up on container restart, not on save. That is the intended behaviour for an immutable image.

    To override a setting, mount a .ini into /usr/local/etc/php/conf.d/ read-only:

    volumes:
      - ./php-overrides.ini:/usr/local/etc/php/conf.d/zz-overrides.ini:ro
    

    Two things that bite:

    • PHP reads that directory in alphabetical order and the base’s file is named php.ini, so an override has to sort after it. zz-overrides.ini applies. So does wordpress.ini, since p precedes w. What does not is anything sorting earlier β€” 00-overrides.ini, cli-tuning.ini, opcache-tuning.ini β€” which is read and then overwritten by the base, silently. Two files in this image were written that way and neither ever took effect.
    • :ro is not optional. A bind mount is writable by default, and this one is PHP configuration the interpreter obeys β€” a WordPress process that can rewrite it can change how PHP runs, permanently, across restarts.

    Architecture

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚         OpenResty / Nginx         β”‚  ← Reverse proxy, security headers,
    β”‚   (rate limiting, PHP block in    β”‚     PHP-in-uploads block
    β”‚    uploads, security headers)     β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚ fastcgi :9000
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚     WordPress (PHP-FPM)           β”‚  ← Read-only filesystem
    β”‚                                   β”‚     DISALLOW_FILE_MODS=true
    β”‚  wp-content/uploads/ β†’ volume     β”‚     Auto-install via wp-cli
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                    β”‚
    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚         MariaDB / MySQL           β”‚  ← All WordPress data lives here
    β”‚                                   β”‚     Persistent volume
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    

    Container Layers

    Alpine Linux
      └── PHP-FPM (from oorabona/php)
          β”œβ”€β”€ gd, mysqli, sodium, zip, apcu, OPcache
          └── WordPress
              β”œβ”€β”€ WordPress core (downloaded at build time)
              β”œβ”€β”€ WP-CLI
              β”œβ”€β”€ MariaDB client tools
              └── Auto-install entrypoint
    

    Database Backend

    This image is designed for MariaDB/MySQL, which is WordPress’s native and most battle-tested database backend.

    WordPress 6.4+ introduced experimental SQLite support via a drop-in plugin. A future lightweight variant could leverage SQLite for single-container deployments (dev environments, static-ish sites, edge hosting), eliminating the MariaDB dependency. This is not currently implemented.

    Building Locally

    # Build with default versions
    ./make build wordpress
    
    # Build with specific versions
    docker build \
      --build-arg REMOTE_CR=ghcr.io/oorabona \
      --build-arg PHP_TAG=latest \
      --build-arg WPCLI_VERSION=2.12.0 \
      --build-arg WPCLI_KEY_FPR=63AF7AA15067C05616FDDD88A3A2E8F226F0BC06 \
      --build-arg SQLITE_PLUGIN_VERSION=2.2.23 \
      --build-arg VERSION=6.9.1 \
      -t wordpress:custom .
    

    Dependencies

    Chained-base container: consumes ghcr.io/oorabona/php (project-produced). Docker Hub mirror at docker.io/oorabona/php (429-rate-limited; default local fallback).

    config.yaml declares source: /php β€” the leading-slash marker signals β€œchained-on-own-build”: sync writes to ghcr.io/<owner>/library/php (shared upstream mirror path), while reachability probing targets ghcr.io/<owner>/php (project’s published container). This ensures REMOTE_CR is injected only when the project-produced PHP image is available.

    Component Version Source Monitoring
    PHP latest oorabona/php Base image tag
    WP-CLI 2.12.0 wp-cli/wp-cli GitHub releases
    WordPress latest wordpress.org API