JFP
Inicio CV Blog
Volver al blog
homelab

Montando la base para los servicios: LXC de Docker, Portainer y Watchtower

Cómo monté un LXC dedicado a Docker en Proxmox usando los Helper Scripts, con Portainer para gestionar los contenedores y Watchtower para mantenerlos actualizados automáticamente.

Montando la base para los servicios: LXC de Docker, Portainer y Watchtower

Con el servidor físico ya listo y Proxmox instalado (como conté en el artículo anterior), tocaba decidir cómo iba a alojar los servicios de verdad: cosas como gestores de descargas, un servidor de streaming, o lo que fuera surgiendo con el tiempo. Aquí explico la base que monté para eso, que sigue en pie hoy.

Por qué un LXC y no una máquina virtual

Proxmox permite dos formas de aislar cosas: máquinas virtuales (VM), que emulan un ordenador completo con su propio kernel, y contenedores LXC, que comparten el kernel del host pero mantienen su propio sistema de archivos y procesos aislados. Para correr Docker no necesitaba la sobrecarga de una VM completa — un LXC es mucho más ligero (arranca en segundos, consume menos RAM en reposo) y es perfectamente capaz de correr Docker dentro, así que fue la opción natural.

Instalando Docker con Proxmox VE Helper Scripts

Para crear el contenedor usé los Proxmox VE Helper Scripts, una colección de scripts comunitarios muy conocida en el mundo Proxmox que automatiza la creación de LXCs con software preinstalado y bien configurado, en lugar de tener que hacerlo todo a mano paso a paso. Tienen un script dedicado para Docker que, además, ofrece instalar Portainer de paso durante el propio proceso.

El comando se ejecuta directamente en la Shell del propio Proxmox (no dentro de ningún contenedor):

bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/docker.sh)"

El script pregunta de forma interactiva por el tamaño del contenedor, si quieres modo por defecto o avanzado, y si quieres instalar Portainer (y/o Docker Compose V2) junto con Docker. En mi caso dije que sí a Portainer, para no tener que instalarlo como un paso aparte.

<!-- TODO IMAGEN 1: Captura de la Shell de Proxmox mientras corre el script docker.sh, mostrando las preguntas interactivas (tamaño de contenedor, instalar Portainer sí/no). Es tuya y real, solo hay que volver a lanzarlo o capturarlo la próxima vez que se use. -->

Cómo quedó configurado

El contenedor, unprivileged (sin privilegios elevados sobre el host, una buena práctica de seguridad recomendada por defecto), quedó así:

Recurso Asignado
CPU 2 vCPUs
RAM 8 GB
SWAP 3 GB
Disco 20 GB
Sistema operativo Debian
<!-- TODO IMAGEN 2: Captura de la pantalla "Summary" del LXC 102 en Proxmox, la que muestra CPU/RAM/disco en vivo. Es la misma pantalla que ya vimos hoy, solo hay que hacer la captura real. -->

Portainer: la interfaz web para gestionar Docker

Portainer es una interfaz web que se instala como un contenedor más y permite ver, crear, parar y editar todos los demás contenedores, redes, volúmenes y stacks de Docker desde el navegador, en lugar de escribir comandos docker sueltos cada vez. Es la herramienta que uso para desplegar cada stack de servicios nuevo: se pega un docker-compose.yml, se le da a desplegar, y Portainer se encarga de bajar las imágenes y levantar los contenedores.

Como venía integrado en el propio script de instalación de Docker, así quedó desplegado (mostrando la configuración equivalente, sin nada que ocultar en este caso):

services:
  portainer:
    image: portainer/portainer-ce:lts
    container_name: portainer
    restart: always
    ports:
      - "8000:8000"
      - "9443:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data

volumes:
  portainer_data:

El puerto 9443 es el que uso para entrar a la interfaz web (HTTPS), y el 8000 lo usa Portainer internamente para el agente de gestión de edge devices, que en mi caso no utilizo pero se queda expuesto por defecto.

