HxHippy

Volumes in Compose

Manage persistent data with volumes in Docker Compose.

Last updated: 2025-01-15

Docker Compose Volumes

Persist data and share files between host and containers.

Volume Types

Named Volumes

services:
  db:
    image: postgres
    volumes:
      - postgres-data:/var/lib/postgresql/data

  redis:
    image: redis
    volumes:
      - redis-data:/data

volumes:
  postgres-data:
  redis-data:

Bind Mounts

services:
  app:
    volumes:
      # Development: mount source code
      - ./src:/app/src
      - ./config:/app/config:ro   # Read-only

  nginx:
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./html:/usr/share/nginx/html

Anonymous Volumes

services:
  app:
    volumes:
      - /app/node_modules   # Preserve container's node_modules

Volume Configuration

volumes:
  db-data:
    driver: local

  # With options
  app-data:
    driver: local
    driver_opts:
      type: none
      device: /data/app
      o: bind

  # External volume (pre-existing)
  shared-data:
    external: true
    name: my-shared-volume

Development vs Production

Development

# docker-compose.dev.yml
services:
  app:
    volumes:
      - .:/app                    # Full source mount
      - /app/node_modules         # Exclude node_modules
    command: npm run dev

Production

# docker-compose.prod.yml
services:
  app:
    volumes:
      - app-logs:/app/logs        # Only logs
      - app-uploads:/app/uploads  # User uploads

volumes:
  app-logs:
  app-uploads:

Common Patterns

Database with Initialization

services:
  db:
    image: postgres:16
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro

  mysql:
    image: mysql:8
    volumes:
      - mysql-data:/var/lib/mysql
      - ./init:/docker-entrypoint-initdb.d:ro

volumes:
  postgres-data:
  mysql-data:

Sharing Data Between Services

services:
  app:
    volumes:
      - shared-uploads:/app/uploads

  nginx:
    volumes:
      - shared-uploads:/usr/share/nginx/html/uploads:ro

volumes:
  shared-uploads:

Config Files

services:
  nginx:
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./certs:/etc/nginx/certs:ro

Volume Commands

# List volumes
docker volume ls

# Inspect volume
docker volume inspect project_postgres-data

# Remove volumes with compose
docker compose down -v

# Backup volume
docker run --rm -v project_db-data:/data -v $(pwd):/backup \
  alpine tar cvf /backup/db-backup.tar /data

# Restore volume
docker run --rm -v project_db-data:/data -v $(pwd):/backup \
  alpine tar xvf /backup/db-backup.tar -C /

Complete Example

services:
  app:
    build: .
    volumes:
      - app-uploads:/app/uploads
      - app-logs:/app/logs
      - ./config/app.json:/app/config.json:ro

  db:
    image: postgres:16
    volumes:
      - db-data:/var/lib/postgresql/data
      - ./init-scripts:/docker-entrypoint-initdb.d:ro
    environment:
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    secrets:
      - db_password

  nginx:
    image: nginx:alpine
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - app-uploads:/var/www/uploads:ro
      - nginx-cache:/var/cache/nginx

volumes:
  app-uploads:
  app-logs:
  db-data:
  nginx-cache:

secrets:
  db_password:
    file: ./secrets/db_password.txt
intermediate Docker Compose Updated 2025-01-15
  • docker compose
  • volumes
  • persistence
  • bind mounts