Guía rápida de Docker Compose - Comandos más útiles con ejemplos

Por cierto, docker-compose es diferente de docker compose...

Índice

Aquí tienes un cheatsheet de Docker Compose con ejemplos anotados para ayudarte a dominar los archivos y comandos de Compose rápidamente.

esquema de docker-compose

Referencia del archivo Compose: docker-compose.yml

Estructura básica:

version: '3'       # Versión del formato del archivo de Compose

services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"   # Puerto del host 8080: Puerto del contenedor 80
  db:
    image: postgres
    environment:            # Variables de entorno
      POSTGRES_PASSWORD: example
    volumes:
      - db_data:/var/lib/postgresql/data

networks:          # Red personalizada
  appnet:
    driver: bridge

volumes:           # Volumen con nombre
  db_data:
  • services: Cada contenedor en tu aplicación de múltiples contenedores. En el ejemplo anterior tenemos dos servicios: web y db.
  • networks & volumes: Define redes aisladas y almacenamiento persistente - aquí tenemos la red appnet y el volumen db_data.

Ejemplos

Servicio único con mapeo de puertos

services:
  app:
    build: .
    ports:
      - "8000:80"   # Puerto del host 8000: Puerto del contenedor 80

Expone la aplicación en el puerto 8000 del host y construye desde el Dockerfile en el directorio actual.

Multi-servicio con volumen compartido y red personalizada

version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - type: bind
        source: ./app
        target: /app
    networks:
      - mynet
  db:
    image: postgres
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - mynet

networks:
  mynet:

volumes:
  db_data:

Web y DB en la misma red; DB utiliza un volumen con nombre persistente - db_data.

Usando contexto de construcción y ruta del Dockerfile

Puedes construir una imagen de Docker según demanda desde el Dockerfile especificado en docker-compose.yml.

services:
  app:
    build:
      context: .
      dockerfile: docker/MyDockerfile

Compartir datos entre servicios

services:
  web:
    image: nginx
    volumes:
      - shared_data:/usr/share/nginx/html
  worker:
    image: myworker
    volumes:
      - shared_data:/usr/src/app/data

volumes:
  shared_data:

Ambos servicios acceden al mismo volumen (para archivos estáticos o intercambio de datos) - shared_data.

Opciones avanzadas del archivo Compose

  • environment: Establece variables de entorno para los contenedores.
  • depends_on: Controla el orden de inicio de los servicios.
  • deploy.replicas: Escala el servicio en modo Swarm.

Ejemplo:

services:
  web:
    image: nginx
    deploy:
      replicas: 3
    depends_on:
      - db

Inicia 3 instancias de web; solo controla el orden de inicio (no la disponibilidad).

Comandos esenciales de Docker Compose

Comando Descripción Uso de ejemplo
docker-compose up Crea y inicia contenedores docker-compose up
docker-compose up -d Ejecutar en segundo plano docker-compose up -d
docker-compose exec Ejecutar un comando en un contenedor en ejecución docker-compose exec web bash
docker-compose build Construir/reconstruir imágenes docker-compose build
docker-compose down Detener y eliminar contenedores, redes, volúmenes e imágenes docker-compose down
docker-compose logs -f Ver y seguir los registros docker-compose logs -f
docker-compose ps Listar contenedores en ejecución docker-compose ps
docker-compose run Ejecutar comandos de una sola vez (ignora el comando en el archivo Compose) docker-compose run web python manage.py migrate
docker-compose stop Detener contenedores en ejecución (se pueden reiniciar con start) docker-compose stop
docker-compose restart Reiniciar servicios docker-compose restart web
docker-compose pull Descargar imágenes de servicio docker-compose pull
docker-compose rm Eliminar contenedores detenidos de servicios docker-compose rm web
docker-compose config Validar y ver el archivo Compose docker-compose config
docker-compose up --scale web=3 Iniciar múltiples instancias de un servicio docker-compose up --scale web=3

