Bind-mount a host directory into a Docker container

Choose an explicit host path, distinguish runtime mounts from image copies, and diagnose permissions and file-sharing behavior.

Best practices
Illustration of container operations and troubleshooting

A bind mount makes a host file or directory available at a container path. Both views refer to the mounted data; this is not a background file-copy service. A writable mount allows the container to change or delete host data, and removing the container does not remove the host directory.

Mount an existing directory or file

For a configuration directory that already exists on the Docker daemon's host:

docker run -d --name myapp \
  --mount type=bind,source=/opt/app/conf,target=/etc/app/conf,readonly \
  myapp:1.2

Use the actual application image and paths. Remove readonly only if writes are intended. The shorter equivalent is -v /opt/app/conf:/etc/app/conf:ro.

For a single file, verify that the source is a file before mounting it:

test -f /opt/app/app.yml
docker run -d --name configured-app \
  --mount type=bind,source=/opt/app/app.yml,target=/etc/app/app.yml,readonly \
  myapp:1.2

The test command is an inspection step; stop if it fails. By default, --mount fails for a missing source, while -v creates a missing source as a directory. That difference often explains why a supposed configuration file becomes an empty directory.

Express the mount in Compose

services:
  app:
    image: myapp:1.2
    volumes:
      - type: bind
        source: /opt/app/conf
        target: /etc/app/conf
        read_only: true
        bind:
          create_host_path: false
      - type: bind
        source: ./logs
        target: /var/log/app
        bind:
          create_host_path: false

Create the intended log directory with appropriate ownership first. Relative Compose paths resolve from the Compose project's file context, while mounts themselves refer to the daemon host. A remote daemon cannot directly mount an arbitrary directory from your laptop. Docker Desktop provides host-file sharing through its VM integration.

Mounts and image copies have different lifecycles

COPY and ADD place build inputs into an image; later host edits do not update those copies. A runtime bind mount can hide files already present at its target in the image. It does not delete those image files, but the mounted view is what the container sees.

A Dockerfile cannot bake a machine-specific runtime bind mount into an image. BuildKit's RUN --mount=type=bind is a separate build-time capability; it does not define a persistent mount for containers launched from the result.

Resolve common failures

Check the inspected mount source, target, and read-only flag. Then check the application's actual numeric UID, GID, supplementary groups, parent-directory access, and any user-namespace mapping. Matching a username alone is insufficient. On SELinux systems, :z and :Z can relabel bind-mounted content for shared or private use; do not relabel broad system directories indiscriminately.

An editor may replace a file with a new inode when saving. A single-file bind mount can continue showing the old object; mounting the containing directory often fits that update pattern better. The application may still need a reload.

Named volumes are useful for Docker-managed application data, but they do not automatically solve every ownership problem. Desktop file-sharing performance depends on its backend and workload; do not assume a legacy delegated option improves every setup.

For file-based logs, configure Guance log collection for the actual host path. Write a test event after recreation and retain container identity when several instances write logs.

See Docker bind mounts and Compose service volumes.

Get a tailored plan

Contact us

Join the community

Scan with WeChat
to join the community

Try Guance

Start online and pay only for what you use.

Get started

Choose a Guance plan

Code hosting