Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 75 additions & 29 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,54 +1,100 @@
# =============================
# === App Container Prefix ===
# =============================
# --------------------------------------------------
# Core application settings
# --------------------------------------------------

# Docker container name prefix
CONTAINER_NAME=app

# =============================
# === Database Configuration ===
# =============================
# --------------------------------------------------
# Database (MySQL)
# --------------------------------------------------

DATABASE_NAME=wordpress
DATABASE_USER=wp_user
DATABASE_PASSWORD=wp_password
DATABASE_ROOT_PASSWORD=root_password

# =============================
# === Nginx Configuration ===
# =============================
SERVER_NAME=localhost
HTTP_PORT=8000
# --------------------------------------------------
# Web / Nginx
# --------------------------------------------------

# =============================
# === phpMyAdmin Configuration ===
# =============================
PHPMYADMIN_PORT=8001
# Public server name (domain or hostname)
SERVER_NAME=localhost

# =============================
# === WordPress Initialization ===
# =============================
# --------------------------------------------------
# WordPress initialization (wp-init)
# --------------------------------------------------

# Skip WordPress initialization service (true/false)
# Skip WordPress initialization tasks (true/false)
SKIP_WP_INIT=false

# Full site URL
# Final site URL used by WordPress
# In production this should be: https://<SERVER_NAME>
SITE_URL=http://${SERVER_NAME}:${HTTP_PORT}

# Columns to skip during WP-CLI search-replace (comma-separated, no spaces)
# Example: guid,post_content
# Columns to skip during WP-CLI search-replace
# Comma-separated, no spaces (e.g. guid,post_content)
SKIP_COLUMNS=guid

# =============================
# === Database Backup Service ===
# =============================
# --------------------------------------------------
# Database backup service (db-backup)
# --------------------------------------------------

# Skip database backup service (true/false)
# Skip automated database backups (true/false)
SKIP_DB_BACKUP=false

# Maximum number of backup files to keep
DATABASE_BACKUP_MAX_FILES=3

# Initial delay before first backup (supports s/m/h/d)
# Examples: 60s, 5m, 2h, 1d
# Delay before first backup (s/m/h/d)
DATABASE_BACKUP_INITIAL_DELAY=60s

# Interval between backups (supports s/m/h/d)
# Interval between backups (s/m/h/d)
DATABASE_BACKUP_INTERVAL=3600s

# --------------------------------------------------
# Development only (docker-compose.dev.yml)
# --------------------------------------------------

# HTTP port exposed by Nginx
HTTP_PORT=8000

# phpMyAdmin exposed port
PHPMYADMIN_PORT=8001

# --------------------------------------------------
# Production only (docker-compose.prod.yml)
# --------------------------------------------------

# Maximum size of a single container log file
LOG_SIZE=10m

# Number of rotated log files to keep
LOG_FILES=3

# Database
DB_CPUS=1.0
DB_MEM_LIMIT=1024M

# WordPress
WP_CPUS=1.0
WP_MEM_LIMIT=512M

# Nginx
NGINX_CPUS=0.5
NGINX_MEM_LIMIT=128M

# wp-init (one-shot container)
WP_INIT_CPUS=0.5
WP_INIT_MEM_LIMIT=128M

# db-backup
DB_BACKUP_CPUS=0.5
DB_BACKUP_MEM_LIMIT=256M

# Certbot
# Email used for Let's Encrypt registration
LETSENCRYPT_EMAIL=admin@example.com

# Certbot renewal interval (s/m/h/d)
CERTBOT_RENEW_INTERVAL=12h
76 changes: 52 additions & 24 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,35 +1,63 @@
# Variables for compose files
COMPOSE_DEV := docker-compose -f docker-compose.yml -f docker-compose.dev.yml
# COMPOSE_PROD := docker-compose -f docker-compose.yml -f docker-compose.prod.yml
COMPOSE_DEV := docker compose -f docker-compose.yml -f docker-compose.dev.yml
COMPOSE_PROD := docker compose -f docker-compose.yml -f docker-compose.prod.yml

