Why a container loses its data when it restarts

Write a row to a database running in a Docker container, stop the container, start it again: the row is gone.

Every container gets its filesystem fresh from its image each time it starts. Anything the container itself writes — database files, uploads, logs — goes into a writable layer that is thrown away when the container is removed. A Docker volume is how you keep that data outside the container, where it survives.

What Is a Docker Volume?

A Docker volume is a mechanism for storing data outside the container, so that it persists even when the container is stopped, restarted, or deleted.

Think of volumes as an external hard drive that you connect to your container. Data is written to this “external drive” and remains safe regardless of what happens to the container.

Why Use Volumes?

  • Persistence: data survives the container lifecycle
  • Sharing: multiple containers can access the same data
  • Backup: it’s easier to back up data
  • Performance: volumes are optimized for I/O operations
  • Portability: you can move data between different hosts

Volumes, bind mounts and tmpfs: which to use

There are three ways to persist data, in the order you should reach for them: volumes, bind mounts, tmpfs.

Volumes are fully managed by Docker and stored in a special directory on the host (/var/lib/docker/volumes/ on Linux).

1
2
3
4
5
# Create a volume
docker volume create my-volume

# Use the volume in a container
docker run -v my-volume:/app/data my-image

Advantages:

  • Managed by Docker (easy to create, delete, inspect)
  • Work on Linux, Windows, and Mac
  • Can be shared between multiple containers
  • Support drivers for remote storage (cloud, NFS, etc.)

2. Bind Mounts - Direct Connection

Bind mounts connect a specific folder on your computer directly to the container.

1
2
# Connect a local folder to the container
docker run -v /path/on/your/pc:/app/data my-image

When to use them:

  • During development, to see code changes in real time
  • When you need access to specific files on the host system
  • To share configurations between host and container

Warning: bind mounts depend on the host filesystem structure, so they’re less portable.

3. tmpfs Mounts - Temporary Data in Memory

tmpfs mounts store data in the host’s RAM, not on disk.

1
docker run --tmpfs /app/temp my-image

When to use them:

  • For sensitive data that shouldn’t be written to disk
  • For high-performance temporary caches
  • Data is lost when the container stops (and that’s exactly what you want)

Docker volume commands: create, list, inspect, remove

Create a Volume

1
docker volume create volume-name

List Volumes

1
docker volume ls

Inspect a Volume

1
docker volume inspect volume-name

This command shows where the volume is physically stored and other useful information.

Delete a Volume

1
2
3
4
5
# Delete a specific volume
docker volume rm volume-name

# Delete all unused volumes
docker volume prune

Warning: deleting a volume means losing all the data it contains. There’s no recycle bin or recovery.

Docker volume examples: database, live-reload dev, sharing

Example 1: MySQL Database with Persistent Data

Without a volume, every time you restart the MySQL container you lose all data. Here’s how to fix it:

1
2
3
4
5
6
7
8
9
# Create a volume for MySQL data
docker volume create mysql-data

# Start MySQL using the volume
docker run -d \
  --name my-mysql \
  -e MYSQL_ROOT_PASSWORD=password123 \
  -v mysql-data:/var/lib/mysql \
  mysql:8

Now you can stop, restart, or even delete and recreate the container: the database data will remain intact in the mysql-data volume.

Example 2: Web Development with Bind Mount

During development, you want code changes to be immediately visible in the container:

1
2
3
4
5
docker run -d \
  --name my-site \
  -p 8080:80 \
  -v $(pwd)/src:/var/www/html \
  php:apache

Any changes to files in the src folder will be immediately available in the container.

Example 3: Sharing Data Between Containers

Two containers that need to access the same files:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# Create the shared volume
docker volume create shared-data

# Container that writes
docker run -d --name writer -v shared-data:/data alpine \
  sh -c "while true; do date >> /data/log.txt; sleep 5; done"

# Container that reads
docker run -it --name reader -v shared-data:/data alpine \
  tail -f /data/log.txt

Volumes in Docker Compose

In Docker Compose you declare volumes once and every service that needs them refers to them by name:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
version: '3.8'

services:
  database:
    image: postgres:15
    volumes:
      - postgres-data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: secret

  app:
    image: my-app
    volumes:
      - ./code:/app              # Bind mount for development
      - logs:/app/logs           # Volume for logs

volumes:
  postgres-data:    # Docker-managed volume
  logs:             # Docker-managed volume

With a simple docker-compose up, Docker automatically creates the necessary volumes.

Backing Up and Restoring Volumes

Back Up a Volume

1
2
3
4
docker run --rm \
  -v volume-name:/source:ro \
  -v $(pwd):/backup \
  alpine tar czf /backup/backup.tar.gz -C /source .

This command:

  1. Mounts the volume in read-only mode (ro)
  2. Creates a compressed archive in the current directory

Restore a Backup

1
2
3
4
docker run --rm \
  -v volume-name:/target \
  -v $(pwd):/backup \
  alpine tar xzf /backup/backup.tar.gz -C /target

Docker volume mistakes to avoid

1. Forgetting to Use Volumes for Databases

If you use a database in Docker without a volume, you will lose all data. Always.

2. Using Bind Mounts in Production

Bind mounts are great for development, but in production use Docker volumes for better portability and security.

3. Not Backing Up Volumes

Volumes are not automatically included in system backups. Plan regular backups.

4. Accumulating Orphan Volumes

When you delete containers, volumes remain. Periodically use:

1
docker volume prune

To delete volumes no longer connected to any container.

Which storage option for which job

ScenarioSolution
Production databaseDocker Volume
Local developmentBind mount
Temporary sensitive datatmpfs
Sharing between containersDocker Volume
Configuration filesBind mount or Volume
Application logsDocker Volume

The rule that covers most cases

Use a named volume for anything a container writes that you want to keep, databases first of all. Use a bind mount when you want the container to see a folder on your machine as you edit it, which is mostly local development. Keep tmpfs for data that must never touch the disk.

Once a database has a volume, you can delete and recreate its container as often as you like and the data stays put. That is the whole point.

Containers also need to reach each other, not just keep their data. That part is handled by a Docker network.