Docker Volumes

Containers are ephemeral by default — all data written inside the container's filesystem is lost when the container is removed. Docker volumes provide persistent storage that survives container removal. Understanding the difference between named volumes (managed by Docker), bind mounts (mapping a host path into the container), and tmpfs mounts (in-memory, for secrets) is essential for correctly persisting application data.

Storage types

Docker storage options:
  Named volume:
    Docker manages storage in /var/lib/docker/volumes/
    Portable, can be backed up with docker commands
    Best for: database data, application state

  Bind mount:
    Maps a host directory/file into the container
    Host manages the path and permissions
    Best for: development (live code reload), config files

  tmpfs mount:
    In-memory storage, never written to disk
    Lost when container stops
    Best for: sensitive data (passwords, tokens) that should not persist

Named volumes

# Create a named volume:
docker volume create myapp-data

# Use volume in a container:
docker run -d   --name mysql-db   -v myapp-data:/var/lib/mysql   -e MYSQL_ROOT_PASSWORD=secret   mysql:8.0

# List volumes:
docker volume ls

# Inspect a volume (shows mountpoint on host):
docker volume inspect myapp-data

docker volume inspect output

[{
    "Name": "myapp-data",
    "Driver": "local",
    "Mountpoint": "/var/lib/docker/volumes/myapp-data/_data",
    "CreatedAt": "2025-06-09T14:30:00Z"
}]
# Remove unused volumes:
docker volume prune    # Removes volumes not attached to any container

Bind mounts

# Mount a specific host directory:
docker run -d   --name nginx   -v /var/www/mysite:/usr/share/nginx/html:ro \   # :ro = read-only
  -p 80:80   nginx:alpine

# Development: mount code directory (live reload):
docker run -d   --name dev-server   -v /home/irfan/myapp:/app \   # Code changes reflect immediately
  -p 3000:3000   node:20-alpine   node /app/server.js

📝 NOTE: Bind mounts create a dependency on the host path structure. If the host path does not exist, Docker creates it (as a directory). For production, prefer named volumes for database data and only use bind mounts for config files and development code.

Volume backup and restore

# Backup a named volume to a tar archive:
docker run --rm   -v myapp-data:/data   -v /backup:/backup   alpine tar czf /backup/myapp-data-$(date +%Y%m%d).tar.gz -C /data .

# Restore from backup to a volume:
docker run --rm   -v myapp-data:/data   -v /backup:/backup   alpine tar xzf /backup/myapp-data-20250609.tar.gz -C /data

# Alternative: access volume data directly on host:
sudo ls /var/lib/docker/volumes/myapp-data/_data/

Conclusion

Named volumes for persistent application data, bind mounts for configuration files and development workflows. Always define volumes explicitly in your docker run command or docker-compose.yml for any data you care about — never rely on container-internal storage for anything that must survive a container recreation. Run docker volume prune periodically to clean up orphaned volumes, but inspect them first: docker volume ls to confirm they are not in use by any container.

FAQ

Is Docker Volumes important for Ubuntu administrators?+

Yes. It supports practical Ubuntu administration because it connects directly to server reliability, security, troubleshooting, or daily operations.

Should I practice this on a live server?+

Use a lab VM first. After you understand the command output and rollback path, apply the workflow carefully on real systems.

What should I do after reading this article?+

Run the practice commands, write down what each one shows, and continue to the next article in the Ubuntu roadmap.

Need help with Ubuntu administration?

Work directly with Muhammad Irfan Aslam for Ubuntu Server, Linux, cloud, Docker, DevOps, CI/CD, or infrastructure troubleshooting support.

Hire Me for Support