# Default compose (dev by default)
COMPOSE := $(COMPOSE_DEV)
# --------------------------------------------------
# Development targets
# --------------------------------------------------

# Primary targets
up:
@$(COMPOSE) up -d --build
up:
@$(COMPOSE_DEV) up -d --build

down:
@$(COMPOSE) down
down:
@$(COMPOSE_DEV) down

clean:
@$(COMPOSE) down -v

restart: down up
clean:
@$(COMPOSE_DEV) down -v

reset: clean up

logs:
@$(COMPOSE) logs -f
logs:
@$(COMPOSE_DEV) logs -f

sync-site-url:
@$(COMPOSE_DEV) exec -T wp-cli sh /scripts/wp-init/site-url/sync-site-url.sh

db-backup:
@$(COMPOSE_DEV) exec -T db-cli sh /scripts/db-backup/run-db-backup-once.sh

db-restore:
@$(COMPOSE_DEV) exec -T db-cli sh -c "/scripts/db-cli/run-db-restore.sh '$(SQLFILE)'"

# --------------------------------------------------
# Production targets
# --------------------------------------------------

up-prod:
@$(COMPOSE_PROD) up -d

down-prod:
@$(COMPOSE_PROD) down

logs-prod:
@$(COMPOSE_PROD) logs -f

# Dev-specific targets (requires containers to be running)
sync-site-url:
@$(COMPOSE) exec -T wp-cli sh /scripts/wp-init/site-url/sync-site-url.sh
certbot-first-issue:
@$(COMPOSE_PROD) run --rm \
--entrypoint sh \
certbot \
/scripts/certbot/certbot-first-issue/certbot-first-issue.sh

db-backup:
@$(COMPOSE) exec -T db-cli sh /scripts/db-backup/run-db-backup-once.sh
certbot-dry-run:
@$(COMPOSE_PROD) run --rm \
--entrypoint sh \
certbot \
/scripts/certbot/certbot-dry-run/certbot-dry-run.sh

db-restore:
@$(COMPOSE) exec -T db-cli sh -c "/scripts/db-cli/run-db-restore.sh '$(SQLFILE)'"
certbot-renew:
@$(COMPOSE_PROD) run --rm \
--entrypoint sh \
certbot \
/scripts/certbot/certbot-renew/certbot-renew.sh

.PHONY: up down clean restart reset logs sync-site-url db-backup db-restore
.PHONY: up down clean reset logs sync-site-url db-backup db-restore \
up-prod down-prod logs-prod certbot-first-issue certbot-dry-run certbot-renew
14 changes: 9 additions & 5 deletions docker-compose.dev.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
services:

Check warning on line 1 in docker-compose.dev.yml

View workflow job for this annotation

GitHub Actions / Docker Compose lint

1:1 [document-start] missing document start "---"
database:
volumes:
- ./db/init:/docker-entrypoint-initdb.d

wordpress:
volumes:
- ./src:/var/www/html/wp-content:rw
- ./php/zz-dev.ini:/usr/local/etc/php/conf.d/zz-dev.ini:ro
- ./src:/var/www/html/wp-content

nginx:
ports:
- "${HTTP_PORT:-8000}:80"
volumes:
- ./src:/var/www/html/wp-content:rw
- ./nginx/dev.conf.template:/etc/nginx/templates/default.conf.template:ro
- ./src:/var/www/html/wp-content

wp-init:
volumes:
- ./src:/var/www/html/wp-content:rw
- ./src:/var/www/html/wp-content
- ./scripts:/scripts:ro
entrypoint: ["/scripts/wp-init/entrypoint.sh"]

Expand All @@ -37,9 +41,9 @@
WORDPRESS_DB_PASSWORD: ${DATABASE_PASSWORD}
WORDPRESS_PATH: /var/www/html
volumes:
- wordpress:/var/www/html
- ./src:/var/www/html/wp-content:rw
- ./src:/var/www/html/wp-content
- ./scripts:/scripts:ro
- wordpress:/var/www/html
networks:
- internal
entrypoint: ["tail", "-f", "/dev/null"]
Expand Down
107 changes: 107 additions & 0 deletions docker-compose.prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
x-logging: &default-logging

