All Articles

What is a Docker Volume? Explained Simply for Beginners (2026)

Containers lose all data when they stop — Docker volumes fix that. Here's what Docker volumes are, how they work, the difference between volumes, bind mounts, and tmpfs, and when to use each.

DevOpsBoysApr 22, 20265 min read
Share:Tweet

When a Docker container stops, everything inside it disappears. The database you wrote data to, the log files, the uploaded files — gone. Unless you use a Docker volume.

Docker volumes are how you persist data in containers. This guide explains what they are and exactly how to use them.


The Problem: Containers Are Ephemeral

Containers are designed to be stateless. You start one, it does its job, you stop it. The next time you start it, it starts fresh.

This is great for web servers and API services — they shouldn't store state anyway. But it's a problem for:

  • Databases (PostgreSQL, MySQL, MongoDB)
  • File uploads
  • Application logs
  • Configuration that changes at runtime

Without volumes, you lose this data every time the container restarts.


What is a Docker Volume?

A Docker volume is a directory on the host machine that Docker manages and mounts inside a container. Data written to that directory persists even when the container stops or is deleted.

Host Machine                Container
┌─────────────────┐         ┌─────────────────┐
│                 │         │                 │
│  /var/lib/      │ ←mount→ │  /var/lib/      │
│  docker/        │         │  postgresql/    │
│  volumes/       │         │  data           │
│  mydb/_data/    │         │                 │
└─────────────────┘         └─────────────────┘

The data lives on the host. The container just reads and writes to it.


Three Types of Docker Storage

Docker has three ways to persist or share data:

Docker manages the storage location. You don't need to know where on the host the data lives.

bash
# Create a named volume
docker volume create mydata
 
# Use it when running a container
docker run -d \
  --name postgres \
  -v mydata:/var/lib/postgresql/data \
  postgres:16

Where is the data stored on the host?

bash
docker volume inspect mydata
# "Mountpoint": "/var/lib/docker/volumes/mydata/_data"

2. Bind Mounts

You specify exactly which directory on the host to mount. The container uses that directory directly.

bash
docker run -d \
  --name nginx \
  -v /home/shubham/website:/usr/share/nginx/html:ro \
  nginx:latest

/home/shubham/website on your host is mounted as /usr/share/nginx/html inside the container. Read-only (:ro).

Common use case: Mounting your source code during development so changes reflect immediately without rebuilding the image.

bash
# Development workflow
docker run -d \
  --name myapp-dev \
  -v $(pwd):/app \
  -p 3000:3000 \
  myapp:dev npm run dev

3. tmpfs Mounts

Stored in RAM only. Fast, but disappears when the container stops. Useful for sensitive temporary data.

bash
docker run -d \
  --name myapp \
  --tmpfs /tmp \
  --tmpfs /run \
  myapp:latest

Volumes vs Bind Mounts — When to Use Which

SituationUse
Database data (PostgreSQL, MySQL, Redis)Volume
Dev environment — mount source codeBind Mount
Production file uploadsVolume
Sharing config files with containersBind Mount
Sensitive temporary data (tokens, certs)tmpfs
Production deploymentsVolume (Docker manages permissions)

Why volumes over bind mounts in production:

  • Docker manages permissions automatically
  • Works the same on any host (no hardcoded paths)
  • Easy to backup and migrate
  • Can be shared between containers

Docker Compose with Volumes

In real projects, you define volumes in docker-compose.yml:

yaml
version: '3.9'
 
services:
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: myapp
    volumes:
      - pgdata:/var/lib/postgresql/data  # Named volume
    ports:
      - "5432:5432"
 
  redis:
    image: redis:7-alpine
    volumes:
      - redisdata:/data
 
  app:
    image: myapp:latest
    volumes:
      - ./config:/app/config:ro  # Bind mount for config files
      - uploads:/app/uploads     # Named volume for user uploads
    depends_on:
      - db
      - redis
 
volumes:
  pgdata:      # Docker creates and manages this
  redisdata:
  uploads:

The named volumes (pgdata, redisdata, uploads) are created automatically when you run docker-compose up.


Common Volume Commands

bash
# List all volumes
docker volume ls
 
# Inspect a volume (find where data is stored)
docker volume inspect mydata
 
# Remove a volume (WARNING: deletes all data in it)
docker volume rm mydata
 
# Remove all unused volumes
docker volume prune
 
# Create a volume manually
docker volume create mydata

How to Backup a Docker Volume

bash
# Backup volume data to a tar file
docker run --rm \
  -v mydata:/data \
  -v $(pwd):/backup \
  ubuntu \
  tar czf /backup/mydata-backup.tar.gz /data
 
# Restore from backup
docker run --rm \
  -v mydata:/data \
  -v $(pwd):/backup \
  ubuntu \
  tar xzf /backup/mydata-backup.tar.gz -C /

This spins up a temporary Ubuntu container, mounts both the volume and a local backup directory, and runs tar.


Sharing Volumes Between Containers

Multiple containers can share the same volume:

yaml
services:
  app:
    image: myapp:latest
    volumes:
      - logs:/var/log/app
 
  log-processor:
    image: fluentd:latest
    volumes:
      - logs:/var/log/input  # Same volume, different path
 
volumes:
  logs:

app writes logs to /var/log/app. log-processor reads from /var/log/input. They're the same directory.


What Happens to Volumes When You Delete a Container?

bash
# Delete container — volume data is SAFE
docker rm mycontainer
 
# Delete container AND its anonymous volumes
docker rm -v mycontainer
 
# Named volumes survive until you explicitly delete them
docker volume rm mydata  # This deletes the data

Named volumes persist until you explicitly delete them. This is why your database data survives even when you remove the container.


Gotcha: Volume Permissions

If your container runs as a non-root user and the volume is owned by root, you'll get permission errors.

dockerfile
# In your Dockerfile
RUN chown -R node:node /app/uploads
USER node

Or at runtime:

bash
docker run --user 1000:1000 -v mydata:/app/data myapp:latest

Check which UID your container's process runs as and make sure the volume directory has matching ownership.


Learn More

Docker volumes are one of the fundamentals you'll use in every real project. The official Docker documentation on volumes is excellent. For hands-on learning, Docker & Kubernetes: The Practical Guide on Udemy covers volumes in depth with real projects.

Once you understand volumes, you'll never lose container data again.

Newsletter

Stay ahead of the curve

Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.

Related Articles

Comments