Bind mounts give the edit-and-reload loop for development; knowing their pitfalls saves hours.
A bind mount maps an existing path on the host directly into the container. Unlike a volume, Docker doesn't manage it; the container sees your real files, and changes go both ways instantly.
docker run -v "$PWD":/app -w /app node:22 npm run devThat is the classic development setup: your editor changes files on the host, the dev server in the container reloads. The --mount form is --mount type=bind,src="$PWD",dst=/app; unlike -v, it errors if the source path doesn't exist instead of creating an empty directory, which catches typos.
Key behaviours and gotchas:
- A bind mount hides whatever the image had at that path. Mounting your project over
/appalso hides thenode_modulesinstalled in the image. A common fix is an extra anonymous volume for that subfolder:-v /app/node_modules. - Permissions: files are owned by numeric UIDs. A container running as root creates root-owned files in your project; a non-root container may be unable to write host files. Run with
--user "$(id -u):$(id -g)"on Linux when needed. - Performance on Docker Desktop is lower than on native Linux, because files cross the VM boundary; synchronized file shares or volumes help for heavy I/O.
- Append
:ro(orreadonlywith--mount) for config files the container should only read. - Bind mounts tie a container to the host's directory layout, so use them for development and for specific host files, and use volumes for application data.
A tmpfs mount (--tmpfs /tmp) lives only in memory and vanishes when the container stops. Use it for scratch files and secrets that must never touch disk, and pair it with --read-only root filesystems.
Example
# Live-reload dev server, keeping the image's node_modules
docker run --rm -it -p 5173:5173 \
-v "$PWD":/app -v /app/node_modules -w /app \
node:22 npm run dev -- --host
# Read-only config file from the host
docker run -d --name proxy \
--mount type=bind,src="$PWD"/nginx.conf,dst=/etc/nginx/nginx.conf,readonly \
-p 8080:80 nginx:1.27
# Avoid root-owned files in your project (Linux)
docker run --rm -v "$PWD":/w -w /w --user "$(id -u):$(id -g)" alpine touch out.txt
# In-memory scratch space on a read-only container
docker run --rm --read-only --tmpfs /tmp alpine sh -c 'echo hi > /tmp/x && cat /tmp/x'Remember
- Bind mounts expose a host path directly; changes are live both ways
- They hide the image's content at the mount point
- Watch UID ownership and Docker Desktop I/O performance
- tmpfs mounts are in-memory and disappear on stop
Watch out for
- Mounting the project over /app and wondering where node_modules went.