platform/site-templates/profiles/wordpress/docker-compose.yml.j2
Bart Van Geyt edfb4c44b8 Phase 3: site templates & base images
Add the building blocks the provisioning CLI renders per site.

Base images (site-templates/images):
- php-fpm: non-root (www-data) php:<ver>-fpm-alpine with pdo_mysql, mysqli,
  gd, intl, zip, opcache, exif; tuned php.ini + pool; built per PHP version.
- nginx: hardened nginx:1.27-alpine with shared security + fastcgi snippets;
  per-site server block mounted at runtime.
- build.sh: build + Trivy-scan (+ optional push) for both images.

Profile templates (site-templates/profiles), Jinja2 rendered:
- static, redirect (tiny nginx 301/302), custom-php (nginx + our php-fpm,
  optional DB), wordpress (nginx + official wordpress-fpm, DB required,
  upload-exec denied). Only nginx carries Traefik labels and joins proxy;
  php-fpm uses the private <slug>_net and joins platform only when a DB is
  needed. Secrets stay in a git-ignored .env, not the compose.

CI: .forgejo/workflows/images.yml builds/scans images (gitleaks + Trivy).
README documents the render context and the Phase 4 web-root ownership item.

Templates validated: all profiles render to valid compose YAML across the
database on/off branches and single/multi-domain host rules.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 17:06:25 +02:00

53 lines
1.6 KiB
Django/Jinja

# Rendered by the provisioning CLI (Phase 4). WordPress always has a database.
# Uses the official WordPress php-fpm image; nginx serves it and proxies PHP.
name: {{ slug }}
services:
nginx:
image: {{ nginx_image }}
container_name: {{ slug }}_nginx
restart: unless-stopped
depends_on: [fpm]
volumes:
- {{ webroot }}:/var/www/html:ro
- ./nginx-site.conf:/etc/nginx/conf.d/default.conf:ro
networks: [proxy, site]
labels:
- "traefik.enable=true"
- "traefik.http.routers.{{ slug }}.rule=Host(`{{ domains | join('`) || Host(`') }}`)"
- "traefik.http.routers.{{ slug }}.entrypoints=websecure"
- "traefik.http.routers.{{ slug }}.tls.certresolver=le"
- "traefik.http.routers.{{ slug }}.middlewares=security-headers@file"
- "traefik.http.services.{{ slug }}.loadbalancer.server.port=80"
deploy:
resources:
limits:
cpus: "{{ resources.cpu }}"
memory: {{ resources.memory }}
fpm:
image: {{ wordpress_image }}
container_name: {{ slug }}_fpm
restart: unless-stopped
env_file: [.env]
environment:
WORDPRESS_DB_HOST: mariadb
WORDPRESS_DB_NAME: db_{{ slug_underscored }}
WORDPRESS_DB_USER: u_{{ slug_underscored }}
# WORDPRESS_DB_PASSWORD is injected from .env
volumes:
- {{ webroot }}:/var/www/html
networks: [site, platform]
deploy:
resources:
limits:
cpus: "{{ resources.cpu }}"
memory: {{ resources.memory }}
networks:
proxy:
external: true
platform:
external: true
site:
name: {{ slug }}_net