Probado con Portainer CE 2.40.0 · Docker Compose v2 · verificado

Actualizado: 2026-07-17

Portainer[1] es la interfaz web de referencia para administrar contenedores Docker, stacks de Docker Compose (la herramienta que define y levanta varios contenedores a partir de un fichero YAML) y clústeres Swarm o Kubernetes desde un panel único, y se instala con un solo fichero compose.yaml y dos comandos. La edición CE 2.40 STS añade soporte nativo de Docker Compose v2, HTTPS activado por defecto en el puerto 9443 y un panel unificado para recursos de Docker Engine, Swarm, Kubernetes y ACI. La misma guía está disponible en inglés.

Esta guía instala Portainer CE con Docker Compose v2 en un servidor Debian/Ubuntu moderno (Ubuntu 24.04 LTS / Debian 13 Trixie), usando un fichero compose.yaml y el plugin oficial docker compose (sin guión, incluido con Docker Engine 20.10+; sustituye al binario independiente docker-compose de la generación anterior).

Puntos clave

  • Usa compose.yaml (sin clave version:) en lugar del antiguo docker-compose.yml con versión explícita.
  • Pinea la imagen (portainer/portainer-ce:2.40.0) en lugar de :latest para evitar actualizaciones silenciosas.
  • El volumen nombrado (portainer_data) simplifica copias de seguridad y actualizaciones.
  • El socket Docker se monta en solo lectura (:ro): Portainer no necesita escritura directa al socket.
  • El formulario de primer acceso expira a los 5 minutos: tenlo todo preparado antes de abrir el navegador.

Requisitos previos

Antes de empezar, necesitas:

  • Servidor con Docker Engine 24+ instalado (incluye el plugin docker compose por defecto). Ver la guía oficial de Docker para Debian[2] o Ubuntu[3].
  • Acceso sudo o usuario en el grupo docker.
  • Puerto 9443 libre para la UI HTTPS y, opcionalmente, el 8000 para el Edge Agent Tunnel (el canal que usa Portainer para gestionar agentes remotos sin abrirles puertos entrantes).

Preparar el fichero compose.yaml

Crea el directorio de trabajo y el fichero de configuración:

mkdir -p ~/docker/portainer
cd ~/docker/portainer
nano compose.yaml

Contenido recomendado:

services:
  portainer:
    image: portainer/portainer-ce:2.40.0
    container_name: portainer
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    ports:
      - "9443:9443"   # UI HTTPS
      - "8000:8000"   # Edge Agent tunnel (opcional)
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - portainer_data:/data

volumes:
  portainer_data:

Diferencias respecto a guías antiguas que vale la pena conocer:

  • Sin clave version:. La Compose Specification la ignora desde 2023; hoy es redundante y genera advertencias en algunas versiones.
  • Nombre compose.yaml preferido sobre docker-compose.yml (ambos funcionan, pero el nuevo es el estándar oficial).
  • Imagen pineada a 2.40.0, no :latest. El pinning evita sorpresas por actualizaciones mayores silenciosas cuando el host lanza un pull.
  • Volumen nombrado (portainer_data) en lugar de bind-mount. Lo gestiona Docker directamente y facilita copias de seguridad con herramientas como restic[4] o docker cp.
  • Socket Docker en solo lectura (:ro). Portainer controla todo vía API, no necesita escritura directa al socket del host.
Panel de administración de Portainer CE mostrando la lista de contenedores Docker en ejecución

Panel de administración de Portainer CE mostrando la lista de contenedores Docker en ejecución

Lanzar el contenedor

Con el fichero compose.yaml en su lugar, levanta Portainer en segundo plano:

docker compose up -d
docker compose ps

Verás un contenedor portainer en ejecución y escuchando en 0.0.0.0:9443. Si el comando docker compose no existe, asegúrate de estar usando Docker Engine 20.10+ con el plugin integrado, no la versión heredada docker-compose (con guión, ya sin mantenimiento activo).

Primer acceso

Abre en el navegador:

https://<IP-o-dominio>:9443

La primera vez te pedirá crear el usuario admin con una contraseña mínima de 12 caracteres. El formulario expira a los 5 minutos desde que arranca el contenedor; si tardas más, reinicia con docker compose restart y vuelve a entrar.

Como el certificado HTTPS es autofirmado en la primera instalación, tu navegador avisará de «conexión no privada». Es normal: pulsa «Avanzado» y luego «Continuar» para acceder. Para producción, coloca Portainer detrás de un reverse proxy como Traefik (el proxy inverso que reparte el tráfico HTTPS entre contenedores y renueva los certificados de forma automática) con Let’s Encrypt (ver más abajo).

