Skip to content

Docker Volumes and Data Persistence Explained

DodaTech 2 min read

In this tutorial, you'll learn about Docker Volumes and Data Persistence Explained. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

What You'll Learn

Manage data in Docker containers — volumes, bind mounts, and how to persist, share, and back up data across container lifecycles.

Why It Matters

Containers are ephemeral by design. Without volumes, all data is lost when a container stops. Volumes are essential for databases, file uploads, and logs.

Real-World Use

Persisting PostgreSQL data across restarts, sharing source code between host and container for development, or storing uploads separately from application code.

The Data Problem

Container starts → writes data → container stops → DATA LOST

Volumes solve this by storing data outside the container's writable layer.

Three Types of Mounts

Type Managed By Use Case Persistence
Volume Docker Production data, backups Survives container removal
Bind mount You Development, config files Survives container removal
tmpfs Memory only Secrets, temp data Lost on container stop

Docker manages the storage location:

# Create a volume
docker volume create postgres-data

# Mount it
docker run -d \
  --name db \
  -v postgres-data:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=secret \
  postgres:16

# Even if container is removed, data persists
docker rm -f db

# Create a new container with same volume
docker run -d \
  --name db2 \
  -v postgres-data:/var/lib/postgresql/data \
  postgres:16

# All previous data is still there

Bind Mounts

Map a host directory into the container:

# Development: live-reload source code
docker run -d \
  -p 3000:3000 \
  -v $(pwd)/src:/app/src \
  node:20-alpine \
  npm run dev

# Mount config file
docker run -d \
  -v $(pwd)/nginx.conf:/etc/nginx/nginx.conf:ro \
  nginx:alpine

Watch out: Bind mounts can overwrite container files. Use :ro for read-only.

tmpfs Mounts

Data stored in memory, never written to disk:

docker run -d \
  --tmpfs /app/temp:noexec,nosuid,size=64m \
  nginx:alpine

# Good for:
# - API tokens
# - Session data
# - Temporary cached files

Volumes in Docker Compose

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

  app:
    build: .
    volumes:
      - ./src:/app/src        # Bind mount for dev
      - uploads:/app/uploads   # Named volume
    ports:
      - "3000:3000"

volumes:
  pgdata:
  uploads:

Backup and Restore

# Backup a volume
docker run --rm \
  -v pgdata:/source \
  -v $(pwd):/backup \
  alpine \
  tar czf /backup/pgdata-backup.tar.gz -C /source .

# Restore a volume
docker run --rm \
  -v pgdata:/target \
  -v $(pwd):/backup \
  alpine \
  tar xzf /backup/pgdata-backup.tar.gz -C /target

# Copy between containers
docker run --rm \
  -v source-volume:/from \
  -v target-volume:/to \
  alpine \
  sh -c "cp -a /from/. /to/"

Common Patterns

Development

# Bind mount source code, named volume for node_modules
docker run -d \
  -v $(pwd):/app \
  -v /app/node_modules \  # Anonymous volume prevents overwrite
  -p 3000:3000 \
  node:20-alpine \
  npm run dev

Production

# Use named volumes, avoid bind mounts
volumes:
  - data:/data
  - config:/etc/app/config:ro

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro