Docker Error Guide: 'invalid mount config for type "bind"' Bind Mount Failures
Fix Docker's invalid mount config for type bind error: create missing host paths, use absolute paths, enable Desktop file sharing, and set SELinux labels.
- #docker
- #troubleshooting
- #errors
- #volumes
Exact Error Message
Docker prints this when you start a container with a bind mount whose host source path cannot be resolved:
docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /path
Closely related wordings you may also see, depending on how the mount was specified:
Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /home/user/data
Error response from daemon: invalid mount config for type "bind": field Source must not be empty
Error response from daemon: invalid mount config for type "bind": mount type 'bind' not supported on this platform
All four are the daemon refusing a type=bind mount because the host-side source is missing, empty, or unusable.
What It Means
A bind mount maps a directory or file that already exists on the host into the container. Unlike a named volume, the Docker daemon does not create the host path for you when you use --mount — it validates that the source exists and errors out if it does not. (The legacy -v shorthand historically auto-created missing host directories; modern --mount is strict, which is the most common source of confusion.)
The daemon resolves the source path on the host filesystem the daemon runs on, not your shell’s working directory or, on Docker Desktop, your laptop’s raw filesystem. So “the folder is right there” can still fail if the path is relative, if Desktop has not shared that part of your disk, or if SELinux blocks the label. The container never starts; you get the daemon error and nothing in docker logs because no container layer was ever created.
This is also why the same command can behave differently on a teammate’s machine or in CI. The CLI passes the source path to the daemon largely as-is, and it is the daemon that does the existence check. On a native Linux host the daemon and your shell share one filesystem, so an absolute path that exists locally will exist for the daemon too. On Docker Desktop, the daemon lives inside a lightweight Linux VM, and only the directories you have explicitly shared are visible inside that VM — everything else simply “does not exist” from the daemon’s point of view, even though you can ls it in your terminal. Understanding that split between where you type the command and where the daemon evaluates the path explains most bind-mount surprises.
Common Causes
- Host source path does not exist. With
--mount, Docker will not auto-create it. The directory must exist beforedocker run. - Relative instead of absolute path.
-v ./data:/appor--mount source=data,...resolves against the daemon’s notion of the path, not yourcwd, and fails. field Source must not be empty. A shell variable expanded to an empty string (-v $DATA_DIR:/appwhereDATA_DIRis unset), leaving no source.- Docker Desktop file sharing not enabled. On macOS/Windows the path lives outside the shared file-sharing roots, so the VM cannot see it.
- SELinux relabeling. On RHEL/Fedora the mount succeeds but the container is denied access unless you add
:z(shared) or:Z(private) to relabel the source. - Mixing
-vauto-create with--mountstrict semantics across scripts, so the same path works in one command and fails in another. - Windows path format.
C:\Users\me\datamust be/c/Users/me/data(or//c/...) for the Linux daemon. - Permissions. The path exists but the daemon user cannot stat it (e.g. inside a restricted mount namespace).
How to Reproduce the Error
Point a bind mount at a directory that does not exist, using the strict --mount form:
docker run --rm \
--mount type=bind,source=/tmp/does-not-exist-1234,target=/data \
alpine ls /data
docker: Error response from daemon: invalid mount config for type "bind": bind source path does not exist: /tmp/does-not-exist-1234.
Reproduce the empty-source variant with an unset variable:
unset DATA_DIR
docker run --rm --mount type=bind,source=$DATA_DIR,target=/data alpine true
docker: Error response from daemon: invalid mount config for type "bind": field Source must not be empty.
Diagnostic Commands
First confirm whether the host path actually exists and is a directory the daemon can read:
ls -ld /tmp/does-not-exist-1234
readlink -f ./data # resolve a relative path to its absolute form
ls: cannot access '/tmp/does-not-exist-1234': No such file or directory
Inspect what mounts a running or created container was asked for:
docker inspect <container> --format '{{json .Mounts}}' | python3 -m json.tool
docker inspect <container> --format '{{range .Mounts}}{{.Type}} {{.Source}} -> {{.Destination}}{{println}}{{end}}'
On Docker Desktop, confirm the daemon’s platform and storage driver, and check the file-sharing roots in Settings → Resources → File Sharing:
docker info --format 'Server: {{.OperatingSystem}} | Driver: {{.Driver}} | Root: {{.DockerRootDir}}'
docker info | grep -i -A3 'file sharing\|operating system'
If the daemon itself looks unhealthy while resolving mounts, check its logs:
journalctl -u docker --no-pager -n 50
docker events --since 5m --filter event=create
Step-by-Step Resolution
1. Create the host path before running. Bind sources are not auto-created with --mount:
mkdir -p /srv/app/data
docker run --rm --mount type=bind,source=/srv/app/data,target=/data alpine ls -la /data
2. Always use absolute paths. Expand relative paths yourself so the daemon and your shell agree:
docker run --rm -v "$(pwd)/data:/data" alpine ls /data
docker run --rm --mount type=bind,source="$(readlink -f ./data)",target=/data alpine ls /data
3. Guard against empty variables to avoid field Source must not be empty:
: "${DATA_DIR:?DATA_DIR must be set}"
docker run --rm --mount type=bind,source="$DATA_DIR",target=/data alpine true
4. Enable Docker Desktop file sharing. In Settings → Resources → File Sharing, add the parent directory (e.g. /Users/me/projects), apply, and restart. On Windows use Linux-style paths: /c/Users/me/data.
5. Add SELinux labels on RHEL/Fedora/CentOS when the container can mount but not read:
docker run --rm -v /srv/app/data:/data:Z alpine ls /data # :Z private, :z shared
6. Pick the right semantics. Use --mount type=bind when you want the strict, fail-fast behaviour and an existing host path. Use -v host:container only when you accept legacy auto-create of directories. Do not mix the two expectations in the same script.
How to Prevent the Issue
- Standardize on
--mountwith absolute, pre-created paths in scripts and Compose files so failures surface early instead of silently auto-creating empty dirs. - Validate required directories in your entrypoint or
maketarget (mkdir -p/[ -d ]) before invokingdocker run. - Quote and default-check every path variable (
"${VAR:?}") to eliminate empty-source errors in CI. - Document the Docker Desktop file-sharing roots your team needs so new machines are configured once.
- On SELinux hosts, bake
:z/:Zinto your run commands and review them so containers do not silently lose access. See more in Docker guides.
Related Docker Errors
- Docker Error: OCI runtime create failed — when the mount config is valid but the runtime still cannot set up the container, often a path or permission problem one layer deeper.
- Docker Error: cannot connect to the Docker daemon — if the daemon is unreachable, mount validation never even runs.
- Browse the full Docker troubleshooting category for more daemon and runtime error guides.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.