How to Deal with Persistent Storage (e.g. Databases) in Docker

Docker containers are ephemeral — they can be created, destroyed, and rebuilt at any time. While this is perfect for stateless applications, it creates a challenge when dealing with stateful services like databases.

If your database container is removed, all its data will be lost unless you persist it outside the container.

In this guide, we’ll explore the best ways to handle persistent storage in Docker.


🔍 Why Persistence Matters

Without persistent storage:

  • Data loss risk: Stopping or removing a container erases all data inside it.
  • No backups: You can’t easily move your data between containers.
  • Difficult scaling: Data must survive container restarts to support production workloads.

Example: Running a MySQL container without persistence means your database resets every time it restarts.


🛠 Methods for Persistent Storage in Docker

1. Docker Volumes (Recommended)

Volumes are the official Docker-managed way to store persistent data.

Creating a volume:

docker volume create my_db_data

Running a container with a volume:

docker run -d \
  --name mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -v my_db_data:/var/lib/mysql \
  mysql:8.0

Advantages:

  • Managed by Docker
  • Portable across hosts
  • Easier backup and restore using docker run --rm -v my_db_data:/backup busybox tar

2. Bind Mounts

Bind mounts directly map a host directory into a container.

Example:

docker run -d \
  --name mysql \
  -e MYSQL_ROOT_PASSWORD=secret \
  -v /path/on/host/mysql_data:/var/lib/mysql \
  mysql:8.0

Advantages:

  • Full control over the data location
  • Easy to inspect and edit files on the host

Considerations:

  • Host directory structure must be managed manually
  • Not as portable as volumes

3. Named Volumes in Docker Compose

When using Docker Compose, persistence can be declared in docker-compose.yml:

version: '3.9'
services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: secret
    volumes:
      - db_data:/var/lib/mysql

volumes:
  db_data:

Advantages:

  • Fully integrated into your stack configuration
  • Easily recreated on another machine with the same docker-compose.yml

4. External Storage Solutions

For production environments, you may want to use:

  • NFS (Network File System)
  • Cloud Block Storage (AWS EBS, Azure Disk, Google Persistent Disk)
  • Database as a Service (RDS, Cloud SQL, etc.)

These options offer:

  • High availability
  • Offsite backups
  • Multi-node access

📌 Best Practices

  1. Never store database data inside the container’s writable layer — it will be lost.
  2. Use named volumes for portability and maintainability.
  3. Keep backups of your volumes (e.g., docker run --rm -v myvolume:/data busybox tar czf /backup/data.tar.gz /data).
  4. Version your schema to handle migrations when containers are updated.
  5. Separate concerns — don’t bundle your database and application into the same container.

🚀 Final Thoughts

Persistent storage is crucial when running databases or any stateful service in Docker.
The safest, most maintainable approach is to use named volumes for local development and external storage for production.

By designing with persistence in mind, you can take full advantage of Docker’s flexibility without risking your valuable data.

Sharing Is Caring:

Leave a Comment