ToolsOps

Docker Compose para WordPress + MariaDB

WordPress con MariaDB en Docker Compose para desarrollo local: dos volúmenes (base de datos y archivos con tus uploads), .env.example, healthcheck de MariaDB y cómo resolver el error de conexión a la base de datos.

Levantar WordPress en local es una de las cosas para las que Docker Compose brilla: en un par de minutos tienes WordPress y su base de datos sin tocar tu sistema. Esta guía monta WordPress con MariaDB y se centra en dos cosas que la gente acaba lamentando si las ignora: los volúmenes y el error de conexión a la base de datos.

compose.yaml de WordPress + MariaDB

services:
  wordpress:
    image: wordpress:6-php8.3-apache
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
    environment:
      WORDPRESS_DB_HOST: "mariadb:3306"
      WORDPRESS_DB_NAME: ${MARIADB_DATABASE}
      WORDPRESS_DB_USER: ${MARIADB_USER}
      WORDPRESS_DB_PASSWORD: ${MARIADB_PASSWORD}
    volumes:
      - wordpress_data:/var/www/html
    depends_on:
      mariadb:
        condition: service_healthy
  mariadb:
    image: mariadb:11
    restart: unless-stopped
    environment:
      MARIADB_DATABASE: ${MARIADB_DATABASE}
      MARIADB_USER: ${MARIADB_USER}
      MARIADB_PASSWORD: ${MARIADB_PASSWORD}
      MARIADB_ROOT_PASSWORD: ${MARIADB_ROOT_PASSWORD}
    volumes:
      - mariadb_data:/var/lib/mysql
    healthcheck:
      test: ["CMD-SHELL", "healthcheck.sh --connect --innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 20s

volumes:
  wordpress_data:
  mariadb_data:

El .env.example:

MARIADB_DATABASE=wordpress
MARIADB_USER=wordpress
MARIADB_PASSWORD=CHANGE_ME
MARIADB_ROOT_PASSWORD=CHANGE_ME

Levántalo con docker compose up -d y abre http://localhost:8080 para el instalador de WordPress.

Dos volúmenes, dos cosas que persistir

Es fácil acordarse del volumen de la base de datos y olvidar el de WordPress. Necesitas los dos:

  • mariadb_data guarda la base de datos: entradas, páginas, usuarios, opciones y configuración.
  • wordpress_data guarda los archivos en /var/www/html: el núcleo de WordPress, los plugins y temas que instales y, sobre todo, tus subidas en wp-content/uploads.

Si te faltara wordpress_data, perderías las imágenes subidas aunque la base de datos quedara intacta: las entradas apuntarían a archivos que ya no existen.

"Error establishing a database connection"

Es el mensaje que más asusta y casi siempre es una de estas tres causas:

  • Host equivocado. WORDPRESS_DB_HOST debe ser mariadb:3306, el nombre del servicio, no localhost.
  • Credenciales que no coinciden. El usuario, la contraseña y el nombre de base de datos de WordPress deben ser los mismos que los de MariaDB. Por eso ambos servicios leen las mismas variables del .env.
  • MariaDB aún no estaba lista. El healthcheck de MariaDB (healthcheck.sh --connect --innodb_initialized) más depends_on: condition: service_healthy hacen que WordPress espere a que la base de datos acepte conexiones, lo que evita el fallo en el primer arranque.

Reiniciar y empezar de cero

docker compose ps                 # ¿están healthy?
docker compose logs -f wordpress  # logs del instalador
docker compose down               # para (datos a salvo)
docker compose down -v            # borra DB y archivos de WordPress

Recuerda que down -v aquí borra los dos volúmenes: pierdes la base de datos y tus uploads. Es lo que quieres para reinstalar limpio, no para un mantenimiento rutinario.

Local, no producción

Este stack es para desarrollar y probar en tu equipo. No es un despliegue endurecido: un WordPress de cara a Internet necesita HTTPS, backups de la base de datos y de los uploads, contraseñas fuertes fuera de git, y actualizaciones constantes de WordPress y sus plugins. Trátalo como un sitio de pruebas desechable.

Siguientes pasos

Genera este stack en el generador de Docker Compose y vuelve al índice de ejemplos para ver otros stacks.

Preguntas frecuentes

Me sale 'Error establishing a database connection', ¿qué reviso?
Lo más común: WORDPRESS_DB_HOST debe ser mariadb:3306 (el nombre del servicio y su puerto interno), no localhost. Después, que las credenciales de WordPress coincidan exactamente con las de MariaDB (mismo usuario, misma contraseña, misma base de datos en el .env). Y que MariaDB haya terminado de inicializar: con el healthcheck y depends_on: condition: service_healthy, WordPress espera a que esté lista, lo que evita el error en el primer arranque.
¿Por qué hay dos volúmenes?
Porque hay dos cosas distintas que persistir. mariadb_data guarda la base de datos (entradas, usuarios, opciones). wordpress_data guarda los archivos de WordPress en /var/www/html, que incluyen tus subidas (wp-content/uploads) y los plugins o temas que instales. Si te faltara el volumen de WordPress, perderías las imágenes subidas aunque la base de datos siguiera intacta.
Cambié la contraseña de MariaDB y dejó de conectar, ¿por qué?
Igual que con Postgres: MariaDB solo crea el usuario y la base de datos la primera vez, con el volumen vacío. Si ya arrancó antes, mariadb_data conserva las credenciales originales y las variables nuevas se ignoran. Para desarrollo, docker compose down -v borra los volúmenes y reinicia limpio (también borra tu contenido de WordPress). Si quieres conservar datos, cambia la contraseña por SQL y actualiza el .env.
¿Necesito publicar el puerto de MariaDB?
No. WordPress llega a MariaDB por la red interna (mariadb:3306), así que la base de datos no publica ningún puerto. Solo WordPress publica un puerto, y atado a 127.0.0.1:8080 para que el sitio sea accesible desde tu navegador sin abrirlo a la red.
¿Puedo usar esto en producción?
No tal cual. Es un entorno de desarrollo y pruebas. Un WordPress de producción necesita HTTPS, backups de la base de datos y de los uploads, contraseñas fuertes fuera de git, actualizaciones de WordPress y plugins, y endurecimiento del servidor. Aquí el objetivo es tener WordPress funcionando en local en un par de minutos, no un sitio expuesto a Internet.