One of the most critical concepts in Docker is understanding data persistence. By default, any data created inside a container is lost when the container is removed. This tutorial demonstrates the problem of data loss and introduces Docker volumes as the solution for persistent storage.
🎯 What You'll Learn: In this comprehensive data persistence tutorial, you'll discover:
- Why container data is lost when containers are removed
- Demonstrating data loss with practical examples
- Introduction to Docker volumes and their benefits
- Creating and inspecting Docker volumes
- Mounting volumes to containers for persistent storage
- Understanding volume lifecycle and data retention
- Practical examples with web servers and databases
Time to read: ~12 minutes | Difficulty: Beginner to Intermediate
🚀 The Container Data Persistence Problem
Docker containers are designed to be ephemeral - they can be created, destroyed, and recreated quickly. However, this creates a challenge: what happens to data when containers are removed?
Prerequisites
Before we begin, make sure you have:
- Docker installed and running on your system
- Basic understanding of Docker containers
- Familiarity with Docker commands (run, rm, exec)
- Understanding of Linux file system basics
🔍 Step 1: Demonstrating Container Data Loss
Let's start by demonstrating the fundamental problem - when container data disappears.
Creating a Container with Data
docker run -it --name temp-container ubuntu:20.04 bash
Docker downloads the Ubuntu 20.04 image and starts an interactive container:
Unable to find image 'ubuntu:20.04' locally
20.04: Pulling from library/ubuntu
13b7e930469f: Pull complete
Digest: sha256:8feb4d8ca5354def3d8fce243717141ce31e2c428701f6682bd2fafe15388214
Status: Downloaded newer image for ubuntu:20.04
root@a10794aab816:/#
Adding Data Inside the Container
Inside the running container, let's create some data:
echo "This is temporary data" > /tmp/test-file.txt
cat /tmp/test-file.txt
ls -la /tmp/
The container shows our created data:
# Output of cat command
This is temporary data
# Output of ls -la /tmp/
total 4
drwxrwxrwt. 1 root root 27 Sep 12 14:35 .
drwxr-xr-x. 1 root root 17 Sep 12 14:34 ..
-rw-r--r--. 1 root root 23 Sep 12 14:35 test-file.txt
Exit the container:
exit
Removing the Container
docker rm temp-container
Output confirms removal:
temp-container
Testing Data Persistence
Now let's create a new container and check if our data survived:
docker run -it --name temp-container2 ubuntu:20.04 bash
Inside the new container, try to access the data:
ls -la /tmp/
cat /tmp/test-file.txt
The results show the data is gone:
# ls output - empty tmp directory
total 0
drwxrwxrwt. 2 root root 6 Apr 4 02:09 .
drwxr-xr-x. 1 root root 6 Sep 12 14:36 ..
# cat output - file doesn't exist
cat: /tmp/test-file.txt: No such file or directory
Exit and clean up:
exit
docker rm temp-container2
⚠️ Data Loss Demonstrated: This proves that container data is completely lost when containers are removed. Each new container starts with a clean filesystem based on the original image.
📦 Step 2: Introduction to Docker Volumes
Docker volumes solve the persistence problem by providing external storage that survives container removal.
Understanding Available Volumes
docker volume ls
This shows any existing volumes:
DRIVER VOLUME NAME
local persist
Volume Components:
Field | Description | Example | Purpose |
---|---|---|---|
DRIVER | Storage driver type | local | Determines where data is stored |
VOLUME NAME | Unique identifier for the volume | persist | Reference name for mounting to containers |
Creating Your First Volume
docker volume create my-persistent-data
Output confirms creation:
my-persistent-data
Verifying Volume Creation
docker volume ls
The new volume appears in the list:
DRIVER VOLUME NAME
local my-persistent-data
local persist
Inspecting Volume Details
docker volume inspect my-persistent-data
This reveals detailed volume information:
[
{
"CreatedAt": "2025-09-12T19:37:47+05:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/my-persistent-data/_data",
"Name": "my-persistent-data",
"Options": null,
"Scope": "local"
}
]
Volume Properties:
Property | Value | Explanation |
---|---|---|
CreatedAt | 2025-09-12T19:37:47+05:00 | Volume creation timestamp |
Driver | local | Uses local filesystem storage |
Mountpoint | /var/lib/docker/volumes/my-persistent-data/_data | Physical storage location on host |
Scope | local | Available only on current Docker host |
💾 Step 3: Creating Multiple Volumes for Different Use Cases
Let's create volumes for common application scenarios:
Creating Application-Specific Volumes
docker volume create database-data
docker volume create app-logs
docker volume create app-config
Each command returns the volume name:
database-data
app-logs
app-config
Viewing All Volumes
docker volume ls
All volumes are now available:
DRIVER VOLUME NAME
local app-config
local app-logs
local database-data
local my-persistent-data
local persist
Volume Naming Conventions:
Pattern | Example | Use Case | Benefits |
---|---|---|---|
Component-based | database-data | Database storage | Clear purpose identification |
Function-based | app-logs | Application logging | Easy maintenance and backup |
Environment-based | prod-config | Production configuration | Environment separation |
Application-based | wordpress-content | CMS content storage | Application-specific organization |
🔗 Step 4: Mounting Volumes to Containers
Now let's use our volume to create truly persistent containers.
docker run -it --name persistent-container -v my-persistent-data:/data ubuntu:20.04 bash
Below output confirms the creation of a container:
persistent-container
Working with Persistent Data
Inside the container, let's create data in the mounted volume:
cd /data
echo "This data will persist!" > persistent-file.txt
echo "Container ID: $(hostname)" >> persistent-file.txt
date >> persistent-file.txt
ls -la
The volume shows our data:
total 4
drwxr-xr-x. 2 root root 33 Sep 12 14:40 .
drwxr-xr-x. 1 root root 18 Sep 12 14:40 ..
-rw-r--r--. 1 root root 80 Sep 12 14:41 persistent-file.txt
Let's see the file contents:
cat persistent-file.txt
Output shows our persistent data:
This data will persist!
Container ID: 8c4b0d76f3ef
Fri Sep 12 14:41:38 UTC 2025
Exit the container:
exit
Testing Data Persistence
docker rm persistent-container
docker run -it --name new-persistent-container -v my-persistent-data:/data ubuntu:20.04 bash
Container removal confirms:
persistent-container
Inside the new container, check if data survived:
cd /data
ls -la
cat persistent-file.txt
The data is still there!
# Directory listing
total 4
drwxr-xr-x. 2 root root 33 Sep 12 14:40 .
drwxr-xr-x. 1 root root 18 Sep 12 14:44 ..
-rw-r--r--. 1 root root 80 Sep 12 14:41 persistent-file.txt
# File contents
This data will persist!
Container ID: 8c4b0d76f3ef
Fri Sep 12 14:41:38 UTC 2025
Exit the new container:
exit
✅ Persistence Achieved: The data survived container removal and recreation! The volume mount -v my-persistent-data:/data
ensures data written to /data
is stored in the external volume.
📊 Step 5: Understanding Volume Mount Syntax
Let's break down the volume mount syntax and explore multiple volume scenarios.
Volume Mount Syntax
The basic syntax is: -v volume_name:container_path
Component | Example | Purpose | Notes |
---|---|---|---|
Volume Name | my-persistent-data | External storage identifier | Must exist before mounting |
Container Path | /data | Mount point inside container | Directory created automatically |
Mount Syntax | -v my-persistent-data:/data | Links volume to container path | Colon separates volume from path |
Multiple Volume Mounts
docker run -it --name multi-volume-container \
-v database-data:/var/lib/database \
-v app-logs:/var/log/app \
-v app-config:/etc/app \
ubuntu:20.04 bash
Inside the container, let's set up each mounted volume:
# Database directory
mkdir -p /var/lib/database
echo "user_data=sample" > /var/lib/database/users.db
# Application logs
mkdir -p /var/log/app
echo "$(date): Application started" > /var/log/app/app.log
# Configuration files
mkdir -p /etc/app
echo "debug=true" > /etc/app/config.ini
echo "port=8080" >> /etc/app/config.ini
Let's verify each volume:
ls -la /var/lib/database/
ls -la /var/log/app/
ls -la /etc/app/
Output shows data in each mounted location:
# Database directory
total 4
drwxr-xr-x. 2 root root 22 Sep 12 14:48 .
drwxr-xr-x. 1 root root 22 Sep 12 14:47 ..
-rw-r--r--. 1 root root 17 Sep 12 14:48 users.db
# Application logs
total 4
drwxr-xr-x. 2 root root 21 Sep 12 14:49 .
drwxr-xr-x. 1 root root 17 Sep 12 14:47 ..
-rw-r--r--. 1 root root 50 Sep 12 14:49 app.log
# Configuration directory
total 4
drwxr-xr-x. 2 root root 24 Sep 12 14:50 .
drwxr-xr-x. 1 root root 17 Sep 12 14:47 ..
-rw-r--r--. 1 root root 21 Sep 12 14:50 config.ini
Exit and clean up:
exit
docker rm multi-volume-container
🌐 Step 6: Practical Example - Persistent Web Server
Let's create a real-world example using a web server with persistent content.
Creating a Persistent Web Server
docker run -d --name web-server \
-v my-persistent-data:/usr/share/nginx/html \
-p 8080:80 \
nginx:alpine
The container starts successfully:
23ba28c2720eb8a66cd2928837e8801cae6f9c008db74c7750eb8bd74cc62fe5
Adding Content to Volume
Let's create an HTML file in our volume:
docker run --rm -v my-persistent-data:/data ubuntu:20.04 \
bash -c "echo '<h1>Hello from Persistent Volume</h1>' > /data/index.html"
This command runs a temporary container to create content (no output means success).
Testing the Web Server
curl http://localhost:8080
Our persistent content is served:
<h1>Hello from Persistent Volume</h1>
Demonstrating Persistence Across Container Recreation
docker stop web-server
docker rm web-server
docker run -d --name web-server-new \
-v my-persistent-data:/usr/share/nginx/html \
-p 8080:80 \
nginx:alpine
Output confirms each step:
web-server
web-server
b562cb8d429d6a82b93ce2f0bba6a5c7beba26fc6a430398454738419ca4856d
Testing Persistence
curl http://localhost:8080
The content persists across container recreation:
<h1>Hello from Persistent Volume</h1>
Clean up the web server:
docker stop web-server-new
docker rm web-server-new
✅ Real-World Persistence: This demonstrates how Docker volumes enable persistent web content, configurations, and data across container lifecycles - essential for production deployments.
🔍 Step 7: Volume Inspection and Management
Let's explore advanced volume inspection techniques.
Detailed Volume Inspection
docker volume inspect my-persistent-data
Complete volume details:
[
{
"CreatedAt": "2025-09-12T19:37:47+05:00",
"Driver": "local",
"Labels": null,
"Mountpoint": "/var/lib/docker/volumes/my-persistent-data/_data",
"Name": "my-persistent-data",
"Options": null,
"Scope": "local"
}
]
Extracting Specific Volume Properties
docker volume inspect my-persistent-data --format="{{.Mountpoint}}"
This shows the physical storage location:
/var/lib/docker/volumes/my-persistent-data/_data
Extract Volume Driver
docker volume inspect my-persistent-data --format="{{.Driver}}"
Output shows the driver type:
local
Working with Volume Paths
VOLUME_PATH=$(docker volume inspect my-persistent-data --format '{{.Mountpoint}}')
echo "Volume is mounted at $VOLUME_PATH"
This shows the full path:
Volume is mounted at /var/lib/docker/volumes/my-persistent-data/_data
Direct Host Access to Volume Data
sudo ls -la $VOLUME_PATH
sudo cat $VOLUME_PATH/persistent-file.txt
Direct host access shows all our persistent data:
# Directory listing
total 8
drwxr-xr-x. 2 root root 51 Sep 12 19:55 .
drwx-----x. 3 root root 19 Sep 12 19:37 ..
-rw-r--r--. 1 root root 38 Sep 12 19:55 index.html
-rw-r--r--. 1 root root 80 Sep 12 19:41 persistent-file.txt
# File contents
This data will persist!
Container ID: 8c4b0d76f3ef
Fri Sep 12 14:41:38 UTC 2025
🎯 Key Volume Concepts
Volume vs Container Storage
Storage Type | Persistence | Performance | Use Case |
---|---|---|---|
Container Storage | Lost on container removal | Fast (in-memory layers) | Temporary data, application binaries |
Volume Storage | Survives container lifecycle | Good (direct filesystem access) | Databases, user content, configuration |
Bind Mounts | Tied to host filesystem | Variable (depends on host) | Development, configuration files |
tmpfs Mounts | In-memory only | Very fast | Sensitive temporary data |
Volume Lifecycle
Stage | Command | Description | Data Impact |
---|---|---|---|
Creation | docker volume create | Volume is created and ready for use | Empty volume initialized |
Mounting | docker run -v volume:path | Volume attached to container | Data becomes accessible in container |
Usage | Container operations | Applications read/write to volume | Data persists across container restarts |
Unmounting | Container removal | Volume detached from container | Data remains in volume |
Deletion | docker volume rm | Volume and data permanently removed | All data lost permanently |
🎯 Key Takeaways
✅ Volume Fundamentals
- Container Data is Ephemeral: Data in containers is lost when containers are removed
- Volumes Provide Persistence: Docker volumes store data outside container lifecycles
- Volume Mounting: Use
-v volume_name:container_path
to mount volumes - Multiple Volumes: Containers can mount multiple volumes for different purposes
- Volume Inspection: Use
docker volume inspect
to examine volume properties - Host Access: Volume data is accessible from the Docker host filesystem
📖 What's Next?
In Part 2 of this Docker volumes series, we'll explore:
- Advanced volume management and cleanup strategies
- Volume backup and restoration techniques
- Bind mounts vs named volumes
- Performance considerations and optimization
- Volume drivers and storage backends
🎉 Volume Fundamentals Mastered! You now understand the critical importance of Docker volumes for data persistence and have hands-on experience creating, mounting, and managing persistent storage in containerized applications.
💬 Discussion
I'd love to hear about your Docker volumes experiences:
- What types of data do you need to persist in your containerized applications?
- How do you currently handle data backup and recovery?
- What challenges have you faced with container data management?
- Have you worked with different volume drivers or storage backends?
Connect with me:
- 🐙 GitHub - Docker volumes examples and configurations
- 📧 Contact - Data persistence questions and architecture discussions