Bind Mounts
A bind mount maps a directory on the host into a container. Use them when you want changes on the host to appear instantly in the container — the canonical case is mounting your source tree during local development. They are NOT a portable persistence mechanism; for production data use named volumes instead.
Bind mounts for dev loop, plus the gotchas
EXAMPLE
# 1) Mount the current directory into the container's /app
docker run --rm -it \
-v "$(pwd)":/app \
-w /app \
node:20-alpine \
npm run dev
# 2) Read-only bind mount — useful for configs you do not want the container to mutate
docker run --rm -it \
-v /etc/nginx/conf.d:/etc/nginx/conf.d:ro \
nginx:1.27
# 3) The --mount syntax is more explicit and harder to typo
docker run --rm -it \
--mount type=bind,source="$(pwd)",target=/app,readonly \
node:20-alpine node /app/index.js
# 4) docker-compose: bind mount the code AND mask node_modules with a volume
# This is the classic 'live reload but keep container-installed deps' pattern.
# docker-compose.yml
# services:
# web:
# image: node:20-alpine
# working_dir: /app
# command: npm run dev
# volumes:
# - .:/app # bind mount: host code -> container
# - /app/node_modules # anonymous volume MASKS host's node_modules
# ports:
# - 3000:3000
# 5) Gotchas you will hit
# a) Permissions: files created in the container land on the host owned by
# the container's user. On Linux this is often UID 0 (root) if the
# container did not switch user. Fix by running the container as your UID:
docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd)":/app node:20-alpine \
npm install
# b) Performance: bind mounts on macOS/Windows go through a network FS layer.
# Mount only the paths you need. For node_modules, prefer a named volume.
# c) SELinux (RHEL/Fedora) blocks bind mounts by default. Append :z (shared) or :Z (private):
docker run -v "$(pwd)":/app:z fedora:40 ls /app
# d) Inotify limits: large source trees can exhaust inotify watchers, breaking
# file-watch reloaders. Raise the limit on the host:
sudo sysctl fs.inotify.max_user_watches=524288
# 6) Inspect bind mounts on a running container
docker inspect web --format '{{ range .Mounts }}{{ .Type }} {{ .Source }} -> {{ .Destination }}{{ println }}{{ end }}'
# 7) Production tip: DO NOT bind-mount production code. Ship a baked image.
# Bind mounts couple the runtime to the host filesystem, which is fine in dev
# but defeats the point of immutable images at deploy time.
Why it matters
The compose pattern - bind-mount the code AND declare an anonymous volume at the path of node_modules / vendor / target - is the trick that makes hot-reload Just Work without dragging the hosts dependencies into the container. Without the anonymous volume, an `npm install` on macOS clobbers the much faster Linux node_modules the container built at image time.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Example
# Mount a host path into the container — perfect for dev hot-reload. docker run -v $(pwd)/src:/app/src node:20Try it Yourself »
Discussion
Loading…