Actualizar Portainer a una nueva versión

Actualizar Portainer es seguro porque el volumen portainer_data persiste usuarios, endpoints y configuración entre versiones. El proceso tiene tres pasos: edita compose.yaml y cambia la etiqueta de imagen (por ejemplo de 2.40.0 a 2.41.0), descarga la nueva imagen y recrea el contenedor, y por último limpia la imagen anterior si quieres liberar espacio:

docker compose pull
docker compose up -d
docker image prune -f

El volumen garantiza que la actualización no pierde datos. Si algo va mal, edita la etiqueta al valor anterior y vuelve a ejecutar docker compose up -d. Si prefieres automatizar por completo este paso, revisa cómo instalar Watchtower, la herramienta que vigila tus imágenes y recrea los contenedores cuando hay una versión nueva.

Exponer Portainer con Traefik (opcional)

Si ya tienes Traefik como ingress con la red traefik_public definida, añade labels al servicio y quita el mapeo de puertos. Cuando Traefik termina TLS por ti, el puerto interno es 9000 (HTTP), no 9443:

services:
  portainer:
    image: portainer/portainer-ce:2.40.0
    restart: unless-stopped
    networks: [traefik_public]
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - portainer_data:/data
    labels:
      - traefik.enable=true
      - traefik.http.routers.portainer.rule=Host(`portainer.example.com`)
      - traefik.http.routers.portainer.entrypoints=websecure
      - traefik.http.routers.portainer.tls.certresolver=letsencrypt
      - traefik.http.services.portainer.loadbalancer.server.port=9000
      - traefik.http.services.portainer.loadbalancer.server.scheme=http

networks:
  traefik_public:
    external: true

volumes:
  portainer_data:

Con esta configuración, Traefik gestiona el certificado TLS con Let’s Encrypt y Portainer queda accesible en https://portainer.example.com sin puertos no estándar. El mismo patrón aplica a cualquier servicio adicional que despliegues; ver cómo instalar servidores MCP locales como ejemplo de servicio complementario.

Preguntas frecuentes

¿Portainer sustituye a la línea de comandos de Docker?

No del todo. Portainer cubre la mayor parte del día a día (arrancar, parar, inspeccionar logs, desplegar stacks, gestionar volúmenes y redes) desde el navegador, pero para depuración fina o scripts automatizados seguirás usando docker y docker compose por terminal. Ambos leen el mismo socket, así que los cambios hechos por uno se ven al instante en el otro.

¿Es seguro exponer Portainer directamente a internet en el puerto 9443?

Funciona, pero no es lo recomendable a largo plazo: el formulario de primer acceso expira en 5 minutos precisamente para reducir ese riesgo, y después conviene añadir autenticación adicional. Lo más seguro es colocarlo detrás de un reverse proxy con TLS válido y, si es posible, restringir el acceso por IP o VPN en lugar de dejarlo accesible a cualquiera.

¿Puedo gestionar varios servidores Docker desde un único Portainer?

Sí. Además del entorno local, Portainer conecta con endpoints remotos vía el Edge Agent (un pequeño contenedor que se instala en cada servidor y abre un túnel saliente hacia tu Portainer central) o vía API TLS directa, lo que permite administrar varios hosts, un clúster Swarm o Kubernetes desde el mismo panel.

Conclusión

La instalación moderna de Portainer con Compose v2 es más sencilla que las guías de hace tres años: un compose.yaml de 15 líneas, versión pineada, HTTPS por defecto y persistencia en volumen nombrado. Para entornos con varios nodos, Swarm o Kubernetes, Portainer añade la misma UI sobre el endpoint del clúster sin cambiar el patrón de despliegue de esta guía.

Lo esencial que no cambia entre versiones:

  • Pinea la imagen para controlar cuándo actualizas.
  • Usa volumen nombrado, no bind-mount, para la carpeta /data.
  • Monta el socket en solo lectura.
  • Pon un reverse proxy con TLS en producción.

Fuentes: [1] Documentación oficial de Portainer CE (instalación con Docker)[5], [2] Documentación oficial de Docker Compose[6], [3] Documentación oficial de Traefik[7], [4] Documentación de restic[4].

Fuentes

  1. Portainer
  2. guía oficial de Docker para Debian
  3. Ubuntu
  4. restic
  5. Documentación oficial de Portainer CE (instalación con Docker)
  6. Documentación oficial de Docker Compose
  7. Documentación oficial de Traefik

Ruta: Self-hosting con Docker: de cero a producción