Docker Compose Volume

Avanzado
Docker
Docker
Actualizado: 13/08/2025

¡Desbloquea el curso de Docker completo!

IA
Ejercicios
Certificado
Entrar

Mira la lección en vídeo

Accede al vídeo completo de esta lección y a más contenido exclusivo con el Plan Plus.

Desbloquear Plan Plus

Declarar volúmenes en Compose

Docker Compose permite definir volúmenes de manera declarativa utilizando la sección top-level volumes en el archivo compose.yaml. Esta aproximación simplifica significativamente la gestión de datos persistentes en aplicaciones multi-contenedor, eliminando la necesidad de crear volúmenes manualmente antes de ejecutar los servicios.

Sección top-level volumes

La declaración de volúmenes en Compose se realiza al mismo nivel que services, creando un inventario centralizado de todos los volúmenes que utilizarán los contenedores:

services:
  web:
    image: nginx:1.27
    volumes:
      - static_files:/usr/share/nginx/html
      
  database:
    image: mysql:8.4
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  static_files:
  mysql_data:

Esta estructura declarativa permite a Docker Compose gestionar automáticamente el ciclo de vida de los volúmenes, creándolos si no existen y manteniéndolos disponibles para todos los servicios que los necesiten.

Configuración de volúmenes nombrados

Los volúmenes pueden incluir configuración específica utilizando el formato extendido. El driver por defecto es local, pero podemos especificarlo explícitamente junto con opciones adicionales:

volumes:
  mysql_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /opt/mysql-data
      
  postgres_data:
    driver: local
    labels:
      com.example.description: "Database volume for PostgreSQL"
      com.example.department: "backend"

Las etiquetas proporcionan metadatos útiles para organizar y documentar volúmenes en entornos empresariales, facilitando su identificación y gestión.

Volúmenes externos

Docker Compose puede referenciar volúmenes externos que ya existen en el sistema, evitando que se creen automáticamente durante el despliegue:

services:
  app:
    image: node:24-alpine
    volumes:
      - shared_storage:/app/uploads

volumes:
  shared_storage:
    external: true

Esta funcionalidad es especialmente útil cuando múltiples stacks de Compose necesitan compartir datos, o cuando los volúmenes son gestionados externamente por herramientas de administración.

Para volúmenes externos con nombres diferentes al especificado en Compose:

volumes:
  app_data:
    external: true
    name: production-app-data

Ejemplo práctico con base de datos

Un caso típico combina volúmenes internos y configuración específica para servicios de base de datos:

services:
  web:
    image: nginx:1.27
    ports:
      - "80:80"
    volumes:
      - web_content:/usr/share/nginx/html
    depends_on:
      - database

  database:
    image: postgresql:17-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: developer
      POSTGRES_PASSWORD: secret123
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - postgres_backups:/backups

volumes:
  web_content:
    driver: local
    
  postgres_data:
    driver: local
    labels:
      com.myapp.service: "database"
      com.myapp.environment: "development"
      
  postgres_backups:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /opt/backups/postgres

Esta configuración crea volúmenes dedicados para datos de PostgreSQL y backups, con el directorio de backups mapeado a una ubicación específica del host mediante bind mount configurado como volumen nombrado.

Nomenclatura y namespacing

Docker Compose aplica prefijos automáticos a los nombres de volúmenes basados en el nombre del proyecto. Por defecto, utiliza el nombre del directorio que contiene el archivo compose.yaml:

# Archivo en directorio 'myapp'
volumes:
  database_data:  # Se crea como 'myapp_database_data'

Para controlar el nombre del proyecto y, por tanto, el prefijo:

docker compose -p production up -d
# Los volúmenes tendrán prefijo 'production_'

Esta estrategia de naming evita conflictos entre diferentes proyectos y facilita la identificación de recursos en sistemas con múltiples aplicaciones containerizadas.

Montajes y permisos

Guarda tu progreso

Inicia sesión para no perder tu progreso y accede a miles de tutoriales, ejercicios prácticos y nuestro asistente de IA.

Progreso guardado
Asistente IA
Ejercicios
Iniciar sesión gratis

Más de 25.000 desarrolladores ya confían en CertiDevs

Los montajes de volúmenes en Docker Compose admiten diferentes tipos y configuraciones que determinan cómo se comportan los datos y qué permisos tienen los contenedores sobre ellos. La sintaxis extendida proporciona control granular sobre estos aspectos, permitiendo configuraciones específicas para cada caso de uso.

Sintaxis de montaje extendida

Docker Compose ofrece dos formas de declarar montajes: la sintaxis corta (volumen:ruta) y la sintaxis extendida que proporciona mayor control. La sintaxis extendida utiliza el formato de objeto con propiedades específicas:

services:
  database:
    image: mysql:8.4
    volumes:
      - type: volume
        source: mysql_data
        target: /var/lib/mysql
        read_only: false
      - type: bind
        source: ./config
        target: /etc/mysql/conf.d
        read_only: true

volumes:
  mysql_data:

Las propiedades principales son type (volume o bind), source (nombre del volumen o ruta del host), target (ruta dentro del contenedor) y read_only para controlar permisos de escritura.

Tipos de montaje: volume vs bind

Los montajes de tipo volume utilizan volúmenes gestionados por Docker, proporcionando mejor portabilidad y rendimiento. Son ideales para datos que deben persistir pero no requieren acceso directo desde el host:

services:
  postgres:
    image: postgresql:17-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: dbuser
      POSTGRES_PASSWORD: dbpass123
    volumes:
      - type: volume
        source: postgres_data
        target: /var/lib/postgresql/data
        volume:
          nocopy: false
      - type: volume
        source: postgres_logs
        target: /var/log/postgresql

