IntermediateLesson 5 of 16

📦 Volumes, Bind Mounts and Persistent Data

Containers are ephemeral — but your data does not have to be. Learn how Docker volumes and bind mounts persist data across container replacements and restarts.

🧒 Simple Explanation (ELI5)

A container is like a hotel room — clean slate on arrival, all traces gone on checkout. But volumes are like a safe in the lobby: your valuables (database files, config, logs) live there permanently, whichever room you check into. When your container is replaced, the new one connects to the same safe and finds all your data intact.

💡
When to use each

Volume — production data, databases, shared data between containers. Docker manages the location.
Bind Mount — development workflows where you want live code reloading. You control the host path.
tmpfs — in-memory temp storage, never written to disk (for secrets or ephemeral scratch data).

🔧 Technical Explanation

Volume vs Bind Mount
Named Volume
Container /var/lib/mysql
Docker managed storage
/var/lib/docker/volumes/...
vs
Bind Mount
Container /app
Host path
/home/user/myapp

💻 Volume Commands

bash
# ---- Named Volumes ----
# Create a volume explicitly
docker volume create mydata

# Mount volume when running a container
docker run -d \
  -v mydata:/var/lib/mysql \          # name:container-path
  -e MYSQL_ROOT_PASSWORD=secret \
  mysql:8

# List all volumes
docker volume ls

# Inspect a volume (see the actual host path)
docker volume inspect mydata

# Remove a volume (only when no container uses it)
docker volume rm mydata

# ---- Bind Mounts ----
# Mount current directory into container (dev hot-reload)
docker run -d \
  -v $(pwd)/src:/app/src \            # absolute host path : container path
  -p 3000:3000 \
  myapp:dev

# ---- tmpfs (memory-only) ----
docker run --tmpfs /tmp myapp

# ---- Sharing volumes between containers ----
docker run -d -v shared-logs:/logs --name writer logwriter
docker run -d -v shared-logs:/logs:ro --name reader logreader

🧪 Hands-on Exercises

  1. Run a MySQL container with a named volume: stop and remove it, start a new MySQL container mounting the same volume — verify data persists.
  2. Use a bind mount to serve local HTML files with nginx: change a file on your host and refresh the browser.
  3. Use docker volume inspect to find where Docker stores the volume files on your host.
  4. Run two containers sharing a named volume — write from one, read from the other.
⚠️
Don't use bind mounts in production

Bind mounts are tightly coupled to the host filesystem path. A typo or missing directory causes a silent empty mount. In production Kubernetes environments, use PersistentVolumeClaims instead. Bind mounts are fine for local development.

🐛 Debugging Scenario

Problem: Database container was replaced; after restart all data is gone.

bash
# Diagnose: container had no volume mount
docker inspect <old_container_id> | grep -A5 Mounts
# Output shows empty Mounts array — no volume was specified

# Fix: add a named volume to the run command
docker run -d \
  -v pgdata:/var/lib/postgresql/data \
  -e POSTGRES_PASSWORD=secret \
  postgres:15

# Verify volume was created and used
docker volume ls
docker inspect <new_container_id> | grep -A10 Mounts

🎯 Interview Questions

What is the difference between a Docker volume and a bind mount?

A volume is a Docker-managed storage area. Docker controls the host location, handles it as a Docker object (create, inspect, remove), and it works portably across any host. A bind mount links a specific host directory into the container — you control the path. Volumes are preferred for production data; bind mounts are convenient for development.

How does a named volume persist data when a container is deleted?

A volume is a separate Docker object from the container. Deleting a container (docker rm) does NOT delete associated volumes unless you use docker rm -v. The volume's data lives in Docker's storage area on the host and persists until explicitly removed with docker volume rm.

Scenario: A developer mounts their entire home directory into a container by mistake. What are the risks?

This is a significant security risk. The container process (which may run as root) has full read/write access to the host home directory — including SSH keys, .env files, browser data, and credentials. A compromised or malicious container image could exfiltrate or modify all of it. Always mount only the minimum necessary directory with the least privilege (use :ro for read-only when writes are not needed).

📋 Summary