Introducción a los Perfiles en Docker Compose
Cuando trabajamos en proyectos de desarrollo, frecuentemente necesitamos servicios que no siempre deben estar activos. Por ejemplo, durante el desarrollo local podrías querer tener un panel de administración visual como Adminer o pgAdmin, pero estos servicios no tienen sentido en producción. Los perfiles resuelven este problema eleganteamente.
En esta lección aprenderás a:
- Definir y usar perfiles en docker-compose.yml
- Crear entornos múltiples (desarrollo, staging, producción)
- Combinar perfiles con variables de entorno
- Optimizar el rendimiento de tu flujo de trabajo
¿Qué son los Perfiles?
Los perfiles son etiquetas que asignas a servicios en tu archivo docker-compose. Un servicio con un perfil solo se arrancará cuando lo solicites explícitamente con la bandera --profile o cuando el perfil esté activo mediante la variable de entorno COMPOSE_PROFILES.
Sintaxis Básica de Perfiles
Veamos la estructura fundamental:
version: '3.9'
services:
app:
image: mi-aplicacion:latest
ports:
- "3000:3000"
db:
image: postgres:15
environment:
POSTGRES_DB: miapp_dev
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev123
profiles:
- development
adminer:
image: adminer
ports:
- "8080:8080"
profiles:
- development
- debug
redis:
image: redis:alpine
profiles:
- cache
mailhog:
image: mailhog/mailhog
ports:
- "1025:1025"
- "8025:8025"
profiles:
- debugEn este ejemplo:
- app y db se inician siempre (sin perfil)
- adminer se inicia con perfil development o debug
- redis requiere el perfil cache
- mailhog se inicia solo con el perfil debug
Activando Perfiles
Existen varias formas de activar perfiles:
Método 1: Bandera --profile
# Activar un solo perfil
docker-compose up -d --profile development
# Activar múltiples perfiles
docker-compose up -d --profile development --profile debug
# Forma corta (separados por coma)
docker-compose up -d --profile "development,debug"Método 2: Variable de entorno
# Linux/Mac
export COMPOSE_PROFILES=development
docker-compose up -d
# Windows PowerShell
$env:COMPOSE_PROFILES="development"
docker-compose up -d
# Windows CMD
set COMPOSE_PROFILES=development
docker-compose up -d.env.local o .bashrc.Método 3: docker-compose.override.yml
También puedes crear archivos de override por perfil:
# docker-compose.dev.yml
version: '3.9'
services:
app:
build:
context: .
target: development
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
command: npm run dev
adminer:
profiles:
- dev-tools
restart: unless-stoppedEntornos Múltiples con Docker Compose
Los entornos múltiples son fundamentales para cualquier proyecto serio. Necesitas poder cambiar entre configuración de desarrollo, staging y producción sin modificar tu código.
docker-compose.yml con la configuración común y archivos específicos para cada entorno.Estructura de Archivos Recomendada
proyecto/
├── docker-compose.yml # Base (siempre presente)
├── docker-compose.dev.yml # Desarrollo
├── docker-compose.staging.yml # Staging
├── docker-compose.prod.yml # Producción
├── .env # Variables comunes
├── .env.dev # Variables desarrollo
├── .env.staging # Variables staging
└── .env.prod # Variables producciónEjemplo Práctico Completo
Creemos una aplicación Node.js con diferentes entornos:
# docker-compose.yml (BASE)
version: '3.9'
services:
app:
image: miapp:latest
restart: unless-stopped
db:
image: postgres:15-alpine
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 5s
retries: 5
volumes:
postgres_data:# docker-compose.dev.yml
version: '3.9'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
volumes:
- .:/app
- /app/node_modules
environment:
- NODE_ENV=development
- DEBUG=true
- LOG_LEVEL=debug
ports:
- "3000:3000"
command: npm run dev
profiles:
- dev-tools
adminer:
image: adminer:latest
ports:
- "8080:8080"
profiles:
- dev-tools
restart: unless-stopped
mailhog:
image: mailhog/mailhog:latest
ports:
- "1025:1025"
- "8025:8025"
profiles:
- dev-tools
restart: unless-stopped# docker-compose.staging.yml
version: '3.9'
services:
app:
build:
context: .
dockerfile: Dockerfile
args:
NODE_ENV: staging
environment:
- NODE_ENV=staging
- DEBUG=false
- LOG_LEVEL=info
deploy:
replicas: 2
resources:
limits:
cpus: '0.5'
memory: 512M
db:
environment:
- POSTGRES_DB=miapp_staging
- POSTGRES_USER=staging_user
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./secrets/staging_db_password.txt# docker-compose.prod.yml
version: '3.9'
services:
app:
image: miapp:production
environment:
- NODE_ENV=production
- DEBUG=false
- LOG_LEVEL=error
deploy:
replicas: 3
restart_policy:
condition: on-failure
delay: 5s
max_attempts: 3
resources:
limits:
cpus: '1.0'
memory: 1G
db:
image: postgres:15-alpine
environment:
- POSTGRES_DB=miapp_production
- POSTGRES_USER=prod_user
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
volumes:
- prod_postgres_data:/var/lib/postgresql/data
secrets:
- db_password
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
depends_on:
- app
profiles:
- production
volumes:
prod_postgres_data:
driver: local-persist
secrets:
db_password:
file: ./secrets/prod_db_password.txtComandos para Cambiar Entre Entornos
- Desarrollo:
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d --profile dev-tools - Staging:
docker-compose -f docker-compose.yml -f docker-compose.staging.yml up -d - Producción:
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --profile production
-d sin antes verificar que los servicios arrancan correctamente. Ejecuta primero docker-compose up sin -d para ver los logs en tiempo real y detectar problemas.Variables de Entorno por Entorno
Usa archivos .env para mantener las configuraciones sensibles separadas:
# .env (común a todos los entornos)
APP_NAME=MiApp
APP_VERSION=1.0.0
# .env.dev
NODE_ENV=development
LOG_LEVEL=debug
API_URL=http://localhost:3001
# .env.staging
NODE_ENV=staging
LOG_LEVEL=info
API_URL=https://api.staging.miapp.com
# .env.prod
NODE_ENV=production
LOG_LEVEL=error
API_URL=https://api.miapp.comPara usar un archivo .env específico:
# Desarrollo
docker-compose --env-file .env.dev -f docker-compose.yml -f docker-compose.dev.yml up
# Producción
docker-compose --env-file .env.prod -f docker-compose.yml -f docker-compose.prod.yml up~/.bashrc o ~/.zshrc:alias dc-dev="docker-compose -f docker-compose.yml -f docker-compose.dev.yml --env-file .env.dev"
alias dc-stage="docker-compose -f docker-compose.yml -f docker-compose.staging.yml --env-file .env.staging"
alias dc-prod="docker-compose -f docker-compose.yml -f docker-compose.prod.yml --env-file .env.prod"Tabla Resumen de Perfiles vs Entornos
| Característica | Perfiles (profiles) | Archivos Compose Múltiples |
|---|---|---|
| Uso principal | Activar/desactivar servicios opcionales | Configuraciones de entorno diferentes |
| Ámbito | Servicios individuales | Servicios completos y configuración |
| Activación | --profile o COMPOSE_PROFILES | -f archivo1.yml -f archivo2.yml |
| Ejemplo típico | Adminer, Mailhog en desarrollo | dev vs staging vs production |
| Flexibilidad | Combinar múltiples perfiles | Override completo de configuración |
Casos de Uso Avanzados
Ver más: Perfiles con Condiciones de DependenciaA veces necesitas que un servicio se ejecute solo si otro perfil está activo. Puedes lograr esto combinando perfiles con la opción profiles:
services:
app:
image: miapp
depends_on:
db:
condition: service_healthy
db:
image: postgres:15
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
retries: 5
profiles:
- database
redis:
image: redis:alpine
profiles:
- cache
elasticsearch:
image: elasticsearch:8.11.0
environment:
- discovery.type=single-node
profiles:
- search
- full-stack
depends_on:
- redisCrea un perfil específico para ejecutar tests:
services:
app:
image: miapp:test
command: npm test
app-ci:
build:
context: .
target: test
profiles:
- ci
depends_on:
db-test:
condition: service_started
db-test:
image: postgres:15
environment:
POSTGRES_DB: test_db
profiles:
- ci
tmpfs:
- /var/lib/postgresql/dataEl tmpfs hace que los datos se guarden en memoria, ideal para tests que deben ser rápidos y no persistir datos.
Buenas Prácticas
Un archivo docker-compose.yml bien estructurado es documentación ejecutable de tu arquitectura de servicios.
- Nombra los perfiles descriptivamente: Usa nombres como
dev-tools,monitoring,cien lugar dep1,p2 - Documenta en comentarios: Explica qué hace cada perfil y cuándo usarlo
- Separación de concerns: Un perfil no debería modificar servicios base si no es necesario
- Versiona tus archivos compose: Los archivos compose son código, trátalos como tal
- Usa .dockerignore: Evita copiar archivos innecesarios al contexto de build
Solución de Problemas Comunes
Ver más: Problemas FrecuentesProblema: Un servicio con perfil no inicia
- Verifica que el perfil esté correctamente escrito
- Comprueba que no haya errores de sintaxis YAML (indentación)
- Usa
docker-compose configpara validar
Problema: Dependencias con perfiles
# Incorrecto: db no existe si no está el perfil
services:
app:
depends_on:
- db # Fallará si db tiene un perfil que no está activo
# Correcto: db siempre presente o sin perfil
services:
app:
depends_on:
db:
condition: service_healthy
db:
image: postgres
# Sin perfil, siempre disponibleProblema: Variables de entorno no cargan
- Verifica el orden de los archivos con
-f - La variable en el archivo override tiene precedencia sobre el base
- Usa
docker-compose configpara ver la configuración final
Comandos Útiles
# Ver qué perfiles están disponibles
docker-compose config --profiles
# Iniciar con múltiples perfiles
docker-compose up -d --profile dev --profile monitoring
# Ver solo servicios sin perfil (base)
docker-compose up -d
# Detener servicios de un perfil específico
docker-compose stop adminer mailhog
# Ver logs de servicios con perfil
docker-compose logs --profile debug
# Listar servicios activos
docker-compose psdocker-compose config --profiles (disponible desde Docker Compose v2.17) lista todos los perfiles definidos en tu archivo, útil para documentar qué perfiles existen.Conclusión
Los perfiles y los entornos múltiples son herramientas poderosas que te permiten:
- Mantener un único archivo base para todos tus servicios
- Activar únicamente los servicios que necesitas en cada momento
- Separar claramente configuraciones de desarrollo, staging y producción
- Mejorar el rendimiento al no cargar servicios innecesarios
- Facilitar el trabajo en equipo con configuraciones predefinidas
Dominar estas técnicas te permitirá crear flujos de trabajo de desarrollo más limpios y profesionales, reduciendo la fricción entre diferentes contextos de ejecución.
¿Cuál es la forma correcta de iniciar solo los servicios base (sin perfiles) usando docker-compose?
- A) docker-compose up --no-profiles
- B) docker-compose up -d
- C) docker-compose start --profile none
- D) docker-compose up -d --profile base
¿Cuál es la ventaja principal de usar múltiples archivos docker-compose (ej: docker-compose.prod.yml) en lugar de solo perfiles?
- A) Los perfiles son más lentos
- B) Los archivos separados permiten hacer override completo de cualquier configuración incluyendo builds, recursos, y variables de entorno específicas del entorno
- C) Los perfiles no funcionan en producción
- D) Los archivos separados usan menos disco