top of page

Docker Volumes Explained: A Step-by-Step Guide (With and Without Volumes)


If you've ever restarted a Docker container and watched all your data disappear, this post is for you. We're going to walk through why Docker volumes exist, what happens when you don't use them, and then do a full hands-on comparison step by step — with room for you to drop in your own screenshots as you follow along.


Table of Contents


What Problem Are We Solving?

By default, Docker containers are ephemeral. Any file a container writes lives inside the container's writable layer. The moment you remove that container (docker rm), all of that data is gone forever — including databases, uploaded files, logs, or configuration changes.

Docker Volumes solve this by storing data outside the container's lifecycle, on the host machine (managed by Docker), so it persists across container restarts, removals, and even recreation.



Part 1: Life Without Docker Volumes

Let's prove the problem exists before we fix it. We'll spin up a simple database container, write some data, delete the container, and watch it vanish.

Step 1.1 — Run a container without a volume

docker run -d --name mysql-no-volume -e MYSQL_ROOT_PASSWORD=root123 mysql:8.0

This starts a MySQL container. All of MySQL's data files (/var/lib/mysql) live inside the container's own filesystem layer — nowhere else.



Step 1.2 — Connect and create some data

docker exec -it mysql-no-volume mysql -uroot -proot123

Inside the MySQL shell:

CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (id INT, name VARCHAR(50));
INSERT INTO users VALUES (1, 'Alice');
SELECT * FROM users;

Exit the shell:

EXIT;

Step 1.3 — Stop and remove the container

docker stop mysql-no-volume
docker rm mysql-no-volume

Step 1.4 — Recreate the container and check for data

docker run -d --name mysql-no-volume -e MYSQL_ROOT_PASSWORD=root123 mysql:8.0
docker exec -it mysql-no-volume mysql -uroot -proot123 -e "SHOW DATABASES;"

Result: testdb is gone. All the data you created is permanently lost, because it lived inside the deleted container's writable layer.


This is the core pain point: containers are meant to be disposable, but your data usually isn't.


Part 2: Life With Docker Volumes

Now let's fix it using a named volume.

Step 2.1 — Create a named volume

docker volume create mysql-data

Verify it exists:

docker volume ls

Step 2.2 — Run a container using that volume

docker run -d --name mysql-with-volume \
  -e MYSQL_ROOT_PASSWORD=root123 \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

Here, -v mysql-data:/var/lib/mysql tells Docker: "Mount the volume mysql-data at path /var/lib/mysql inside the container." Now MySQL's data directory is backed by the volume, not the container's internal layer.



Step 2.3 — Create data again

docker exec -it mysql-with-volume mysql -uroot -proot123
CREATE DATABASE testdb;
USE testdb;
CREATE TABLE users (id INT, name VARCHAR(50));
INSERT INTO users VALUES (1, 'Alice');
SELECT * FROM users;
EXIT;

Step 2.4 — Destroy the container (but not the volume)

docker stop mysql-with-volume
docker rm mysql-with-volume

Note: we removed the container, but the volume (mysql-data) still exists independently.

docker volume ls

Step 2.5 — Recreate the container with the same volume

docker run -d --name mysql-with-volume \
  -e MYSQL_ROOT_PASSWORD=root123 \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0
docker exec -it mysql-with-volume mysql -uroot -proot123 -e "SHOW DATABASES; SELECT * FROM testdb.users;"

Result: testdb and Alice's row are exactly where you left them.


Side-by-Side Comparison Table

Aspect

Without Volumes

With Volumes

Data location

Inside container's writable layer

Managed by Docker, outside the container

Data on container removal

Lost permanently

Persists

Sharing data between containers

Not possible

Multiple containers can mount the same volume

Backup / migration

Difficult (must export from inside container)

Easy (docker run --rm -v ... backup pattern, or copy the volume path)

Performance (Linux)

Fine, but irrelevant since data isn't durable

Native filesystem performance, no overhead

Managed by Docker CLI

No

Yes (docker volume create/ls/inspect/rm)

Best for

Truly disposable/stateless containers (e.g., short scripts)

Databases, uploads, logs, configs, anything stateful



Bind Mounts vs Named Volumes

While we're here, it's worth understanding the other common way to persist data — bind mounts.

docker run -d --name mysql-bind-mount \
  -e MYSQL_ROOT_PASSWORD=root123 \
  -v /home/user/mysql-data:/var/lib/mysql \
  mysql:8.0

Named Volume

Bind Mount

Managed by

Docker

You (manual host path)

Location

/var/lib/docker/volumes/...

Any path you choose on host

Portability

High (works the same across machines)

Lower (depends on host path existing)

Use case

Production, databases

Local development, sharing source code into a container

Common Volume Commands Cheat Sheet

# Create a volume
docker volume create my-volume

# List all volumes
docker volume ls

# Inspect a volume (see its host path, driver, etc.)
docker volume inspect my-volume

# Remove a specific volume
docker volume rm my-volume

# Remove all unused (dangling) volumes
docker volume prune

# Mount a volume when running a container
docker run -v my-volume:/path/in/container my-image

Wrapping Up

The core lesson: containers should be disposable, data usually shouldn't be. Docker volumes decouple the two, letting you freely recreate, upgrade, or scale containers without ever touching the data they depend on.

A quick mental model to keep:

  • No volume → data lives and dies with the container.

  • Named volume → data outlives the container, managed by Docker.

  • Bind mount → data outlives the container, managed by you, tied to a specific host path.


$50

Product Title

Product Details goes here with the simple product description and more information can be seen by clicking the see more button. Product Details goes here with the simple product description and more information can be seen by clicking the see more button

$50

Product Title

Product Details goes here with the simple product description and more information can be seen by clicking the see more button. Product Details goes here with the simple product description and more information can be seen by clicking the see more button.

$50

Product Title

Product Details goes here with the simple product description and more information can be seen by clicking the see more button. Product Details goes here with the simple product description and more information can be seen by clicking the see more button.

Recommended Products For This Post
 
 
 

Recent Posts

See All

Comments


© 2026 by neoaitech.com

  • Linkedin
  • Facebook
  • Twitter
  • Instagram

B608, 11 K County, Pune, Maharashtra, India

bottom of page