Tienes Portainer funcionando y una segunda máquina con Docker que también quieres ver desde la misma consola. La respuesta no es abrir el socket de Docker a la red: es desplegar un agente en la máquina remota. Este artículo explica qué hace ese agente, cómo se despliega y qué mirar cuando el entorno no llega a conectar.

Puntos clave

  • El agente es un contenedor que corre en el host remoto y escucha en el puerto 9001; el servidor de Portainer se conecta hacia él.
  • La comunicación va siempre sobre TLS con un certificado que el propio agente genera al arrancar.
  • Una petición sin firmar recibe un 401 con el mensaje Missing request signature headers: el agente no es una API abierta.
  • Si el servidor tiene un secreto propio, hay que pasarlo al agente con la variable AGENT_SECRET.
  • La alternativa de exponer el socket de Docker por TCP es equivalente a repartir acceso de root a esa máquina.

Por qué un agente y no el socket

La forma aparentemente sencilla de gestionar un host remoto es publicar el demonio de Docker por TCP y apuntar Portainer ahí. Es también la forma de convertir esa máquina en un problema. La documentación de Docker lo dice sin rodeos al hablar de las claves de acceso al demonio: "That means anyone with the keys can give any instructions to your Docker daemon, giving them root access to the machine hosting the daemon. Guard these keys as you would a root password!". Quien puede hablar con el demonio puede lanzar un contenedor privilegiado que monte el disco del anfitrión, así que el acceso al socket equivale a acceso de root.

El agente evita esa exposición. Habla con el socket local dentro de la máquina y publica hacia fuera una superficie mucho más pequeña: un único puerto, sobre TLS, que solo atiende peticiones firmadas por el servidor que lo gobierna.

Desplegar el agente en el host remoto

En una máquina con Docker suelto, el despliegue es un contenedor:

docker run -d \
  --name portainer_agent \
  --restart=always \
  -p 9001:9001 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /var/lib/docker/volumes:/var/lib/docker/volumes \
  portainer/agent:latest

Los dos montajes cumplen funciones distintas. El del socket es el que permite al agente hablar con Docker. El de los volúmenes es el que permite explorar su contenido desde la consola; si tus volúmenes no viven en la ruta estándar, ajusta ese segundo montaje a la ruta real.

Si prefieres declararlo junto al resto de tu infraestructura:

services:
  agent:
    image: portainer/agent:latest
    container_name: portainer_agent
    restart: always
    ports:
      - "9001:9001"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /var/lib/docker/volumes:/var/lib/docker/volumes

Al arrancar, el registro del contenedor confirma la configuración efectiva. En la versión que probamos para este artículo, la línea relevante declara api_version=2.39.6, server_addr=0.0.0.0, server_port=9001 y use_tls=true.

Qué expone realmente el agente

Conviene comprobarlo en lugar de suponerlo. Cuatro llamadas contra un agente recién levantado dejan clara la superficie:

Llamada Resultado
http://host:9001/ping (texto plano) 400: el agente no atiende HTTP sin cifrar
https://host:9001/ping sin validar el certificado 204
https://host:9001/ping validando el certificado falla: el certificado es autofirmado
https://host:9001/endpoints sin firma 401 Missing request signature headers

El certificado lo genera el agente en el momento de arrancar y tiene validez de un año exacto desde ese instante. Por eso validar la cadena desde fuera no funciona y por eso tampoco tiene sentido intentar poner ese puerto detrás de un proxy que espere un certificado de una autoridad pública: la confianza aquí la establece el servidor de Portainer, no el sistema de certificados del navegador.

La última fila es la importante desde el punto de vista de seguridad. Aunque alguien alcance el puerto 9001, sin las cabeceras de firma que emite el servidor no obtiene nada.

El secreto compartido

Si tu servidor de Portainer arranca con un secreto propio, el agente tiene que conocerlo. Se pasa como variable de entorno:

docker run -d --name portainer_agent --restart=always \
  -p 9001:9001 \
  -e AGENT_SECRET=tu-secreto \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /var/lib/docker/volumes:/var/lib/docker/volumes \
  portainer/agent:latest

Es un secreto compartido, así que trátalo como tal: no lo dejes en el historial del intérprete de órdenes ni en un fichero de compose sin cifrar dentro de un repositorio.

Conectar el entorno desde la consola

Con el agente en marcha, en el servidor se añade un entorno nuevo del tipo agente y se indica la dirección, sea nombre DNS o dirección IP, junto con el puerto. El valor por defecto, y el que corresponde al despliegue de arriba, es 9001.

Si necesitas además gestionar el sistema de ficheros del anfitrión desde la consola, el agente admite un montaje adicional de la raíz (-v /:/host). Es una capacidad potente y por eso mismo conviene añadirla solo si vas a usarla.

Qué mirar cuando el entorno no conecta

Por orden de probabilidad:

  1. El puerto no llega. Comprueba desde el servidor que el 9001 del host remoto responde. Un cortafuegos o un grupo de seguridad de por medio es la causa más habitual.
  2. Estás probando con HTTP. Un 400 al llamar en texto plano es el comportamiento esperado, no un fallo. Prueba con HTTPS.
  3. El certificado no valida. También es esperado: es autofirmado. No es el motivo por el que el entorno falla.
  4. Falta el secreto. Si el servidor tiene AGENT_SECRET y el agente no, la conexión se rechaza aunque la red esté perfecta.
  5. Los volúmenes no aparecen. El agente arrancó sin el montaje de volúmenes, o tus volúmenes no están en la ruta estándar.

Cuándo esto no es lo que necesitas

Si lo que tienes entre manos es un clúster y no dos o tres máquinas sueltas, el agente sigue sirviendo, pero la conversación cambia de sitio: pasa a ser una decisión de orquestación. Ahí conviene leer antes si Docker Swarm sigue teniendo sentido y, si decides ir por esa vía, cómo montar Traefik sobre Swarm con certificados.

Preguntas frecuentes

¿Necesito un agente en la máquina donde corre Portainer? No. El servidor gestiona su propio host a través del socket local; el agente es para los remotos.

¿Puedo poner el agente detrás de un proxy inverso con un certificado público? No tiene sentido. El servidor de Portainer valida al agente por su firma, no por la cadena de certificación, y el agente ya cifra por su cuenta.

¿El agente actualiza los contenedores del host remoto? No por sí solo. Es el canal por el que el servidor opera; las acciones las decides tú desde la consola.

Conclusión

Añadir un segundo host a Portainer es desplegar un contenedor, abrir un puerto y registrar el entorno. Lo que hay que entender no es el procedimiento, que son tres pasos, sino por qué existe: publicar el socket de Docker por la red regala acceso de root a esa máquina, y el agente reduce esa superficie a un puerto cifrado que solo obedece peticiones firmadas. La versión en inglés de este artículo está en Portainer Agent: managing a second Docker host.

Fuentes

  1. Portainer, documentación del agente para entornos Docker
  2. portainer/agent, repositorio del proyecto
  3. Docker, proteger el acceso al demonio