Mount the project folder and nothing more. Bind mounts give a container write access to host files by default, so a mounted home directory, credentials folder or Docker socket puts them within reach of every tool inside. Use the read only option wherever the container does not need to write.
What a bind mount does
A bind mount maps a host path into a container. Docker's documentation says bind mounts have write access to files on the host by default, so a process in the container can create, modify or delete important system files or directories. The same page explains that a mount over an existing container directory hides what was there, and that the only way to see it again is to recreate the container without the mount.
For a dev container this matters because the container runs your editor's server, extensions, build tools and often scripts from the repository itself.
A decision table
| Candidate mount | Suggested stance | Reason |
|---|---|---|
| The project folder | Mount, writable | The tools need to edit it |
| A shared reference data folder | Mount read only | No need to write |
| Your whole home directory | Avoid | Exposes every project and dotfile to the container |
| A credentials or key folder | Avoid | Anything in the container could read it |
| The Docker socket | Avoid | Gives control of the daemon, see below |
| A build cache | Prefer a named volume | Keeps host paths out of it |
The stance column is a recommendation from this post, not a quote from the documentation. The facts behind it are the default write access, the read only option and the daemon's authority.
How to write the mount safely
Docker prefers the mount flag for being explicit and says it supports every option. A read only mount looks like this:
docker run --mount type=bind,src=./reference,dst=/reference,ro IMAGE
One difference between the two syntaxes is worth knowing. If you use the volume flag with a host path that does not exist, Docker creates a directory there for you, always as a directory. The mount flag produces an error instead, which catches typos.
In devcontainer.json, the mounts property accepts values with the same fields as the Docker mount flag, so the same advice applies. See which devcontainer settings to flag in review.
The socket is a special case
Docker documents an example that mounts the Docker socket into a container. A container that can talk to the daemon can start other containers with other mounts. Read why that equals root on the host before approving it.
Permission surprises
On Linux, dev container tooling can update a container user's UID and GID to match your local user so bind mounted files have sensible ownership. The reference says updateRemoteUserUID defaults to true. If you run with user namespace remapping, Docker warns that mounts into paths the mapped user cannot write cause permission problems.
A short routine
- List every mount in your dev container and Compose files.
- Remove any that point at a home directory, key folder or socket.
- Switch read only candidates to read only.
- Replace caches with named volumes.
- Re-run the container and see what breaks, then fix the narrowest thing.
Safeguard can scan the dependencies in the project you mount, and you can try a free scan at gold.safeguard.sh/scan.
Quick check
Does a read only mount hide the files from the container?
No. It only blocks writing. The container can still read everything in the mounted path.
Does Docker Desktop keep bind mounts away from my machine?
No. Docker says the daemon runs in a Linux VM and uses built in mechanisms to share host paths with containers, so mounted paths are still shared.
Sources
- Bind mounts, Docker Docs
- Running containers, Docker Docs
- devcontainer.json reference, containers.dev
- Isolate containers with a user namespace, Docker Docs
Last reviewed: 19 October 2026.