Los perfiles de Docker Compose te permiten guardar en un único archivo tanto los servicios que siempre necesitas como los que solo enciendes de vez en cuando. En lugar de mantener un docker-compose.yml para producción y otro para desarrollo, etiquetas cada servicio con un perfil y decides en el momento del arranque cuáles quieres levantar. Esta guía explica el atributo profiles, cómo activarlo y cómo se lleva con las dependencias. La misma explicación está disponible en inglés.

Puntos clave

  • Un perfil es una etiqueta que asignas a un servicio con el atributo profiles; ese servicio solo arranca cuando activas su perfil.
  • Los servicios sin atributo profiles están siempre habilitados y se levantan con un docker compose up normal.
  • Los perfiles se activan con la opción --profile o con la variable de entorno COMPOSE_PROFILES; puedes activar varios a la vez.
  • La función llegó en Docker Compose 1.28.0 (enero de 2021) y funciona igual en la versión 2 del plugin docker compose.
  • Si nombras un servicio con perfil en la línea de comandos, Compose lo arranca aunque no hayas activado el perfil, junto con sus dependencias.

¿Qué problema resuelven los perfiles?

Un mismo proyecto suele necesitar servicios distintos según el contexto. En producción quieres solo la aplicación y su base de datos, pero en tu portátil te viene bien un visor de correo, una interfaz web para la base de datos o un contenedor que lanza copias de seguridad puntuales. La respuesta tradicional era mantener varios ficheros y encadenarlos con -f, lo que multiplica el mantenimiento y abre la puerta a que se descuadren.

Los perfiles resuelven esto dentro de un único docker-compose.yml. Marcas los servicios accesorios con una etiqueta y quedan en reposo: docker compose up ni los mira. Cuando los necesitas, activas su perfil y aparecen. La documentación oficial lo resume así: los servicios sin el atributo profiles están siempre habilitados, y el resto solo se ejecuta cuando su perfil está activo. Es la misma filosofía de encendido selectivo que aplicamos a las políticas de reinicio y los healthchecks para controlar el ciclo de vida de cada contenedor.

Cómo asignar servicios a un perfil

El atributo profiles va dentro de la definición de cada servicio y acepta una lista de nombres. Un nombre de perfil válido sigue el patrón [a-zA-Z0-9][a-zA-Z0-9_.-]+: letras, números, guiones, puntos y guiones bajos. Este archivo de ejemplo deja app y db siempre activos, y esconde tres servicios detrás de los perfiles debug, dev y tools:

services:
  app:
    image: nginx:1.27-alpine
    restart: unless-stopped
    ports:
      - "8080:80"
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16.4-alpine
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: cambia_esta_clave
    volumes:
      - db_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5

  adminer:
    image: adminer:4.8.1
    restart: unless-stopped
    profiles: ["debug"]
    ports:
      - "8081:8080"
    depends_on:
      - db

  mailpit:
    image: axllent/mailpit:v1.20
    restart: unless-stopped
    profiles: ["dev"]
    ports:
      - "8025:8025"

  backup:
    image: postgres:16.4-alpine
    profiles: ["tools"]
    entrypoint: ["pg_dump", "-h", "db", "-U", "postgres", "app"]
    depends_on:
      - db

volumes:
  db_data:

Aquí app es un servidor web de ejemplo y db una base de datos PostgreSQL con su healthcheck; ninguno lleva profiles, así que siempre arrancan. adminer (interfaz web de base de datos), mailpit (buzón de correo de pruebas) y backup (un pg_dump puntual) están reservados a sus perfiles. Un servicio puede pertenecer a varios perfiles a la vez: basta con listar más nombres, por ejemplo profiles: ["debug", "dev"].

Seguimos el convenio de Compose v2: sin la clave version:, con volúmenes con nombre, restart: unless-stopped y un healthcheck en la base de datos. Si todavía no tienes el motor listo, empieza por cómo instalar Docker en Ubuntu 24.04 y luego publica cada servicio detrás de un proxy inverso.

Activar perfiles con –profile y COMPOSE_PROFILES

Con el archivo anterior, un arranque normal solo levanta la base:

docker compose up -d

Para encender los servicios de un perfil, usa la opción --profile antes del subcomando. Puedes repetirla para activar varios, o pasar una lista separada por comas en COMPOSE_PROFILES:

docker compose --profile debug up -d
docker compose --profile debug --profile dev up -d
COMPOSE_PROFILES=debug,dev docker compose up -d

