Divendres, octubre 17, 2025
VIRTUALITZACIÓ

Com fer servir Docker per a aixecar serveis bàsics (Nginx, MariaDB, WordPress)

Treballar amb serveis web sovint implica lidiar amb configuracions, dependències, actualitzacions i, de vegades, errors que semblen trets d’una altra dimensió. No importa si vens d’un entorn de hosting compartit, d’entorns on-premise més clàssics o si simplement estàs donant les teves primeres passes a Linux. En tots els casos, Docker pot ajudar a reduir la fricció.

Perquè Docker

Docker no fa màgia, però et treu de sobre moltes de les tasques repetitives o propenses a trencar-se: versions del sistema, instal·lació de dependències, conflictes entre serveis… No reemplaça el coneixement de com funciona Linux per sota, però permet enfocar-te en que el servei estigui disponible sense necessitat de resoldre problemes que no aporten valor en aquell moment.

En entorns personals, de proves o fins i tot en producció ben continguda, muntar serveis amb Docker pot ser molt més estable que fer-ho directament sobre el sistema base.

Això sí, Docker també té trampes comunes: volums mal muntats, xarxes mal enteses, dades volàtils que desapareixen després d’un docker rm, contenidors que “funcionen” fins que necessites canviar-los. La idea és evitar aquests errors des del principi.

L’escenari

Volem aixecar tres serveis bàsics:

  1. Nginx actuant com a proxy revers
  2. MariaDB com a base de dades
  3. WordPress com a aplicació web

Tot ha de córrer en contenidors separats, però comunicar-se entre si com si estiguessin en el mateix servidor. I ha de persistir la informació (res de perdre el contingut del blog cada vegada que reinicies un contenidor).

Fem servir docker-compose perquè descriu tota la pila de manera llegible, replicable i menys propensa a errors que córrer comandes docker run a mà.

Estructura del projecte

Primer, armem un directori de treball bàsic amb la següent estructura:

wordpress-docker/
│
├── docker-compose.yml
├── nginx/
│   └── default.conf
└── data/
    ├── db/ (volum persistent per a MariaDB)
    └── wp/ (volum persistent per a WordPress)

Això no és obligatori, però tenir-ho organitzat des del principi t’estalvia recerques més endavant.

L’arxiu docker-compose.yml

Aquí va un exemple funcional, que pots ajustar al teu gust. Inclou noms explícits, volums persistents i xarxa definida:

version: '3.9'
services:
  db:
    image: mariadb:11
    container_name: wp_db
    restart: always
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: wppassword
      MYSQL_ROOT_PASSWORD: rootpassword
    volumes:
      - ./data/db:/var/lib/mysql
    networks:
      - wpnet

  wordpress:
    image: wordpress:6.4-php8.2-apache
    container_name: wp_app
    depends_on:
      - db
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: wppassword
    volumes:
      - ./data/wp:/var/www/html
    networks:
      - wpnet

  nginx:
    image: nginx:stable
    container_name: wp_nginx
    ports:
      - "80:80"
    volumes:
      - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on:
      - wordpress
    networks:
      - wpnet

networks:
  wpnet:
    driver: bridge

Algunes decisions justificades

  1. MariaDB versió fixa: Fer servir latest és temptador, però també impredictible. Fixar una versió com mariadb: 11 evita sorpreses.
  2. Volums mapejats a disc: Sense això, les dades es perden en recrear els contenidors.
  3. Xarxa pròpia (wpnet): Encara que Docker crea una xarxa bridge per defecte, definir-la explícitament dona més control i llegibilitat.

Nginx com a proxy

Per què posar Nginx si el contenidor de WordPress ja serveix pàgines amb Apache?

Perquè en molts entorns, especialment amb múltiples serveis, és preferible separar responsabilitats: Nginx escolta al port 80 i reenvia trànsit a WordPress. A més, Nginx és més versàtil com a proxy si després afegeixes HTTPS, certificats Let’s Encrypt o balanceig de càrrega.

Aquí un arxiu nginx/default.conf bàsic.