Patrones comunes de Compose

  • Bases de datos con datos persistentes

    services:
      mysql:
        image: mysql
        environment:
          MYSQL_ROOT_PASSWORD: password
        volumes:
          - mysql_data:/var/lib/mysql
    
    volumes:
      mysql_data:
    

    Los datos de la base de datos persisten en el volumen mysql_data incluso tras reiniciar los contenedores.

  • Montaje de código para desarrollo

    services:
      app:
        build: .
        volumes:
          - .:/app
    

    Editar código en el host en vivo, reflejado automáticamente en el contenedor.

Banderas útiles

  • -d: Modo de detención (ejecutar en segundo plano).
  • --build: Forzar la reconstrucción de imágenes antes de iniciar.
  • --force-recreate: Reconstruir contenedores incluso si no han cambiado.
  • --remove-orphans: Eliminar contenedores no definidos en el archivo Compose.

Definir y personalizar servicios

Puedes definir y personalizar servicios, redes y volúmenes en Docker Compose aprovechando el archivo docker-compose.yml, que centraliza todas las necesidades de configuración y orquestación de tu aplicación.

  • Servicios se definen bajo la clave services.
  • Cada servicio representa una configuración de contenedor, donde puedes establecer:
    • Image: Seleccionar una imagen de Docker Hub u otro registro.
    • Ports: Mapear puertos del contenedor a puertos del host.
    • Variables de entorno: Pasar valores de configuración.
    • Volúmenes: Persistir datos o compartir archivos/carpetas con el host u otros servicios.
    • Redes: Controlar qué redes puede acceder el servicio.

Ejemplo:

services:
  web:
    image: nginx:latest
    ports:
      - "8080:80"   # Puerto del host 8080: Puerto del contenedor 80
    environment:
      - NGINX_HOST=localhost
    volumes:
      - web_data:/usr/share/nginx/html
    networks:
      - frontend

  db:
    image: postgres:13
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - backend
  • Aquí, el servicio web utiliza la imagen nginx, establece una variable de entorno, adjunta un volumen, abre el puerto 80 como 8080 en el host y se conecta a la red frontend. El servicio db hace algo similar para PostgreSQL.

Personalizar redes

  • Redes controlan qué servicios pueden comunicarse. Compose crea una red por defecto, pero puedes definir más, especificar controladores personalizados, establecer opciones y determinar qué servicio se une a qué red para un aislamiento fino.
  • Define redes en el nivel superior bajo networks, y lista qué redes debe adjuntar un servicio con la clave networks a nivel de servicio.

Ejemplo:

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    driver_opts:
      com.docker.network.bridge.host_binding_ipv4: "127.0.0.1"
  • Adjunta redes a servicios:
services:
  app:
    networks:
      - frontend
      - backend
  db:
    networks:
      - backend
  • Esta configuración permite que el servicio app acceda a usuarios en las redes frontend y backend, mientras que db solo es accesible dentro de la backend.

Personalizar volúmenes

  • Volúmenes se definen bajo la clave volumes en el nivel superior. Móntalos en contenedores usando la clave volumes bajo un servicio.
  • Los volúmenes pueden tener nombres, usar controladores personalizados y compartirse entre múltiples servicios para persistencia de datos y compartir datos.

Ejemplo:

volumes:
  web_data:                # Volumen con nombre para contenido web
  db_data:                 # Volumen con nombre para base de datos

services:
  web:
    volumes:
      - web_data:/usr/share/nginx/html

  db:
    volumes:
      - db_data:/var/lib/postgresql/data
  • En este ejemplo, web_data se persiste y está disponible para cualquier contenedor que lo monte. db_data asegura que los datos de la base de datos nunca se pierdan al recrear el contenedor.
  • Puedes definir montajes de tipo bind con opciones de controlador personalizado para casos avanzados:
volumes:
  db_data:
    driver: local
    driver_opts:
      type: none
      device: /data/db_data
      o: bind
  • Esta configuración establece un montaje de tipo bind desde la ruta del host /data/db_data dentro del contenedor.