El comodín "*" habilita todos los perfiles de golpe, algo útil para levantar el proyecto completo o para pararlo entero sin dejar contenedores huérfanos:

docker compose --profile "*" up -d
docker compose --profile "*" down

Ojo con el apagado: docker compose down solo detiene los servicios de los perfiles activos en ese momento. Si arrancaste adminer con --profile debug y luego haces un down sin ese perfil, el contenedor de adminer sigue en marcha. Por eso conviene apagar con el mismo perfil (o con "*") con el que arrancaste.

Casos de uso: dev, debug y servicios opcionales

Los perfiles brillan en tres situaciones habituales del self-hosting:

  • Entorno de desarrollo (dev): herramientas que solo quieres en tu máquina, como Mailpit para atrapar el correo saliente o un servicio con recarga en caliente. En el servidor de producción nunca activas ese perfil.
  • Depuración (debug): utilidades de diagnóstico como Adminer, un pgweb o un contenedor con curl y dig. Las enciendes cuando algo falla y las apagas al terminar, sin dejarlas expuestas de forma permanente.
  • Tareas puntuales (tools): contenedores de un solo uso, como un pg_dump para copias de seguridad o un script de migración. Encajan bien con docker compose run, que arranca el servicio, ejecuta su comando y termina.

Este último caso enlaza con una ventaja importante: cuando nombras un servicio con perfil directamente en la línea de comandos, Compose lo arranca sin que tengas que activar su perfil a mano.

docker compose run --rm backup

Ese comando levanta backup (perfil tools) y, como depende de db, también se asegura de que la base de datos esté disponible, todo sin escribir --profile tools.

Combinar perfiles y dependencias

La relación entre profiles y depends_on tiene una regla que conviene tener clara: un servicio siempre activo no puede depender de un servicio que esté escondido tras un perfil inactivo. Si app declarara depends_on: [adminer] y no activas el perfil debug, Compose fallaría porque la dependencia no existe en ese arranque. La solución es que ambos compartan perfil o que la dependencia no lleve ninguno.

En cambio, cuando arrancas un servicio con perfil, sus dependencias listadas en depends_on se levantan con él aunque estén en otro perfil o sin perfil. Por eso en el ejemplo adminer y backup pueden depender de db sin problemas: db no lleva perfil, así que siempre está disponible. Si combinas esto con límites de recursos y una buena gestión de logs, tienes un archivo único capaz de servir a producción, desarrollo y mantenimiento sin duplicar nada.

Una recomendación final: no fíes la seguridad a los perfiles. Que un servicio esté en el perfil debug no impide que alguien lo arranque; solo evita que se levante por defecto. Para servicios sensibles, combina los perfiles con autenticación y con no publicar sus puertos hacia el exterior.

Preguntas frecuentes

¿Los servicios sin perfil se arrancan siempre?

Sí. Cualquier servicio que no declare el atributo profiles está siempre habilitado y se levanta con un docker compose up normal, sin importar qué perfiles actives. Los perfiles solo afectan a los servicios que llevan la etiqueta.

¿Puedo activar todos los perfiles a la vez?

Sí, con el comodín --profile "*". Habilita todos los perfiles definidos en el archivo en una sola orden, tanto para up como para down. Es la forma más cómoda de levantar o parar el proyecto entero cuando tienes muchos servicios opcionales.

¿Desde qué versión existen los perfiles en Docker Compose?

Los perfiles llegaron en Docker Compose 1.28.0, publicada en enero de 2021, y funcionan igual en la versión 2 del plugin docker compose, que es la que usarás hoy en cualquier instalación reciente. No necesitas la clave version: en el archivo.

Conclusión

Los perfiles convierten un docker-compose.yml en una definición flexible que se adapta al contexto: producción, desarrollo o mantenimiento, todo en un solo sitio. Etiqueta con profiles los servicios accesorios, actívalos con --profile o COMPOSE_PROFILES cuando los necesites y deja que las dependencias sin perfil arranquen siempre. El siguiente paso natural es repasar los healthchecks y las políticas de reinicio para que cada servicio, activo o no, se comporte de forma predecible.

Fuentes: [1] Docker Docs: Using profiles with Compose[1], [2] compose-spec: atributo profiles (GitHub)[2], [3] freeCodeCamp: Docker Compose para producción[3].

Fuentes

  1. Docker Docs: Using profiles with Compose
  2. compose-spec: atributo profiles (GitHub)
  3. freeCodeCamp: Docker Compose para producción

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