chore: initialize dockerized wordpress stack
This commit is contained in:
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
# Environment files
|
||||
.env
|
||||
.env.*
|
||||
*.env
|
||||
|
||||
# Local docker data volumes
|
||||
/db_data/
|
||||
/wordpress_data/
|
||||
/wordpress_data/wp-config.php
|
||||
/redis_data/
|
||||
|
||||
# WordPress exports / backups
|
||||
*.sql
|
||||
*.tar
|
||||
*.tar.gz
|
||||
*.tgz
|
||||
*.zip
|
||||
|
||||
# Editor / OS cruft
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Log files
|
||||
*.log
|
||||
48
README.md
Normal file
48
README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
# DigitechFlow WordPress Stack
|
||||
|
||||
This repository contains a hardened Docker Compose stack for the DigitechFlow WordPress deployment. It runs MySQL, WordPress (PHP-FPM), Nginx, and Valkey (Redis-compatible cache) with sensible defaults.
|
||||
|
||||
## Prerequisites
|
||||
- Docker Engine + Docker Compose V2
|
||||
- Traefik network (`traefik_default`) already present for routing/SSL
|
||||
- Host directories writable for `db_data/`, `wordpress_data/`, and `redis_data/`
|
||||
|
||||
## Getting Started
|
||||
1. Copy the environment template and fill in secrets:
|
||||
```bash
|
||||
cp .env.example .env
|
||||
# Edit .env to use strong unique values (DB creds, salts)
|
||||
```
|
||||
2. Bring up the stack:
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
3. Access WordPress via the configured Traefik domain (e.g., https://digitechflow.com).
|
||||
|
||||
## Services
|
||||
- **db**: `mysql:latest` with persistent volume `db_data/`.
|
||||
- **wordpress**: `wordpress:php8.3-fpm` serving PHP over FastCGI.
|
||||
- **wordpress_nginx**: `nginx:latest` front-end with custom config tuned for Traefik and FastCGI.
|
||||
- **redis**: `valkey/valkey:latest` for object caching with persistence and healthcheck.
|
||||
|
||||
## Configuration Highlights
|
||||
- Secrets and database settings sourced from `.env`; the template (`.env.example`) documents required keys.
|
||||
- `config/nginx/default.conf` contains gzip, caching, and FastCGI tuning. Adjust if you need custom routes.
|
||||
- `wordpress.ini` sets PHP limits and Opcache recommendations.
|
||||
- Local data directories (`db_data/`, `wordpress_data/`, `redis_data/`) plus `wp-config.php` are gitignored to prevent leaking content/secrets.
|
||||
|
||||
## Operations
|
||||
- Update images: `docker compose pull && docker compose up -d`.
|
||||
- View logs: `docker compose logs -f <service>`.
|
||||
- Run WordPress CLI tasks: `docker compose exec wordpress wp <command>` (install WP-CLI first if needed).
|
||||
|
||||
## Security Notes
|
||||
- Always use unique, strong passwords in `.env` and rotate them periodically.
|
||||
- Regenerate WordPress auth salts via https://api.wordpress.org/secret-key/1.1/salt/ and store them in `.env`.
|
||||
- Ensure Traefik enforces HTTPS and apply rate limiting/WAF middleware as needed.
|
||||
- Schedule backups (database dumps + `wordpress_data`) off-host; the stack does not include automated backups by default.
|
||||
|
||||
## Troubleshooting
|
||||
- Bad gateway from Nginx usually means PHP-FPM isn’t reachable; check `docker compose logs wordpress wordpress_nginx`.
|
||||
- If Compose warns about `version: '3'`, you can remove that line—it’s optional with Compose V2.
|
||||
- Ensure the Traefik network exists: `docker network ls | grep traefik_default`.
|
||||
49
config/nginx/default.conf
Normal file
49
config/nginx/default.conf
Normal file
@@ -0,0 +1,49 @@
|
||||
server {
|
||||
listen 80;
|
||||
server_name _;
|
||||
|
||||
root /var/www/html;
|
||||
index index.php index.html;
|
||||
|
||||
# Trust real client IPs forwarded by Traefik
|
||||
set_real_ip_from 172.19.0.0/16;
|
||||
set_real_ip_from 172.21.0.0/16;
|
||||
real_ip_header X-Forwarded-For;
|
||||
real_ip_recursive on;
|
||||
|
||||
# Basic compression for text assets
|
||||
gzip on;
|
||||
gzip_types text/plain text/css application/json application/javascript application/xml+rss image/svg+xml;
|
||||
gzip_comp_level 5;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ /index.php?$args;
|
||||
}
|
||||
|
||||
location ~ \.php$ {
|
||||
include fastcgi_params;
|
||||
fastcgi_pass wordpress:9000;
|
||||
fastcgi_index index.php;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||
fastcgi_param HTTP_X_FORWARDED_FOR $proxy_add_x_forwarded_for;
|
||||
fastcgi_param HTTP_X_FORWARDED_PROTO $http_x_forwarded_proto;
|
||||
fastcgi_param HTTPS $http_x_forwarded_proto;
|
||||
fastcgi_buffers 16 16k;
|
||||
fastcgi_buffer_size 32k;
|
||||
fastcgi_read_timeout 120s;
|
||||
fastcgi_send_timeout 120s;
|
||||
fastcgi_connect_timeout 60s;
|
||||
}
|
||||
|
||||
location ~* \.(?:css|js|jpg|jpeg|gif|png|svg|ico|webp|avif)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, no-transform";
|
||||
access_log off;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
client_max_body_size 64m;
|
||||
sendfile on;
|
||||
keepalive_timeout 65;
|
||||
}
|
||||
12
config/redis.conf
Normal file
12
config/redis.conf
Normal file
@@ -0,0 +1,12 @@
|
||||
# Persistent Valkey configuration tuned for WordPress object cache.
|
||||
appendonly yes
|
||||
appendfsync everysec
|
||||
save 900 1
|
||||
save 300 10
|
||||
save 60 10000
|
||||
maxmemory 256mb
|
||||
maxmemory-policy allkeys-lru
|
||||
protected-mode no
|
||||
bind 0.0.0.0
|
||||
port 6379
|
||||
dir /data
|
||||
99
docker-compose.yaml
Normal file
99
docker-compose.yaml
Normal file
@@ -0,0 +1,99 @@
|
||||
services:
|
||||
# MySQL Service
|
||||
db:
|
||||
image: mysql:latest
|
||||
container_name: digitechflow_db
|
||||
volumes:
|
||||
- ./db_data:/var/lib/mysql
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||
MYSQL_DATABASE: ${MYSQL_DATABASE}
|
||||
MYSQL_USER: ${MYSQL_USER}
|
||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
|
||||
networks:
|
||||
- wordpress_network
|
||||
healthcheck:
|
||||
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 10
|
||||
|
||||
# WordPress PHP-FPM Service
|
||||
wordpress:
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
image: wordpress:php8.3-fpm
|
||||
container_name: digitechflow_wordpress
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./wordpress_data:/var/www/html
|
||||
- ./wordpress.ini:/usr/local/etc/php/conf.d/wordpress.ini
|
||||
expose:
|
||||
- "9000"
|
||||
environment:
|
||||
WORDPRESS_DB_HOST: ${WORDPRESS_DB_HOST}
|
||||
WORDPRESS_DB_USER: ${WORDPRESS_DB_USER}
|
||||
WORDPRESS_DB_PASSWORD: ${WORDPRESS_DB_PASSWORD}
|
||||
WORDPRESS_DB_NAME: ${WORDPRESS_DB_NAME}
|
||||
WORDPRESS_REDIS_HOST: ${WORDPRESS_REDIS_HOST}
|
||||
networks:
|
||||
- wordpress_network
|
||||
extra_hosts:
|
||||
- "host.docker.internal:host-gateway" # For crowdsec plugin to connect to host crowdsec api
|
||||
# Nginx front-end for WordPress (Traefik faces this container)
|
||||
wordpress_nginx:
|
||||
depends_on:
|
||||
wordpress:
|
||||
condition: service_started
|
||||
image: nginx:latest
|
||||
container_name: digitechflow_nginx
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./wordpress_data:/var/www/html:ro
|
||||
- ./config/nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
|
||||
networks:
|
||||
- wordpress_network
|
||||
- traefik_default
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.digitechflow.rule=Host(`digitechflow.com`)"
|
||||
- "traefik.http.routers.digitechflow.entrypoints=websecure"
|
||||
- "traefik.http.routers.digitechflow.middlewares=crowdsec@file,retry-fast@file"
|
||||
- "traefik.http.routers.digitechflow.tls.certresolver=letsencrypt"
|
||||
- "traefik.http.services.digitechflow.loadbalancer.server.port=80"
|
||||
- "traefik.http.services.digitechflow.loadbalancer.serversTransport=fast-upstreams@file"
|
||||
- "traefik.docker.network=traefik_default"
|
||||
|
||||
redis:
|
||||
image: valkey/valkey:latest
|
||||
container_name: digitechflow_valkey
|
||||
restart: unless-stopped
|
||||
volumes:
|
||||
- ./redis_data:/data
|
||||
- ./config/redis.conf:/usr/local/etc/redis/redis.conf:ro
|
||||
command: ["valkey-server", "/usr/local/etc/redis/redis.conf"]
|
||||
networks:
|
||||
- wordpress_network
|
||||
healthcheck:
|
||||
test: ["CMD", "redis-cli", "ping"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
# Volumes for persistent data
|
||||
volumes:
|
||||
db_data:
|
||||
wordpress_data:
|
||||
redis_data:
|
||||
|
||||
# Network for communication between services
|
||||
networks:
|
||||
wordpress_network:
|
||||
driver: bridge
|
||||
ipam:
|
||||
config:
|
||||
- subnet: 172.21.0.0/16
|
||||
gateway: 172.21.0.1
|
||||
traefik_default:
|
||||
external: true # Assumes Traefik uses an existing network
|
||||
12
wordpress.ini
Normal file
12
wordpress.ini
Normal file
@@ -0,0 +1,12 @@
|
||||
file_uploads = On
|
||||
memory_limit = 512M
|
||||
upload_max_filesize = 64M
|
||||
post_max_size = 64M
|
||||
max_execution_time = 300
|
||||
max_input_time = 1000
|
||||
; Opcache tuning for better PHP-FPM performance
|
||||
opcache.enable=1
|
||||
opcache.memory_consumption=192
|
||||
opcache.interned_strings_buffer=16
|
||||
opcache.max_accelerated_files=10000
|
||||
opcache.validate_timestamps=0
|
||||
Reference in New Issue
Block a user