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:
- Nginx actuant com a proxy revers
- MariaDB com a base de dades
- 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
- MariaDB versió fixa: Fer servir latest és temptador, però també impredictible. Fixar una versió com mariadb: 11 evita sorpreses.
- Volums mapejats a disc: Sense això, les dades es perden en recrear els contenidors.
- 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:
- Les variables WORDPRESS_DB_* no coincideixen amb les de MYSQL_* del contenidor de MariaDB.
- El nom del host (WORDPRESS_DB_HOST) no apunta a db, que és el nom del servei a la xarxa de Docker.
- 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
- 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.
- 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.
- 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:
- nginx-proxy: un proxy revers automàtic basat en Nginx.
- 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
- Un domini vàlid que apunti a la IP del teu servidor (per exemple, elmeudomini.com apuntant al teu VPS).
- Que el port 80 i 443 estiguin oberts (firewall i proveïdor).
- 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:
- un container_name únic
- noms de volum únics
- dominis diferents (per exemple, blog1.exemple.com, blog2.exemple.com)
- usar la xarxa nginx_proxy externa
Consell
Quan hi ha diversos llocs, els errors de certificats solen esdevenir per:
- DNS mal configurat (el domini no apunta al servidor)
- Domini no accessible des de fora (el proxy no pot obtenir el challenge)
- 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:
- Instànciar múltiples contenidors de WordPress (wp_app1, wp_app2, etc.).
- Fer servir un contenidor Nginx personalitzat com a balancejador que distribueixi peticions.
- 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
- WordPress no està dissenyat per a instàncies múltiples sense una capa d’emmagatzematge comú.
- La base de dades ha d’ estar centralitzada i sincronitzada.
- Arxius com imatges pujades han d’ estar en volums compartits o S3-compatible.
- 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)
- DNS configurat correctament: cada domini ha de resoldre el servidor.
- Ports oberts: verifica que el 80 i 443 estan accessibles externament.
- 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.
- Llençar l’ stack amb:
- Crear un directori independent (llocs/wp1, llocs/wp2…).Crear un docker-compose.yml 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.