Docker and Kubernetes course menu
Docker Bind Mounts: Share Your Code with a Container
Mount a host folder into a container with bind mounts, see changes without rebuilding, use read-only mounts, tmpfs, and choose between bind mounts and volumes.
On this page
A bind mount connects a folder on your computer to a path in a container. Both see the same files. This is ideal for development, because you can edit code on your computer, and the container sees the change straight away.
Syntax#
If the left side of -v is a path, it is a bind mount. If it is a name, it is a volume:
docker run -v "$PWD/src":/app/src image # bind mount
docker run -v mydata:/app/data image # named volumeLive changes#
Here Nginx serves a folder from the host, with no custom image:
mkdir html
echo "<h1>Version 1</h1>" > html/index.html
docker run -d --name web -p 8080:80 -v "$PWD/html":/usr/share/nginx/html:ro nginx:1.30-alpine > /dev/null
sleep 2
curl -s http://localhost:8080
echo "<h1>Version 2</h1>" > html/index.html
curl -s http://localhost:8080
docker rm -f web > /dev/null<h1>Version 1</h1>
<h1>Version 2</h1>The page changed with no rebuild and no restart. :ro stops the container from changing your files.
Using tools without installing them#
A bind mount lets you run tools on your files from a container:
mkdir work
echo "Hello from the host" > work/in.txt
docker run --rm -v "$PWD/work":/work -w /work alpine:3.24 sh -c 'tr a-z A-Z < in.txt > out.txt'
cat work/out.txtHELLO FROM THE HOST-w sets the working folder. This is a handy way to use a specific Node.js or Python version without installing it.
File ownership#
On Linux, files created by a container are owned by the container's user, which is often root:
docker run --rm -v "$PWD/work":/work alpine:3.24 touch /work/made-by-root
ls -l work/made-by-root | awk '{print $3, $4}'
docker run --rm --user "$(id -u):$(id -g)" -v "$PWD/work":/work alpine:3.24 touch /work/made-by-me
ls -l work/made-by-me | awk '{print $3, $4}'root root
asha asha--user runs the container with your user ID, which avoids files that you cannot delete.
The --mount syntax#
--mount is longer, but clearer. Unlike -v, it fails if the host path does not exist, rather than creating an empty folder:
docker run --rm --mount type=bind,src="$PWD/work",dst=/work,readonly alpine:3.24 ls /work | head -n 1
docker run --rm --mount type=bind,src=/no/such/path,dst=/work alpine:3.24 true 2>&1 | head -n 1 | cut -c1-96in.txt
docker: Error response from daemon: invalid mount config for type "bind": bind source path doestmpfs#
A tmpfs mount lives in memory, and vanishes when the container stops. It suits temporary files and secrets that should never reach the disk:
docker run --rm --tmpfs /scratch alpine:3.24 sh -c 'mount | grep scratch | cut -d, -f1'tmpfs on /scratch type tmpfs (rwWhich should I use?#
A mount hides what was there#
A mount covers whatever the image had at that path. If you mount your project over /app, the node_modules installed in the image is hidden. Compose for Development shows the fix.
On Windows and macOS#
Bind mounts cross from your computer into Docker's Linux virtual machine, so they can be slower, and file-change events may not arrive. On Windows, keep the project inside the WSL file system, not on /mnt/c.
Common mistakes#
Practice#
Practice exercise
Create conf/app.txt containing mode=test. Run an alpine:3.24 container that mounts conf read-only at /conf, prints the file, and shows that writing to it fails.
Show solution
mkdir conf
echo "mode=test" > conf/app.txt
docker run --rm -v "$PWD/conf":/conf:ro alpine:3.24 sh -c 'cat /conf/app.txt; touch /conf/x'mode=test
touch: /conf/x: Read-only file systemKey takeaway#
Next: Container Networking.
Finished this lesson?
Related lessons
Recommended Docker and Kubernetes resources
- Docker Deep Dive by Nigel Poulton
A practical guide to how Docker works, for readers who have finished the basics.
Some links are affiliate links. If you buy through them, Laviyx Learn may earn a commission at no extra cost to you. As an Amazon Associate, we earn from qualifying purchases.