Table of Contents
What this error means
Compose is telling you that a bind mount’s host side is not an absolute path. Docker can’t mount a relative path from your machine into a container unless Compose resolves it to an absolute path first.
Typical triggers:
- Long syntax with type: bind and a relative source (e.g., source: ./data)
- OS-specific path formatting issues (Windows drive letters, backslashes)
- Using ~ (home) or unexpanded variables in YAML
Quickstart fix
Use an absolute path or the built-in ${COMPOSE_PROJECT_DIR} variable, which expands to the directory containing your compose file.
- Cross‑platform (recommended): ${COMPOSE_PROJECT_DIR}/data
- Linux/macOS: ${PWD}/data (works when PWD is set)
- Windows: C:/Users/you/project/data (forward slashes)
If you don’t need a host path, prefer a named volume to avoid path issues entirely.
Minimal working example (bind mount)
Create a data directory next to your compose file and start a container that writes to it.
tversion: "3.9"
services:
app:
image: busybox:1.36
command: ["sh", "-c", "echo hello >> /data/out.txt && tail -f /dev/null"]
volumes:
- type: bind
source: ${COMPOSE_PROJECT_DIR}/data
target: /data
bind:
create_host_path: true
Run:
docker compose up -d
ls ./data
cat ./data/out.txt
This works on Linux, macOS, and Windows (Docker Desktop) because COMPOSE_PROJECT_DIR resolves to an absolute path.
Minimal working example (named volume, no host path)
tversion: "3.9"
services:
app:
image: busybox:1.36
command: ["sh", "-c", "echo hello >> /data/out.txt && tail -f /dev/null"]
volumes:
- appdata:/data
volumes:
appdata:
No host path—so no absolute-path problem.
Step-by-step: Fixing your compose file
- Identify mounts that need host paths
- In service.volumes, entries like ./data:/data or long syntax with type: bind use a host path.
- Switch to an absolute path
- Best: source: ${COMPOSE_PROJECT_DIR}/data
- Or: use a full OS path, e.g., /home/alice/proj/data or C:/Users/Alice/proj/data
- Keep Windows paths portable
- Use forward slashes: C:/Users/Alice/proj/data
- Ensure the path is under a shared location (e.g., C:/Users) if file sharing is enabled in Docker Desktop.
- Prefer named volumes when you don’t need a specific host directory
- Replace host path with a named volume and declare it under top-level volumes.
- Validate expansion before running
- Print the rendered config: docker compose config
- Confirm the source paths are absolute in the output.
Common patterns (good vs. bad)
- Good (long syntax, cross‑platform):
volumes:
- type: bind
source: ${COMPOSE_PROJECT_DIR}/logs
target: /var/log/app
- Good (short syntax, explicit absolute):
volumes:
- /home/alice/app/logs:/var/log/app:rw
- Windows good:
volumes:
- C:/Users/Alice/app/logs:/var/log/app
- Bad (relative in long syntax):
volumes:
- type: bind
source: ./logs # Likely: The path must be absolute
target: /var/log/app
- Bad (tilde not expanded):
volumes:
- ~/logs:/var/log/app # ~ is not expanded by Compose
Cross-platform variable approach
Define an absolute path in .env per machine, or rely on COMPOSE_PROJECT_DIR.
- Using COMPOSE_PROJECT_DIR (no .env needed):
volumes:
- type: bind
source: ${COMPOSE_PROJECT_DIR}/data
target: /data
- Using a custom DATA_DIR from .env:
DATA_DIR=/absolute/path/to/project/data
volumes:
- type: bind
source: ${DATA_DIR}
target: /data
On Windows PowerShell, create .env with an absolute path via:
"DATA_DIR=$(Get-Location).Path\data" | Out-File -Encoding ASCII .env
Then edit slashes to forward (C:/...) or rely on Compose handling. Forward slashes are safest.
Troubleshooting checklist
- docker compose config shows absolute source paths
- The host directory exists or create_host_path: true is set
- Windows: path is shared with Docker Desktop and uses forward slashes
- WSL2: run compose inside the Linux distro and use Linux paths (/home/… or /mnt/c/…)
- You’re not mixing a named volume name with type: bind (that’s invalid)
Performance notes
- Bind mounts are convenient but can be slower, especially on macOS/Windows where file I/O crosses the virtualization boundary.
- Prefer named volumes for heavy, hot I/O (databases, caches). Use bind mounts mainly for source code.
- Avoid mounting large node_modules or build directories; consider .dockerignore or multi-stage builds.
- On Windows/macOS, keep projects under the default shared locations (e.g., C:/Users, $HOME) to reduce overhead.
Pitfalls to avoid
- Relative source in long syntax for binds (use COMPOSE_PROJECT_DIR or a full path)
- Tilde (~) and %USERPROFILE% not expanded by Compose unless provided via .env or environment
- Backslashes in Windows paths; prefer forward slashes
- Mounting a file vs. directory: specify the exact host file path when targeting a file
- Using docker stack deploy: Swarm nodes require absolute host paths that exist on every node
FAQ
Q: Can I use relative paths for bind mounts? A: Use ${COMPOSE_PROJECT_DIR}/relative-dir to ensure they resolve to an absolute path. Plain ./dir in long syntax often triggers the error.
Q: Why does short syntax sometimes work and long syntax fails? A: Some implementations are stricter with long syntax (type: bind). Using an already-absolute source avoids ambiguity.
Q: How do I mount a single file? A: Use the absolute path to the file on the host: /abs/path/app.conf:/app/app.conf:ro.
Q: How do I make this portable across OSes? A: Use ${COMPOSE_PROJECT_DIR} or a .env variable set to an absolute path per machine.
Q: Should I use a named volume instead? A: Yes, if you don’t need a specific host directory. It avoids path errors and is usually faster for heavy I/O.