Resumen de buenas prácticas:

  • Usa el nombre del servicio como nombre de host DNS para la comunicación entre servicios.
  • Adjunta servicios a múltiples redes según sea necesario para controlar el acceso.
  • Usa volúmenes con nombre para almacenamiento persistente y compartir datos.
  • Define todo usando YAML, lo que permite el control de versiones y scripts de despliegue fáciles.

Archivos Compose múltiples

Para organizar configuraciones complejas de múltiples servicios en Docker Compose, puedes usar archivos Compose múltiples y archivos de sobrescritura, permitiendo configuraciones modulares, específicas del entorno y escalables. Aquí te explico cómo funciona:

  1. Estructura de archivos base y de sobrescritura
  • Crea un archivo base (compose.yaml o docker-compose.yml) que contenga todas las definiciones de servicios comunes y por defecto.
  • Agrega archivos de sobrescritura específicos del entorno (por ejemplo, docker-compose.override.yml, docker-compose.dev.yml, docker-compose.prod.yml).

Ejemplo de estructura de archivos:

/proyecto
|-- docker-compose.yml           # Configuración base
|-- docker-compose.override.yml  # Sobrescrituras locales/dev (aplicadas automáticamente)
|-- docker-compose.prod.yml      # Sobrescrituras de producción
|-- docker-compose.test.yml      # Sobrescrituras de prueba (si es necesario)

La configuración base define servicios principales, mientras que cada sobrescritura personaliza ajustes para un entorno o caso específico.

  1. Cómo funcionan los archivos de sobrescritura
  • Fusión: Cuando ejecutas docker compose up, Docker Compose fusiona el archivo base con cualquier archivo de sobrescritura en orden; los archivos posteriores sobrescriben, extienden o añaden ajustes a los archivos anteriores.
  • Sobrescritura de campos: Si un servicio o campo se define en múltiples archivos, el valor del último archivo especificado se usa. Los campos nuevos se añaden.

Ejemplo de fusión:

  • docker-compose.yml:
    services:
      web:
        image: myapp
        ports:
          - "8000:80"
    
  • docker-compose.override.yml:
    services:
      web:
        environment:
          - DEBUG=true
    
  • Resultado: El servicio web usa tanto la imagen y el puerto base como la variable de entorno sobrescrita DEBUG.
  1. Uso de comandos para múltiples archivos
  • Comportamiento por defecto: Si está presente, Docker Compose carga automáticamente docker-compose.override.yml junto con docker-compose.yml al ejecutar cualquier comando.
  • Especificar archivos manualmente: Usa banderas -f para controlar qué archivos se fusionan y en qué orden:
    docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
    
    • Esto ignora el sobrescritura por defecto y usa ajustes específicos de producción.
  1. Estrategias prácticas de organización
  • Separación por entorno: Usa un sobrescritura por entorno: dev, test, prod, etc.
  • Microservicios y equipos: Separa la configuración en archivos distintos para diferentes servicios o equipos, y combínalos según sea necesario.
  • Conmutadores de características: Archivos adicionales pueden introducir o eliminar servicios o configuraciones opcionales para necesidades temporales (por ejemplo, un compose.debug.yml para registro adicional).
  1. Ventajas
  • Claridad: Mantiene archivos individuales pequeños y enfocados.
  • Escalabilidad: Añade fácilmente nuevos servicios, entornos o ajustes.
  • Mantenibilidad: Solo cambia o revisa las secciones relevantes para un despliegue específico.
  1. Ejemplo: Cambiar entornos

Desarrollo:

docker compose -f docker-compose.yml -f docker-compose.dev.yml up

Producción:

docker compose -f docker.docker-compose.yml -f docker-compose.prod.yml up -d

Cada entorno obtiene solo la configuración necesaria para él, con toda la configuración compartida en el archivo base.

Organizar configuraciones complejas de Compose con múltiples archivos - y aprovechar el sistema de sobrescritura/fusión - asegura modularidad, personalización específica del entorno y escalabilidad fácil para aplicaciones Docker con múltiples servicios.

Enlaces útiles