server {
    listen 80;
    server_name localhost;
    location / {
        proxy_pass http://wp_app:80;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

La clau aquí és proxy_pass http://wp_app:80; — el nom del contenidor de WordPress dins la xarxa wpnet.

Com aixecar els serveis

Des del directori wordpress-docker:

docker-compose up -d

Això descarrega les imatges, crea els contenidors, i aixeca els serveis. Després, n’hi ha prou amb obrir http://localhost per acabar la instal·lació de WordPress.

Problemes comuns

1. “Error en connectar amb la base de dades” a WordPress

La majoria de les vegades, és un d’aquests:

  1. Les variables WORDPRESS_DB_* no coincideixen amb les de MYSQL_* del contenidor de MariaDB.
  2. El nom del host (WORDPRESS_DB_HOST) no apunta a db, que és el nom del servei a la xarxa de Docker.
  3. El contenidor de MariaDB no està llest encara quan arrenca WordPress. Això de vegades requereix afegir una mica més de temps d’espera o fer servir un contenidor com a wait-for-it.

2. Arxius creats amb permisos estranys als volums

Això passa quan l’usuari dins del contenidor (per exemple www-data) no coincideix amb l’UID de l’usuari en el host. No és greu, però pot causar molèsties si edites arxius des de fora del contenidor. Una solució és fer servir user: en el docker-compose.yml, però no sempre val la pena si només fas servir els volums dins de Docker.

3. Canvis en Nginx que no tenen efecte

Si edites default.conf, assegura’t que el volum estigui correctament mapejat i no oblidis reiniciar el contenidor:

docker-compose restart nginx

I si l’arxiu té errors, Nginx no arrenca. Pots entrar al contenidor i revisar els logs amb:

docker logs wp_nginx

Recomanacions

  1. No esborris contenidors a cegues: si fas docker-compose down, perdràs els contenidors però no les dades (si fas servir volums ben mapejats). Però si fas docker volume rm sense saber què estàs eliminant, podries perdre contingut real.
  2. Backup del volum de base de dades: fes servir docker exec wp_db mysqldump periòdicament, o automatitza alguna cosa més robusta si el lloc creix.
  3. Entorns separats: Si has de tenir diverses instal·lacions (proves, producció, etc), fes servir noms de xarxa, contenidors i volums diferents. No confiïs que Docker ho gestioni tot màgicament.

HTTPS amb Docker i Let’s Encrypt

La forma més directa i replicable de tenir HTTPS a Docker sense tornar-te boig amb certificats manuals és fer servir els contenidors:

  1. nginx-proxy: un proxy revers automàtic basat en Nginx.
  2. acme-companion: genera i renova certificats HTTPS amb Let’ s Encrypt automàticament.

Com funciona?

Ambdós contenidors treballen junts: tu només llences els teus serveis WordPress amb algunes variables d’entorn (com el domini), i el proxy s’encarrega d’enrutar i generar els certificats. No necessites configurar Nginx manualment.

Requisits previs

  1. Un domini vàlid que apunti a la IP del teu servidor (per exemple, elmeudomini.com apuntant al teu VPS).
  2. Que el port 80 i 443 estiguin oberts (firewall i proveïdor).
  3. Docker i Docker Compose funcionant.

Pas a pas

1. Crear una xarxa externa

Per a què el proxy i els teus contenidors es comuniquin:

docker network create nginx_proxy

2. Aixecar el nginx-proxy + acme-companion

Pots crear un arxiu proxy-compose.yml com aquest:

version: '3.9'

services:
  nginx-proxy:
    image: nginxproxy/nginx-proxy:alpine
    container_name: nginx_proxy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./certs:/etc/nginx/certs
      - ./vhost.d:/etc/nginx/vhost.d
      - ./html:/usr/share/nginx/html
    networks:
      - nginx_proxy
    restart: always

  acme-companion:
    image: nginxproxy/acme-companion
    container_name: nginx_acme
    depends_on:
      - nginx-proxy
    environment:
      DEFAULT_EMAIL: el_teu_email@exemple.com
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./certs:/etc/nginx/certs
      - ./vhost.d:/etc/nginx/vhost.d
      - ./html:/usr/share/nginx/html
      - ./acme:/etc/acme.sh
    networks:
      - nginx_proxy
    restart: always

networks:
  nginx_proxy:
    external: true

Llença aquest stack:

docker compose -f proxy-compose.yml up -d

3. Adaptar el docker-compose.yml del WordPress

Ara no necessites el teu propi Nginx ni definir ports. Només defineixes variables:

version: '3.9'

services:
  db:
    image: mariadb:11
    container_name: wp_db
    restart: always
    environment:
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wpuser
      MYSQL_PASSWORD: wppassword
      MYSQL_ROOT_PASSWORD: rootpassword
    volumes:
      - ./data/db:/var/lib/mysql
    networks:
      - nginx_proxy

  wordpress:
    image: wordpress:6.4-php8.2-apache
    container_name: wp_app
    restart: always
    environment:
      VIRTUAL_HOST: domini.com
      LETSENCRYPT_HOST: domini.com
      LETSENCRYPT_EMAIL: el_teu_email@exemple.com
      WORDPRESS_DB_HOST: wp_db:3306
      WORDPRESS_DB_NAME: wordpress
      WORDPRESS_DB_USER: wpuser
      WORDPRESS_DB_PASSWORD: wppassword

    volumes:
      - ./data/wp:/var/www/html

    networks:
      - nginx_proxy

networks:
  nginx_proxy:
    external: true

Un cop llençat amb docker compose up -d, el proxy detecta el contenidor de WordPress, genera els certificats i enruta tot el trànsit HTTPS cap a ell.

Múltiples llocs WordPress en un mateix servidor

Gràcies al nginx-proxy, pots aixecar múltiples llocs amb certificats SSL sense repetir la configuració. N’hi ha prou amb fer servir diferents directoris i configurar les variables VIRTUAL_HOST i LETSENCRYPT_HOST per a cadascun.

Estructura suggerida

sitios/
├── wp1/
│   ├── docker-compose.yml
│   └── data/
│       ├── db/
│       └── wp/
└── wp2/
    ├── docker-compose.yml
    └── data/
        ├── db/
        └── wp/

Cada docker-compose.yml ha de tenir:

  1. un container_name únic
  2. noms de volum únics
  3. dominis diferents (per exemple, blog1.exemple.com, blog2.exemple.com)
  4. usar la xarxa nginx_proxy externa

Consell

Quan hi ha diversos llocs, els errors de certificats solen esdevenir per:

  1. DNS mal configurat (el domini no apunta al servidor)
  2. Domini no accessible des de fora (el proxy no pot obtenir el challenge)
  3. Fer servir dominis locals (.local, .dev sense configuració DNS adequada)

Balanç de càrrega amb múltiples instàncies WordPress

Això no és habitual en entorns personals, però si necessites balancejar múltiples instàncies de WordPress (per càrrega o alta disponibilitat), pots fer-ho dins del mateix Docker.

L’ enfocament seria:

  1. Instànciar múltiples contenidors de WordPress (wp_app1, wp_app2, etc.).
  2. Fer servir un contenidor Nginx personalitzat com a balancejador que distribueixi peticions.
  3. Fer servir volums compartits (per exemple, amb NFS, Ceph o bind mounts) per a wp-content i base de dades externa comuna (MariaDB no es pot replicar fàcilment sense configuració addicional).

Exemple bàsic de Nginx com a balancejador

upstream wordpress_cluster {
    server wp_app1:80;
    server wp_app2:80;
}

server {
    listen 80;
    server_name dominio.com;

    location / {
        proxy_pass http://wordpress_cluster;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

Consideracions

  1. WordPress no està dissenyat per a instàncies múltiples sense una capa d’emmagatzematge comú.
  2. La base de dades ha d’ estar centralitzada i sincronitzada.
  3. Arxius com imatges pujades han d’ estar en volums compartits o S3-compatible.
  4. Tenir una base de dades cau amb Redis o Varnish ajuda, però no és trivial si no controles bé les sessions.

Checklist tècnica amb HTTPS (Let’s Encrypt i múltiples llocs)

  1. DNS configurat correctament: cada domini ha de resoldre el servidor.
  2. Ports oberts: verifica que el 80 i 443 estan accessibles externament.
  3. Xarxa nginx_proxy creada:
docker network create nginx_proxy
  • Llençar el proxy HTTPS amb l’arxiu proxy-compose.yml.
  • Per a cada lloc WordPress:
    • Crear un directori independent (llocs/wp1, llocs/wp2…).Crear un docker-compose.yml amb:
      • VIRTUAL_HOST, LETSENCRYPT_HOST, LETSENCRYPT_EMAIL.Xarxa nginx_proxy a tots els serveis.
      Muntar volums per a persistència.
    • Llençar l’ stack amb:
docker compose up -d
  • Verificar HTTPS: accedeix al lloc amb navegador, o usa curl -I https://elteudomini.com.
  • Revisar logs si falla:
docker logs nginx_acme
docker logs nginx_proxy
  • (Opcional) Afegir un cron o script per a revisar expiració de certificats i espai en disc.

Conclusió

Muntar Nginx, MariaDB i WordPress amb Docker no hauria de ser una experiència frustrant, però sovint ho és quan se subestimen detalls com volums persistents, noms de servei o dependències entre contenidors.

Espero que aquesta guia t’hagi estalviat temps i mals de cap. No busca cobrir tots els casos possibles, però sí donar-te una base sòlida i explicada amb sentit comú. Si ja treballes amb Linux, probablement reconeguis alguns dels patrons. Si estàs començant, amb sort t’estalvies una o dues nits de proves fallides.

Deixa un comentari

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *