Docker follow symlink outside context
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
This question usually appears when a Docker build or bind mount seems to "lose" files behind a symbolic link. The short answer is that Docker treats build-time context and runtime mounts differently, and a symlink that points outside the allowed context is usually blocked for security reasons.
Build Context Is the Real Boundary
When you run docker build ., Docker sends a build context to the builder. Only files inside that context are available to COPY and ADD. A symlink inside the context does not magically grant access to files outside the context.
For example, imagine this host layout:
A Dockerfile like this is misleading:
Even though project/shared exists as a symlink, the target directory lives outside the build context. Docker does not treat that as permission to copy arbitrary host files.
The fix is structural, not magical. Move the needed files under the build context, choose a larger context root, or use an additional named context if your build setup supports it.
A Safe Project Layout
One common solution is to move the Dockerfile one level higher so both directories are within the context:
Then the build becomes explicit:
And you build from workspace:
This keeps the dependency visible and reproducible. Hidden filesystem reach-through is exactly what Docker tries to prevent.
Runtime Mounts Behave Differently
At container runtime, bind mounts expose a real host path into the container. Symlink behavior now depends on the mounted directory and the host filesystem.
Example:
If /data/link.txt is a symlink, the container can see that symlink. Whether opening it succeeds depends on where the target points and whether that target is also reachable from inside the container.
So there are two separate questions:
- Can the container see the symlink entry
- Can the target path be resolved inside the container
A symlink that points to /Users/name/secrets.txt on the host usually fails inside the container unless that host path is also mounted.
Diagnosing the Problem Quickly
If you are unsure whether the failure is at build time or runtime, reduce it to a tiny repro:
If the build fails on COPY, the issue is almost certainly the build context boundary. If the image builds but the running container cannot open the file, inspect the resolved path from inside the container:
Common Pitfalls
The biggest mistake is assuming Docker follows symlinks like a normal local shell command. It does not, because image builds must be reproducible and must not read arbitrary files from the host.
Another mistake is solving the issue by building from the filesystem root. That works technically, but it sends an enormous context, slows builds, and increases the chance of copying secrets into the image.
A third mistake is forgetting .dockerignore. Even when you choose a larger safe context, you should still exclude directories such as .git, node_modules, logs, and credentials to keep the build smaller and safer.
Summary
- Docker build instructions can only access files inside the build context.
- A symlink inside the context does not grant access to targets outside it.
- Runtime bind mounts are different and depend on what host paths are actually mounted.
- The safest fix is usually to change the project layout or build context root.
- Use
.dockerignoreso a broader context does not become a slower or riskier build.

