# Sirius Press — a complete self-hosted stack. # # Three containers: MariaDB, PHP-FPM with the patched WordPress baked in, and # nginx in front. Only nginx is published. # # The volume layout is the part worth reading. WordPress core lives in the # image, not in a volume, so `docker compose build --pull && up -d` genuinely # upgrades it — the usual arrangement, where the whole document root is a # volume, freezes core at whatever version first created the volume and turns # every security release into a manual migration. What people actually need to # keep — uploads, plugins and themes they installed, and wp-config.php — is # what gets a volume. # # cp .env.example .env # then edit it # docker compose up -d name: sirius-press services: db: image: mariadb:11.4 restart: unless-stopped environment: MARIADB_DATABASE: ${DB_NAME:-wordpress} MARIADB_USER: ${DB_USER:-wordpress} MARIADB_PASSWORD: ${DB_PASSWORD:?set DB_PASSWORD in .env} MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD:?set DB_ROOT_PASSWORD in .env} MARIADB_AUTO_UPGRADE: "1" command: # utf8mb4 throughout: a post containing an emoji should not be a # database error, and WordPress has assumed this for years. - --character-set-server=utf8mb4 - --collation-server=utf8mb4_unicode_ci volumes: - db:/var/lib/mysql healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] interval: 10s timeout: 5s retries: 12 app: build: context: .. dockerfile: docker/Dockerfile args: # install.sh copies these out of tools/wordpress.lock into .env. # Defaults are pinned here too, so a plain `docker compose build` # cannot quietly drift onto a different core. WP_VERSION: ${WP_VERSION:-7.1.1} WP_URL: ${WP_URL:-https://wordpress.org/wordpress-7.1.1.tar.gz} WP_SHA256: ${WP_SHA256:-3996fee13448ef12e07e9f0c77db2f655ffa1b7cde71c80a4965d3bf1fb956b3} restart: unless-stopped depends_on: db: condition: service_healthy environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_NAME: ${DB_NAME:-wordpress} WORDPRESS_DB_USER: ${DB_USER:-wordpress} WORDPRESS_DB_PASSWORD: ${DB_PASSWORD:?set DB_PASSWORD in .env} WORDPRESS_SITE_URL: ${SITE_URL:-} WORDPRESS_DEBUG: ${WP_DEBUG:-false} SIRIUS_PRESS_KEY: ${SIRIUS_PRESS_KEY:-} volumes: - config:/var/www/config # The document root is a volume so nginx can read the same files. It is # refilled from the image on every start, so this does not pin core. - core:/var/www/html - uploads:/var/www/html/wp-content/uploads - plugins:/var/www/html/wp-content/plugins - themes:/var/www/html/wp-content/themes web: image: nginx:1.27-alpine restart: unless-stopped depends_on: - app ports: - "${HTTP_PORT:-80}:80" volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro # nginx serves static files directly and only proxies PHP, so it needs # to see the same tree. Read-only: the web tier has no business writing. - core:/var/www/html:ro - uploads:/var/www/html/wp-content/uploads:ro - plugins:/var/www/html/wp-content/plugins:ro - themes:/var/www/html/wp-content/themes:ro volumes: db: config: core: uploads: plugins: themes: