Keeping Data Alive: Docker Storage Beyond the Container

Docker’s layered images are great for shipping applications, but by default every change a container makes disapears when the container is removed. To keep that data around we need to look at the three official persistence mechanisms—volumes, bind mounts, and tmpfs mounts—and understand why they exist in the first place.

Why the Union File System Isn’t Enough

Each Docker image is a stack of read-only layers. When you start a container, Docker adds a thin writable layer on top. This stack is called a Union File System. Any file created or modified inside the container lands in that writable layer only. The moment the container is deleted, the writable layer vanishes, taking your changes with it. UnionFS therefore gives you:

  • Fast image reuse and distribution
  • Isolation between containers
  • But zero durability

Volume, Bind Mount, or tmpfs?

Mechenism Where the data lives Lifetime Typical use-case
Volume /var/lib/docker/volumes/... Survives container removal Databases, shared caches
Bind mount Any host directory you pick Survives container & engine removal Source code, config files
tmpfs mount Host RAM (swap-backed) Vanishes when container stops Secrets, short-lived scratch files

Working with Named Volumes

Create and inspect

docker volume create web_logs
docker volume ls
docker volume inspect web_logs

Attach at run-time

docker run -d \
  --name nginx \
  -v web_logs:/var/log/nginx \
  nginx:alpine

Data written to /var/log/nginx inside the container is now stored in the web_logs volume and remains after the container is removed.

Populate on first use

If the image already contains files in /var/log/nginx, Docker copies them into the newly created volume so the container starts with sensible defaults.

Share between containers

docker run -d --name log_processor --volumes-from nginx alpine tail -f /var/log/nginx/access.log

Backup & restore

# Backup
docker run --rm \
  --volumes-from nginx \
  -v $(pwd):/backup \
  alpine tar czf /backup/web_logs.tgz -C /var/log/nginx .

# Restore
docker run --rm \
  -v web_logs:/data \
  -v $(pwd):/backup \
  alpine tar xzf /backup/web_logs.tgz -C /data

Declarative Volumes in a Dockerfile

FROM alpine:3.19
WORKDIR /app
RUN apk add --no-cache curl
VOLUME ["/uploads", "/cache"]

Building an image with this Dockerfile and running it will automatically create anonymous volumes for /uploads and /cache. You can later give those volumes names or map them to host directories.

Bind Mounts for Development

Bind mounts map any host path into the container. They are ideal when you need to edit source code on the host and see changes immediately inside the container..

docker run --rm -it \
  --mount type=bind,src=$(pwd)/src,dst=/var/www/html,readonly \
  php:8.3-cli php -S 0..0.0:8000 -t /var/www/html

tmpfs for Ephemeral Secrets

Use --tmpfs when you want files to live only in memory:

docker run --rm -it --tmpfs /run/secrets:rw,size=10m alpine sh

Everything under /run/secrets disappears when the container exits, leaving no trace on disk.

Quick Reference

# Remove unused volumes
docker volume prune

# Upgrade a container while keeping its data
docker stop db
docker rm db
docker run -d --name db -v db_data:/var/lib/postgresql/data postgres:16

By choosing the right storage mechanism you can keep stateful workloads safe, share data between containers, and still enjoy Docker’s lightweight immutability everywhere else.

Tags: docker volume bind-mount tmpfs unionfs

Posted on Tue, 09 Jun 2026 17:04:48 +0000 by dpacmittal