DevOps & Infrastructure

Docker Bind Mounts or Volumes? A Practical Choice

Choose between Docker bind mounts and named volumes by ownership, portability, backup needs, and failure modes.

2 min read
#docker#storage#containers#operations

A misty green valley surrounded by mountains at sunrise

Photo: Unsplash.

Both bind mounts and named volumes put persistent data outside a container’s writable layer. The important difference is who owns the path.

A bind mount maps a path you choose:

services:
  site:
    volumes:
      - ./config/nginx.conf:/etc/nginx/nginx.conf:ro

This is ideal when the host and container should both see a file: source code during development, checked-in configuration, or generated artifacts. The trade-off is coupling. Move the project to a host with a different directory layout or permissions and the mount may fail.

A named volume is managed by Docker:

services:
  db:
    image: postgres:17
    volumes:
      - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:

It is usually the calmer choice for database state and application data that only containers need. Inspect it with docker volume inspect postgres_data; do not build procedures around its internal path under Docker’s data directory.

My rule is simple:

  • Use a bind mount when the host intentionally owns and edits the file.
  • Use a named volume when the service owns the data.
  • Use :ro whenever the container only needs to read a bind mount.
  • Test the backup and restore process independently of either choice.

One trap is docker compose down -v: the -v explicitly removes named volumes declared by the project. That may be desirable in a disposable development stack and disastrous around production data. Read the command before pressing Enter.

A volume is persistence, not a backup. Export data using the database’s supported tools or a tested filesystem procedure, store it elsewhere, and practice restoring it.

References