Docker Swarm es el modo de orquestación integrado en Docker Engine: agrupa varios servidores en un clúster y reparte entre ellos contenedores replicados, con balanceo de carga, actualizaciones progresivas y recuperación automática si un nodo cae. Es mucho más sencillo de operar que Kubernetes y usa el mismo formato de ficheros Compose que ya conoces. En este tutorial crearás un clúster de tres nodos en Ubuntu 24.04 (un manager y dos workers), desplegarás un stack replicado y practicarás las operaciones del día a día.
Requisitos previos
Para seguir esta guía necesitas:
- Tres servidores con Ubuntu 24.04 LTS, por ejemplo VPS de CubePath, con al menos 1 GB de RAM cada uno.
- Docker Engine instalado desde el repositorio oficial de Docker en los tres, y tu usuario añadido al grupo
dockerpara ejecutardockersinsudo. - Una red privada entre los tres servidores. En esta guía se usan estas direcciones de ejemplo, sustitúyelas por las tuyas:
| Nodo | Rol | IP privada |
|---|---|---|
manager1 | Manager | 10.0.0.11 |
worker1 | Worker | 10.0.0.12 |
worker2 | Worker | 10.0.0.13 |
- Un nombre de host distinto en cada servidor (
hostnamectlmuestra el actual). Swarm identifica los nodos por su hostname endocker node ls.
Paso 1: Abrir los puertos de Swarm en la red privada
Los nodos de Swarm se comunican por estos puertos, que deben estar abiertos solo entre los nodos y nunca hacia Internet:
| Puerto | Protocolo | Uso |
|---|---|---|
| 2377 | TCP | Gestión del clúster (solo hacia los managers) |
| 7946 | TCP y UDP | Descubrimiento y comunicación entre nodos |
| 4789 | UDP | Tráfico de las redes overlay (VXLAN) |
| ESP (protocolo IP 50) | - | Redes overlay cifradas |
Ejecuta en los tres servidores, ajustando 10.0.0.0/24 a tu red privada:
sudo ufw allow OpenSSH
sudo ufw allow from 10.0.0.0/24 to any port 2377 proto tcp
sudo ufw allow from 10.0.0.0/24 to any port 7946
sudo ufw allow from 10.0.0.0/24 to any port 4789 proto udp
sudo ufw allow from 10.0.0.0/24 proto esp
sudo ufw enable
Comprueba las reglas:
sudo ufw status
AdvertenciaLos puertos que publica Docker (
ports:en un stack o-pendocker run) se abren mediante reglas de iptables propias de Docker y no pasan por UFW. Un puerto publicado queda accesible desde Internet aunque UFW no tenga una regla para él. Publica solo lo que quieras exponer.
Paso 2: Inicializar el clúster en el manager
En manager1, inicializa Swarm indicando la IP privada con --advertise-addr. Es la dirección que los demás nodos usarán para conectarse; si no la indicas y el servidor tiene varias interfaces, Docker puede elegir la pública:
docker swarm init --advertise-addr 10.0.0.11
Swarm initialized: current node (k3v9q2x8m1n7b5c4z6a0d2f1g) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx 10.0.0.11:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
Copia el comando docker swarm join completo. Si lo pierdes, puedes volver a mostrarlo en cualquier momento desde el manager:
docker swarm join-token worker
ImportanteEl token de unión da acceso al clúster. No lo guardes en repositorios ni lo compartas. Si se filtra, invalídalo con
docker swarm join-token --rotate worker.
Paso 3: Unir los workers al clúster
Ejecuta el comando docker swarm join que copiaste en worker1 y en worker2:
docker swarm join --token SWMTKN-1-your_worker_token 10.0.0.11:2377
This node joined a swarm as a worker.
Vuelve a manager1 y lista los nodos. Todos los comandos de gestión del clúster (docker node, docker service, docker stack) se ejecutan en un manager:
docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
k3v9q2x8m1n7b5c4z6a0d2f1g * manager1 Ready Active Leader 28.4.0
p8w2e5r7t1y3u6i9o0a4s2d5f worker1 Ready Active 28.4.0
h6j3k9l1z4x7c2v8b5n0m3q6w worker2 Ready Active 28.4.0
NotaCon un solo manager, si ese servidor cae no podrás gestionar el clúster, aunque los contenedores de los workers sigan funcionando. En producción usa 3 managers, que toleran la caída de uno. Puedes convertir los workers en managers con
docker node promote worker1 worker2.
Paso 4: Desplegar un stack en una red overlay cifrada
Un stack es un conjunto de servicios definidos en un fichero Compose que Swarm despliega y mantiene en el clúster. Crea el fichero en manager1:
mkdir -p ~/stacks
nano ~/stacks/demo.yml
El servicio usa la imagen traefik/whoami, un servidor HTTP mínimo que responde con el nombre del contenedor que atiende la petición. Así podrás ver el balanceo entre réplicas:
services:
whoami:
image: traefik/whoami
ports:
- "8080:80"
networks:
- app
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 10s
failure_action: rollback
order: start-first
restart_policy:
condition: on-failure
resources:
limits:
cpus: "0.25"
memory: 64M
networks:
app:
driver: overlay
driver_opts:
encrypted: "true"
Los bloques importantes son:
replicas: 3: Swarm mantiene siempre tres contenedores y los reparte entre los nodos disponibles.update_config: las actualizaciones sustituyen los contenedores de uno en uno, esperan 10 segundos entre cada uno, arrancan el nuevo antes de parar el antiguo y vuelven atrás solas si algo falla.encrypted: "true": el tráfico entre contenedores de distintos nodos por la redappva cifrado con IPsec. Por eso abriste ESP en el paso 1.
Despliega el stack con el nombre demo:
docker stack deploy -c ~/stacks/demo.yml demo
Creating network demo_app
Creating service demo_whoami
Comprueba en qué nodos se han colocado las réplicas:
docker service ps demo_whoami
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
x1c4v7b0n3m6 demo_whoami.1 traefik/whoami:latest worker1 Running Running 20 seconds ago
q9w2e5r8t1y4 demo_whoami.2 traefik/whoami:latest worker2 Running Running 20 seconds ago
a3s6d9f2g5h8 demo_whoami.3 traefik/whoami:latest manager1 Running Running 20 seconds ago
El puerto publicado usa la malla de enrutado (routing mesh) de Swarm: el puerto 8080 responde en todos los nodos y reparte las peticiones entre las réplicas, estén donde estén. Haz varias peticiones contra un mismo nodo:
for i in 1 2 3; do curl -s http://10.0.0.12:8080 | grep Hostname; done
Hostname: 5e1f0a9b2c7d
Hostname: 8d3c6b1a4f2e
Hostname: c7a2e9d4b1f6
Cada respuesta llega de un contenedor distinto aunque siempre preguntas al mismo nodo.
Paso 5: Escalar y actualizar servicios
Para absorber más carga, aumenta el número de réplicas. Swarm crea las nuevas y las reparte entre los nodos:
docker service scale demo_whoami=6
demo_whoami scaled to 6
overall progress: 6 out of 6 tasks
verify: Service demo_whoami converged
Para que el cambio sea permanente, actualiza también replicas en demo.yml: si vuelves a ejecutar docker stack deploy, el fichero manda.
Cualquier cambio en la definición del contenedor (imagen, variables de entorno, límites) se aplica como actualización progresiva según update_config. Por ejemplo, añade una variable de entorno:
docker service update --env-add APP_VERSION=2 demo_whoami
Swarm sustituye las réplicas de una en una y muestra el progreso hasta que el servicio converge. En tu flujo habitual cambiarás la etiqueta de imagen en demo.yml y volverás a ejecutar docker stack deploy, que hace lo mismo. Si la nueva versión no se comporta como esperas, vuelve a la anterior:
docker service rollback demo_whoami
Revisa el historial de tareas para ver las réplicas sustituidas:
docker service ps demo_whoami
Las tareas antiguas aparecen con DESIRED STATE en Shutdown, y las activas en Running.
Paso 6: Mantenimiento de nodos
Antes de reiniciar o actualizar un servidor, drénalo: Swarm deja de asignarle tareas y mueve las que tenía a otros nodos:
docker node update --availability drain worker1
Comprueba que no quedan contenedores en ejecución en worker1:
docker node ps worker1 --filter desired-state=running
La lista debe salir vacía. Haz el mantenimiento y, al terminar, vuelve a activar el nodo:
docker node update --availability active worker1
NotaAl reactivar el nodo, Swarm no mueve las réplicas existentes para equilibrar la carga. Solo coloca ahí las tareas nuevas. Para redistribuirlas, fuerza una actualización con
docker service update --force demo_whoami.
Para fijar un servicio a ciertos nodos, etiqueta el nodo y usa una restricción de colocación. Por ejemplo, para una base de datos que debe correr donde está su disco:
docker node update --label-add storage=ssd worker2
Y en el servicio del fichero de stack:
deploy:
placement:
constraints:
- node.labels.storage == ssd
Paso 7: Hacer copia de seguridad del estado del clúster
El estado de Swarm (servicios, redes, secretos, configuración) vive en la base de datos Raft de los managers, en /var/lib/docker/swarm. Para copiarlo de forma consistente hay que parar Docker en el manager. Con un solo manager, mientras Docker esté parado no podrás gestionar el clúster, pero los contenedores de los workers siguen funcionando:
sudo systemctl stop docker docker.socket
sudo tar -czf /root/swarm-backup-$(date +%F).tar.gz -C /var/lib/docker swarm
sudo systemctl start docker
Comprueba que el manager vuelve a estar operativo:
docker node ls
Guarda la copia fuera del servidor. Para restaurar en un manager nuevo, se extrae el archivo en /var/lib/docker/ con Docker parado y se ejecuta docker swarm init --force-new-cluster para que el nodo arranque el clúster con ese estado. Con 3 managers rara vez necesitarás restaurar, porque los otros dos mantienen el estado.
Solución de problemas
docker swarm joinse queda esperando o datimeout: el worker no llega al puerto 2377 del manager. Comprueba la regla de UFW en el manager y que usas la IP privada connc -zv 10.0.0.11 2377desde el worker.- El servicio responde en un nodo pero no en otros: falla el tráfico overlay entre nodos. Revisa que 4789/udp, 7946 y ESP están permitidos entre todos los nodos.
- Una tarea se queda en
Pendingconno suitable node: ningún nodo cumple las restricciones de colocación o los recursos pedidos. Consulta el motivo condocker service ps --no-trunc demo_whoami. - La imagen no se descarga en los workers: si viene de un registro privado, despliega con
docker stack deploy --with-registry-authpara pasar las credenciales a los nodos.
Conclusión
Tienes un clúster Docker Swarm de tres nodos con un stack replicado en una red overlay cifrada, y sabes escalar, actualizar, revertir y drenar nodos sin cortar el servicio. Como siguientes pasos, promociona dos nodos más a manager para tener alta disponibilidad, guarda contraseñas con docker secret en lugar de variables de entorno, y pon un proxy inverso como Traefik o Nginx delante de los servicios publicados para servirlos con HTTPS.