Check warning on line 1 in docker-compose.prod.yml

View workflow job for this annotation

GitHub Actions / Docker Compose lint

1:1 [document-start] missing document start "---"
logging:
driver: json-file
options:
max-size: "${LOG_SIZE:-10m}"
max-file: "${LOG_FILES:-3}"

services:
database:
<<: *default-logging
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci
deploy:
resources:
limits:
cpus: '${DB_CPUS:-1.0}'
memory: ${DB_MEM_LIMIT:-1024M}

wordpress:
<<: *default-logging
init: true
security_opt:
- no-new-privileges:true
environment:
WORDPRESS_CONFIG_EXTRA: |
define('WP_ENVIRONMENT_TYPE', 'production');
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true);
volumes:
- ./php/zz-prod.ini:/usr/local/etc/php/conf.d/zz-prod.ini:ro
tmpfs:
- /tmp
deploy:
resources:
limits:
cpus: '${WP_CPUS:-1.0}'
memory: ${WP_MEM_LIMIT:-512M}

nginx:
<<: *default-logging
init: true
security_opt:
- no-new-privileges:true
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/prod.conf.template:/etc/nginx/templates/default.conf.template:ro
- certbot_conf:/etc/letsencrypt
- certbot_www:/var/www/certbot
deploy:
resources:
limits:
cpus: '${NGINX_CPUS:-0.5}'
memory: ${NGINX_MEM_LIMIT:-128M}

wp-init:
<<: *default-logging
restart: "no"
volumes:
- ./scripts:/scripts:ro
entrypoint: ["/scripts/wp-init/entrypoint.sh"]
deploy:
resources:
limits:
cpus: '${WP_INIT_CPUS:-0.5}'
memory: ${WP_INIT_MEM_LIMIT:-128M}

db-backup:
<<: *default-logging
restart: unless-stopped
volumes:
- ./scripts:/scripts:ro
- db_backups:/backups
entrypoint: ["/scripts/db-backup/entrypoint.sh"]
deploy:
resources:
limits:
cpus: '${DB_BACKUP_CPUS:-0.5}'
memory: ${DB_BACKUP_MEM_LIMIT:-256M}

certbot:
<<: *default-logging
image: certbot/certbot:v5.2.2
container_name: ${CONTAINER_NAME}-certbot
env_file: .env
environment:
SERVER_NAME: ${SERVER_NAME}
LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
CERTBOT_RENEW_INTERVAL: ${CERTBOT_RENEW_INTERVAL:-12h}
tmpfs:
- /var/lib/letsencrypt
volumes:
- ./scripts:/scripts:ro
- certbot_conf:/etc/letsencrypt
- certbot_www:/var/www/certbot
deploy:
resources:
limits:
cpus: '${CERTBOT_CPUS:-0.5}'
memory: ${CERTBOT_MEM_LIMIT:-128M}

volumes:
db_backups:
certbot_conf:
certbot_www:
7 changes: 2 additions & 5 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
services:

Check warning on line 1 in docker-compose.yml

View workflow job for this annotation

GitHub Actions / Docker Compose lint

1:1 [document-start] missing document start "---"
database:
container_name: ${CONTAINER_NAME}-database
image: mysql:8.4.7
Expand All @@ -16,7 +16,7 @@
timeout: 30s
retries: 10
volumes:
- dbdata:/var/lib/mysql
- db_data:/var/lib/mysql
networks:
- internal

Expand Down Expand Up @@ -46,10 +46,7 @@
env_file: .env
environment:
- SERVER_NAME=${SERVER_NAME}
ports:
- "${HTTP_PORT:-8000}:80"
volumes:
- ./nginx:/etc/nginx/templates:ro
- wordpress:/var/www/html
networks:
- internal
Expand Down Expand Up @@ -91,7 +88,7 @@
- internal

volumes:
dbdata:
db_data:
wordpress:

networks:
Expand Down
Loading