--- title: "Actualizar contenedores Docker con Watchtower en Ubuntu" description: "Instala Watchtower con Docker Compose para actualizar tus contenedores de forma automática y controlada: por etiquetas, en una ventana horaria y con avisos." category: "Docker Avanzado" language: es source: https://cubepath.com/es/docs/docker-avanzado/watchtower-actualizaciones-automaticas-de-docker updated: 2026-09-25 --- # Actualizar contenedores Docker con Watchtower en Ubuntu Watchtower es un contenedor que vigila las imágenes de tus otros contenedores: cuando se publica una versión nueva de la misma etiqueta (por ejemplo `nginx:1.28`), descarga la imagen y recrea el contenedor con la misma configuración. En este tutorial instalarás Watchtower con Docker Compose en Ubuntu 24.04 y lo configurarás de forma prudente: solo actualizará los contenedores que marques, lo hará en una ventana horaria fija, borrará las imágenes antiguas y te avisará de cada cambio. ## Requisitos previos Para seguir esta guía necesitas: - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. - Un usuario no root con privilegios `sudo` que pertenezca al grupo `docker`. - Docker Engine y el plugin Docker Compose instalados desde el repositorio oficial de Docker. - Opcional: un webhook de Discord o Slack, o una cuenta SMTP, para recibir avisos. ## Qué imagen de Watchtower usar El proyecto original, `containrrr/watchtower`, dejó de mantenerse y su repositorio está archivado. Además, su cliente usa una versión antigua de la API de Docker que las versiones recientes de Docker Engine ya no aceptan, por lo que falla con un error del tipo `client version 1.25 is too old`. En este tutorial se usa la bifurcación mantenida `nickfedor/watchtower`, que conserva las mismas variables de entorno, opciones y etiquetas. Si ya tienes `containrrr/watchtower` en marcha, puedes migrar cambiando únicamente el nombre de la imagen. ## Cuándo conviene (y cuándo no) actualizar automáticamente Watchtower solo sigue la etiqueta con la que arrancaste el contenedor. Eso te permite decidir cuánto riesgo asumes: | Etiqueta de la imagen | Qué actualizará Watchtower | Recomendación | |---|---|---| | `nginx:latest` | Cualquier versión nueva, incluidas las mayores | Evítala en producción | | `nginx:1.28` | Parches de la rama 1.28 | Buen equilibrio | | `nginx:1.28.0` | Nada, la etiqueta no cambia | Control manual | Las bases de datos (PostgreSQL, MySQL, Redis con persistencia) son malas candidatas a la actualización automática: una versión mayor puede requerir una migración de datos. Déjalas fuera o en modo solo aviso, como verás en el paso 5. ## Paso 1: Arrancar un contenedor de ejemplo Para tener algo que actualizar, crea un proyecto con Nginx. La etiqueta `com.centurylinklabs.watchtower.enable=true` marca el contenedor como actualizable; en el paso siguiente configurarás Watchtower para que ignore todo lo que no la lleve. ```bash sudo mkdir -p /opt/web sudo chown "$USER": /opt/web nano /opt/web/compose.yaml ``` ```yaml services: web: image: nginx:stable-alpine container_name: web restart: unless-stopped ports: - "8080:80" labels: - "com.centurylinklabs.watchtower.enable=true" ``` Arráncalo: ```bash cd /opt/web docker compose up -d ``` Comprueba que la etiqueta está aplicada: ```bash docker inspect web --format '{{ index .Config.Labels "com.centurylinklabs.watchtower.enable" }}' ``` ```output true ``` ## Paso 2: Instalar Watchtower con Docker Compose Crea un directorio propio para Watchtower: ```bash sudo mkdir -p /opt/watchtower sudo chown "$USER": /opt/watchtower nano /opt/watchtower/compose.yaml ``` ```yaml services: watchtower: image: nickfedor/watchtower:latest container_name: watchtower restart: unless-stopped volumes: - /var/run/docker.sock:/var/run/docker.sock environment: TZ: Europe/Madrid WATCHTOWER_SCHEDULE: "0 0 4 * * *" WATCHTOWER_LABEL_ENABLE: "true" WATCHTOWER_CLEANUP: "true" WATCHTOWER_TIMEOUT: "30s" ``` Qué hace cada variable: - `TZ`: zona horaria en la que se interpreta el horario. Cámbiala por la tuya. - `WATCHTOWER_SCHEDULE`: expresión cron de **seis campos**, el primero son los segundos. `0 0 4 * * *` significa todos los días a las 04:00:00. - `WATCHTOWER_LABEL_ENABLE`: solo actualiza contenedores con la etiqueta `com.centurylinklabs.watchtower.enable=true`. Sin esta opción, Watchtower actualizaría todos los contenedores del servidor. - `WATCHTOWER_CLEANUP`: borra la imagen antigua después de actualizar, para que no se acumulen en disco. - `WATCHTOWER_TIMEOUT`: tiempo que se da a cada contenedor para detenerse limpiamente antes de forzarlo. Watchtower necesita el socket de Docker para detener y recrear contenedores. > Advertencia: el acceso al socket de Docker equivale a acceso root en el host. Usa solo la imagen indicada y no añadas otras opciones que expongan su API HTTP a Internet. Arranca Watchtower: ```bash cd /opt/watchtower docker compose up -d ``` Comprueba en el registro que ha aplicado el horario y el filtro por etiquetas: ```bash docker logs watchtower ``` ```output level=info msg="Watchtower v1.x.x" level=info msg="Using no notifications" level=info msg="Only checking containers with enable label" level=info msg="Scheduling first run: 2026-09-26 04:00:00 +0200 CEST" ``` Los textos exactos pueden variar según la versión; lo importante es que aparezcan el filtro por etiqueta y la fecha de la primera ejecución. ## Paso 3: Probar una ejecución inmediata No hace falta esperar a las 04:00 para comprobar que todo funciona. Lanza una ejecución única en un contenedor temporal con `--run-once`, que revisa los contenedores marcados, actualiza si hay imagen nueva y termina: ```bash docker run --rm \ -v /var/run/docker.sock:/var/run/docker.sock \ nickfedor/watchtower --run-once --label-enable --cleanup ``` ```output level=info msg="Watchtower v1.x.x" level=info msg="Running a one time update." level=info msg="Session done" Failed=0 Scanned=1 Updated=0 notify=no ``` `Scanned=1` indica que ha encontrado el contenedor `web`. `Updated=0` es lo normal si la imagen ya estaba al día. Si aparece `Scanned=0`, el contenedor no tiene la etiqueta o está parado. Para ver en detalle qué compara, añade `--debug` al comando anterior. ## Paso 4: Recibir avisos de las actualizaciones Watchtower envía notificaciones mediante URLs de la librería Shoutrrr, que admite Discord, Telegram, Slack, correo SMTP y otros servicios. Solo necesitas la variable `WATCHTOWER_NOTIFICATION_URL`. Algunos formatos habituales: | Servicio | URL | |---|---| | Discord | `discord://TOKEN@WEBHOOK_ID` | | Telegram | `telegram://TOKEN_DEL_BOT@telegram?chats=ID_DEL_CHAT` | | Correo SMTP | `smtp://usuario:contraseña@smtp.your_domain:587/?from=watchtower@your_domain&to=admin@your_domain` | En un webhook de Discord con la forma `https://discord.com/api/webhooks/123456789/AbCdEf`, el `WEBHOOK_ID` es `123456789` y el `TOKEN` es `AbCdEf`. Para no dejar el secreto dentro del `compose.yaml`, guárdalo en un fichero `.env` en el mismo directorio: ```bash nano /opt/watchtower/.env ``` ```ini WATCHTOWER_NOTIFICATION_URL=discord://AbCdEf@123456789 ``` Restringe sus permisos: ```bash chmod 600 /opt/watchtower/.env ``` Añade la variable al bloque `environment` de `/opt/watchtower/compose.yaml`: ```yaml WATCHTOWER_NOTIFICATION_URL: ${WATCHTOWER_NOTIFICATION_URL} ``` Recrea el contenedor: ```bash cd /opt/watchtower docker compose up -d ``` Al arrancar, Watchtower envía un mensaje de inicio al canal configurado; si lo recibes, las notificaciones funcionan. A partir de ahí recibirás un aviso cada vez que actualice un contenedor o falle al hacerlo. Si no llega nada, busca errores de notificación con `docker logs watchtower`. ## Paso 5: Vigilar sin actualizar Para contenedores delicados, como una base de datos, puede interesarte saber que hay una imagen nueva sin que Watchtower la aplique. Para eso existe la etiqueta `com.centurylinklabs.watchtower.monitor-only`. Un ejemplo con PostgreSQL: ```yaml services: db: image: postgres:17 labels: - "com.centurylinklabs.watchtower.enable=true" - "com.centurylinklabs.watchtower.monitor-only=true" ``` Con estas dos etiquetas, Watchtower revisa el contenedor en cada ejecución y te notifica si hay una imagen nueva, pero no la descarga ni reinicia el contenedor. La actualización la haces tú a mano, cuando tengas una copia de seguridad reciente: ```bash docker compose pull db docker compose up -d db ``` Si prefieres que Watchtower no actualice nada en todo el servidor y solo avise, añade `WATCHTOWER_MONITOR_ONLY: "true"` al bloque `environment` de Watchtower. ## Paso 6: Imágenes de registros privados Si alguno de tus contenedores usa una imagen de un registro privado (GitHub Container Registry, un Harbor propio, etc.), Watchtower necesita las mismas credenciales que usa Docker. Inicia sesión en el registro como root, que crea `/root/.docker/config.json`: ```bash sudo docker login ghcr.io ``` Monta ese fichero en Watchtower añadiendo esta línea a `volumes:` en `/opt/watchtower/compose.yaml`: ```yaml - /root/.docker/config.json:/config.json:ro ``` Aplica el cambio con `docker compose up -d` y ejecuta de nuevo la prueba del paso 3 con el mismo montaje para verificar que puede consultar el registro. > Nota: si usas un gestor de credenciales (`credsStore`) en `config.json`, Watchtower no puede leerlas. En ese caso las credenciales tienen que estar directamente en el fichero. ## Solución de problemas - **`client version 1.25 is too old. Minimum supported API version is 1.44`**: estás usando la imagen archivada `containrrr/watchtower` con un Docker Engine reciente. Cambia la imagen a `nickfedor/watchtower`. - **`Scanned=0` en cada ejecución**: el filtro por etiquetas está activo y ningún contenedor tiene `com.centurylinklabs.watchtower.enable=true`. Recuerda que añadir una etiqueta en Compose requiere recrear el contenedor con `docker compose up -d`. - **Watchtower nunca se ejecuta**: el horario tiene cinco campos en lugar de seis. `0 4 * * *` no significa las 04:00 en Watchtower; usa `0 0 4 * * *`. - **Un contenedor se actualizó y ya no arranca**: vuelve a la versión anterior fijando una etiqueta concreta en su `compose.yaml` (por ejemplo `nginx:1.28.0-alpine`) y ejecuta `docker compose up -d`. Para evitarlo, usa etiquetas de rama en lugar de `latest`. ## Conclusión Watchtower mantiene al día los contenedores que marques, a la hora que elijas y avisándote de cada cambio, mientras las bases de datos quedan en modo solo aviso. Como siguientes pasos, programa copias de seguridad de tus volúmenes antes de la ventana de actualización, revisa las etiquetas de imagen de tus servicios para fijar ramas estables y añade comprobaciones de salud (`healthcheck`) en Compose para detectar pronto un contenedor que no arranque tras actualizarse.