Cómo desplegar WordPress con Docker y PHP-FPM
Guía paso a paso para desplegar WordPress con Docker Compose usando el stack LEMP — PHP-FPM, Nginx, MySQL y Adminer — con volúmenes persistentes y límites de logs.
WordPress puede desplegarse de muchas formas — desde hosting administrado hasta instalación manual del stack LAMP/LEMP en un servidor. Hacerlo manualmente es lento y propenso a errores. Docker Compose soluciona eso: define todos los servicios en un archivo y el despliegue es reproducible.
Este tutorial usa el stack LEMP (Linux, Nginx, MySQL, PHP) con la imagen oficial de WordPress en modo PHP-FPM.
Requisitos previos
- Docker instalado: Instalar Docker en Ubuntu 20.04
- Docker Compose v2+
Servicios del stack
El docker-compose.yml define 4 servicios:
| Servicio | Imagen | Puerto |
|---|---|---|
| WordPress (PHP-FPM) | wordpress:fpm | 9000 (interno) |
| Nginx | nginx:alpine | 80 |
| MySQL | mysql:8.0 | 3306 (interno) |
| Adminer | adminer | 8080 |
docker-compose.yml
version: "3.8"
services:
wordpress:
image: wordpress:fpm
restart: unless-stopped
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wp_user
WORDPRESS_DB_PASSWORD: wp_password
WORDPRESS_DB_NAME: wordpress
volumes:
- wordpress_data:/var/www/html
- ./wp-content/plugins:/var/www/html/wp-content/plugins
- ./wp-content/themes:/var/www/html/wp-content/themes
- ./wp-content/uploads:/var/www/html/wp-content/uploads
depends_on:
- db
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
nginx:
image: nginx:alpine
restart: unless-stopped
ports:
- "80:80"
volumes:
- wordpress_data:/var/www/html:ro
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- wordpress
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
db:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wp_user
MYSQL_PASSWORD: wp_password
MYSQL_ROOT_PASSWORD: root_password
volumes:
- db_data:/var/lib/mysql
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
adminer:
image: adminer
restart: unless-stopped
ports:
- "8080:8080"
volumes:
wordpress_data:
db_data:nginx.conf
Nginx actúa como proxy inverso que recibe el HTTP y pasa las peticiones PHP al proceso PHP-FPM de WordPress en el puerto 9000:
server {
listen 80;
server_name localhost;
root /var/www/html;
index index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass wordpress:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires max;
log_not_found off;
}
}Estructura de directorios
wp-fpm-deploy/
├── docker-compose.yml
├── nginx.conf
└── wp-content/
├── plugins/ ← sincronizado con el contenedor
├── themes/ ← sincronizado con el contenedor
└── uploads/ ← sincronizado con el contenedorDespliegue
# Levantar todos los servicios en background
docker compose up -d
# Ver logs en tiempo real
docker compose logs -f
# Estado de los contenedores
docker compose psWordPress queda disponible en http://localhost. El instalador de WordPress aparece en el primer acceso. Adminer (gestor de base de datos) en http://localhost:8080.
Operaciones comunes
# Reiniciar un servicio específico
docker compose restart nginx
# Actualizar imágenes y reiniciar
docker compose pull && docker compose up -d
# Detener sin borrar volúmenes
docker compose stop
# Detener y borrar contenedores (datos en volúmenes se conservan)
docker compose down