<!-- TODO IMAGEN 3: Captura del dashboard de Portainer con la lista de stacks o contenedores. Cuidado: recortar/tapar cualquier IP interna o dato que no quieras mostrar antes de subirla. -->

Con Docker y Portainer ya en marcha, faltaba resolver un problema práctico: mantener actualizadas las imágenes de cada contenedor sin tener que entrar manualmente a revisar cada pocos días si hay una versión nueva.

Watchtower: actualizaciones automáticas

Watchtower es un contenedor que vigila las imágenes Docker que corren en el host y, cuando detecta una versión nueva en el registro, descarga la imagen actualizada y recrea el contenedor automáticamente. Este sí lo desplegué yo aparte, como un stack en Portainer:

version: '3.8'
services:
  watchtower:
    image: containrrr/watchtower:latest
    container_name: watchtower
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WATCHTOWER_CLEANUP=true
      - WATCHTOWER_INCLUDE_RESTARTING=false
      - WATCHTOWER_INCLUDE_STOPPED=false
      - WATCHTOWER_REVIVE_STOPPED=false
      - WATCHTOWER_NO_RESTART=false
      - WATCHTOWER_TIMEOUT=30s
      # sec min hour dmonth month dweek
      - WATCHTOWER_SCHEDULE=0 0 6 * * 3
      - WATCHTOWER_DEBUG=false
      - WATCHTOWER_LABEL_TAKE_PRECEDENCE=true
      - WATCHTOWER_MONITOR_ONLY=false
      - WATCHTOWER_NO_STARTUP_MESSAGE=false
      - WATCHTOWER_NOTIFICATIONS=email
      - WATCHTOWER_NOTIFICATION_EMAIL_TO=************
      - WATCHTOWER_NOTIFICATION_EMAIL_FROM=************
      - WATCHTOWER_NOTIFICATION_EMAIL_SERVER=************
      - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=587
      - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=************
      - WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD=************

Los puntos clave de esta configuración:

  • Se ejecuta cada miércoles a las 6:00 de la mañana (WATCHTOWER_SCHEDULE, en formato cron con segundos), no de forma continua — evita reinicios inesperados de servicios en mitad del día.
  • Limpia las imágenes viejas después de actualizar (WATCHTOWER_CLEANUP), para no ir acumulando basura en disco.
  • No toca contenedores que estén parados o reiniciándose (INCLUDE_RESTARTING / INCLUDE_STOPPED en false), solo los que están corriendo normalmente.
  • Tiene notificaciones por correo configuradas (WATCHTOWER_NOTIFICATIONS=email), así que me entero si algo se actualiza o si falla algo, sin tener que entrar a mirar. Los datos del servidor SMTP los he ocultado aquí, claro.
  • WATCHTOWER_LABEL_TAKE_PRECEDENCE=true permite excluir contenedores concretos de la actualización automática poniéndoles la etiqueta com.centurylinklabs.watchtower.no-pull, útil para servicios que prefiero actualizar a mano y controlar bien la versión.

Con esto, cualquier stack nuevo que despliegue en Portainer hereda automáticamente las actualizaciones automáticas de Watchtower, sin tener que configurar nada adicional por servicio.

<!-- TODO IMAGEN 4 (opcional): Captura de los logs de Watchtower mostrando una actualización real de algún contenedor. Solo si tienes uno reciente a mano; si no, se puede omitir sin problema. -->

El punto de partida

Con Docker corriendo en su propio LXC, Portainer como interfaz de gestión y Watchtower manteniendo todo actualizado, ya tenía la base montada para empezar a desplegar servicios de verdad. El primero y más grande que llegó fue un stack completo dedicado a la gestión automatizada de medios — series, películas, música, libros y descargas — que cuento en el siguiente artículo, porque da para una entrada entera él solo.

Tags

#docker #proxmox #portainer #watchtower #homelab