volumes:
  postgres_data:
  postgres_logs:

Los montajes de tipo bind mapean directorios específicos del host al contenedor, útiles para desarrollo y configuraciones que necesitan editarse externamente:

services:
  web:
    image: nginx:1.27
    volumes:
      - type: bind
        source: ./html
        target: /usr/share/nginx/html
        read_only: true
      - type: bind
        source: ./nginx.conf
        target: /etc/nginx/nginx.conf
        read_only: true
    ports:
      - "8080:80"

Permisos de solo lectura

La opción read_only previene modificaciones accidentales y mejora la seguridad, especialmente útil para archivos de configuración y recursos estáticos:

services:
  app:
    image: node:24-alpine
    volumes:
      # Código fuente en solo lectura
      - type: bind
        source: ./src
        target: /app/src
        read_only: true
      # Directorio de escritura para logs
      - type: volume
        source: app_logs
        target: /app/logs
        read_only: false
      # Configuración protegida
      - type: bind
        source: ./config/app.json
        target: /app/config.json
        read_only: true

volumes:
  app_logs:

Gestión de permisos de usuario

Los permisos de archivos en volúmenes pueden requerir ajustes cuando los contenedores ejecutan procesos con usuarios específicos. PostgreSQL, por ejemplo, requiere que el directorio de datos pertenezca al usuario postgres:

services:
  postgres:
    image: postgresql:17-alpine
    user: "999:999"  # UID:GID del usuario postgres
    environment:
      POSTGRES_DB: empresa
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secure456
      PGDATA: /var/lib/postgresql/data/pgdata
    volumes:
      - type: volume
        source: postgres_data
        target: /var/lib/postgresql/data
        volume:
          nocopy: false

  postgres_backup:
    image: postgresql:17-alpine
    depends_on:
      - postgres
    volumes:
      - type: volume
        source: postgres_data
        target: /var/lib/postgresql/data
        read_only: true
      - type: bind
        source: ./backups
        target: /backups
    command: >
      sh -c "pg_dump -h postgres -U admin -d empresa > /backups/backup-$$(date +%Y%m%d).sql"

volumes:
  postgres_data:

Configuración avanzada de volúmenes

Las opciones específicas de volúmenes permiten control adicional sobre el comportamiento del montaje. La opción nocopy determina si el contenido inicial del contenedor se copia al volumen:

services:
  mysql:
    image: mysql:8.4
    environment:
      MYSQL_ROOT_PASSWORD: rootpass123
      MYSQL_DATABASE: production
      MYSQL_USER: appuser
      MYSQL_PASSWORD: apppass456
    volumes:
      - type: volume
        source: mysql_data
        target: /var/lib/mysql
        volume:
          nocopy: true  # No copiar datos iniciales
      - type: bind
        source: ./mysql-config
        target: /etc/mysql/conf.d
        read_only: true
        bind:
          propagation: rprivate

volumes:
  mysql_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /opt/mysql-data

Ejemplo integral con múltiples servicios

Un stack completo que combina diferentes tipos de montajes y permisos para una aplicación web con base de datos:

services:
  nginx:
    image: nginx:1.27-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - type: bind
        source: ./nginx/nginx.conf
        target: /etc/nginx/nginx.conf
        read_only: true
      - type: volume
        source: static_content
        target: /usr/share/nginx/html
        read_only: true
      - type: bind
        source: ./ssl
        target: /etc/ssl/certs
        read_only: true

  app:
    image: node:24-alpine
    user: "1000:1000"
    working_dir: /app
    environment:
      NODE_ENV: production
      DB_HOST: database
    volumes:
      - type: bind
        source: ./app
        target: /app
        read_only: true
      - type: volume
        source: app_uploads
        target: /app/uploads
      - type: volume
        source: static_content
        target: /app/public
    depends_on:
      - database

  database:
    image: mysql:8.4
    environment:
      MYSQL_ROOT_PASSWORD: root123
      MYSQL_DATABASE: webapp
      MYSQL_USER: webuser
      MYSQL_PASSWORD: web456
    volumes:
      - type: volume
        source: mysql_data
        target: /var/lib/mysql
      - type: bind
        source: ./mysql/custom.cnf
        target: /etc/mysql/conf.d/custom.cnf
        read_only: true

volumes:
  mysql_data:
    driver: local
  app_uploads:
    driver: local  
  static_content:
    driver: local

Esta configuración establece permisos diferenciados: archivos de configuración en solo lectura, volúmenes de datos con permisos de escritura, y separación clara entre contenido estático y dinámico para optimizar rendimiento y seguridad.

Aprendizajes de esta lección de Docker

  • Comprender cómo declarar volúmenes en un archivo compose.yaml usando la sección top-level volumes.
  • Diferenciar entre volúmenes nombrados, externos y sus configuraciones específicas.
  • Aplicar la sintaxis extendida para montajes de volúmenes y bind mounts con control de permisos.
  • Gestionar permisos de usuario y opciones avanzadas como nocopy para volúmenes.
  • Configurar un stack completo con múltiples servicios y volúmenes optimizados para seguridad y rendimiento.

Completa este curso de Docker y certifícate

Únete a nuestra plataforma de cursos de programación y accede a miles de tutoriales, ejercicios prácticos, proyectos reales y nuestro asistente de IA personalizado para acelerar tu aprendizaje.

Asistente IA

Resuelve dudas al instante

Ejercicios

Practica con proyectos reales

Certificados

Valida tus conocimientos

Más de 25.000 desarrolladores ya se han certificado con CertiDevs

⭐⭐⭐⭐⭐
4.9/5 valoración