16.1.1.2 Build Directory Mistake
A focused guide to Build Directory Mistake, connecting core concepts with practical Docker and container operations.
A build directory mistake covers the category of build problems caused by running docker build from the wrong working directory, specifying an incorrect path as the build context, or misunderstanding how Docker resolves relative paths during a build, all of which produce confusing symptoms, missing files, an unexpectedly large context, or files copied from the wrong source, that trace back to a simple directory or path error rather than anything wrong with the Dockerfile's actual instructions.
Running the build from the wrong directory
The most basic version of this mistake is invoking docker build from a directory that is not actually the intended build context, often after navigating elsewhere in a terminal session and forgetting to return:
cd /home/user/projects/my-api/scripts
docker build -t my-api ..
This particular invocation does correctly specify the parent directory as context using .., but it is easy to instead run docker build -t my-api . from the wrong directory entirely, building against whatever happens to be in the current working directory rather than the actual project root, often producing a build that either fails immediately because no Dockerfile exists there, or, more confusingly, succeeds against an entirely unintended context if a different Dockerfile happens to exist in that location too.
pwd
docker build -t my-api .
Running pwd immediately before a build, as a habit, is a small but effective safeguard against this specific class of mistake.
Confusing the context argument with the Dockerfile path
The final positional argument to docker build specifies the build context, not the Dockerfile location; the -f flag specifies the Dockerfile separately, and conflating the two leads to passing a Dockerfile path where a context directory was expected, or vice versa:
docker build -t my-api Dockerfile
unable to prepare context: context must be a directory
This error message itself is the clearest signal that a file path was mistakenly passed where a directory was expected; the corrected invocation specifies the context directory and, separately if needed, the Dockerfile's actual location:
docker build -f Dockerfile -t my-api .
Nested project structures with multiple Dockerfiles
In a monorepo or multi-service project with several Dockerfiles, each intended to be built with a different context, building from the repository root without specifying the correct, narrower context for a specific service can either fail or, worse, succeed while including far more of the repository than that specific service actually needs:
my-monorepo/
service-a/
Dockerfile
src/
service-b/
Dockerfile
src/
docker build -f service-a/Dockerfile -t service-a .
Building this way from the repository root, with -f pointing at the specific service's Dockerfile but the context still set to the entire repository root, sends the entire monorepo as build context, which works but is unnecessarily large; a more scoped approach builds with the context set to the specific service's own subdirectory instead:
docker build -t service-a ./service-a
This requires the Dockerfile to only reference files within service-a/ itself, which is usually the more maintainable structure for a monorepo with genuinely independent services, avoiding cross-service file references that a narrower context would break.
Relative paths inside the Dockerfile behaving unexpectedly
Within the Dockerfile, every COPY source path is resolved relative to the build context root, not relative to the Dockerfile's own location, which is a frequent point of confusion specifically when the Dockerfile lives in a different directory than the context:
docker build -f docker/Dockerfile -t my-api .
COPY src/ ./src/
Here, src/ resolves relative to the repository root (the context, .), not relative to the docker/ directory where the Dockerfile itself lives, which is correct but frequently assumed incorrectly by someone newer to this specific distinction, leading to a COPY instruction that looks reasonable but references a path that does not actually exist relative to what the author assumed the base location to be.
Symlinks and directory mistakes
A build context containing a symlink pointing outside the context directory can produce inconsistent behavior, since the daemon may or may not be able to correctly resolve and include the symlink's target depending on the build backend and how the symlink is structured:
ls -la
lrwxrwxrwx shared-config -> ../shared/config
A symlink pointing outside the build context generally cannot be resolved correctly, since the target lies outside what was actually sent to the daemon; resolving this typically requires either moving the actual target inside the context, restructuring to avoid the symlink, or using BuildKit's named multiple contexts to reference the external location explicitly and intentionally.
Verifying the actual context being used
When uncertain whether a build invocation is using the intended context and Dockerfile, requesting verbose build output, or simply double-checking both arguments explicitly before running the command, resolves ambiguity quickly:
docker build --progress=plain -f path/to/Dockerfile -t my-api path/to/context 2>&1 | head -5
Sending build context to Docker daemon 4.2MB
A context size that looks obviously wrong, far too small or far too large for what is actually expected, is often the fastest confirmation that the wrong directory was specified, well before any Dockerfile instruction even begins executing.
Common mistakes
- Running
docker build .from an unintended working directory, without first confirming the current directory withpwd. - Passing a Dockerfile path where a build context directory was expected, or vice versa, confusing the two distinct arguments.
- Building a single service in a monorepo with an unnecessarily broad context covering the entire repository, rather than scoping the context to just that service's own directory.
- Assuming
COPYsource paths resolve relative to the Dockerfile's own location rather than relative to the actual build context root. - Including a symlink pointing outside the build context, producing inconsistent or failed resolution depending on the build backend.
Build directory mistakes are usually quick to both produce and resolve once correctly identified, and a habit of confirming the working directory, double-checking the context and Dockerfile path arguments explicitly, and sanity-checking the reported context size before assuming a Dockerfile instruction itself is at fault catches the large majority of this category of problem immediately.