A stray file just leaked into a Docker image build, and a careless docker image build context is usually why. This guide builds a tagged image from a local Dockerfile, verifies that the image exists, and keeps the build context small enough that credentials and unrelated files are not sent to the builder. The installed client is Docker 29.8.1 from package docker-ce-cli version 5:29.8.1-1~ubuntu.24.04~noble.
Allow about fifteen minutes. You need Docker Engine or another working Docker builder, a shell, and a project directory containing a Dockerfile. The build itself is an ordinary user command when your account can access Docker. Adding yourself to the Docker group is an administrative security decision and is not required by this guide.
Confirm the client version and the command syntax before changing anything:
$ docker --version
Docker version 29.8.1, build 4a63305
$ docker image build --help
Usage: docker image build [OPTIONS] PATH | URL | -
docker image build is the documented command. The installed manpage also describes docker build as its alias. The final positional argument is the build context. A local directory, a Git or tarball URL, or - for standard input can be used as that context.
Checkpoint: check that the builder is reachable:
$ docker info
This prints client and server information when the daemon or selected builder is available. If it reports that it cannot connect, fix the Docker service, context or permissions first. Do not add sudo automatically: use it only when your host's Docker administration policy requires it.
Change into the directory that contains the files the image is allowed to read. The context is not just a label: instructions such as COPY and ADD can use files inside it. A broad context can make builds slower and can expose files that should never reach a builder.
$ cd /path/to/project
$ find . -maxdepth 2 -type f -print | sort
$ test -f Dockerfile
Review the list before building. Add a .dockerignore file for local credentials, build output and other material that the image does not need:
.git
.env
.env.*
*.pem
*.key
node_modules
dist
This is a filter for the build context, not a substitute for secret handling. Do not put passwords, tokens or private keys in a Dockerfile or pass them through --build-arg. Build arguments can be visible in build metadata and are not a secret store.
Checkpoint: run git status --short and inspect .dockerignore before continuing. If the project uses a different Dockerfile name, record its path for the next step.
Build from the current directory and give the result a name that includes a repository and tag:
$ docker image build --tag example-app:local .
[+] Building ...
=> exporting to image
=> => naming to docker.io/library/example-app:local
Replace example-app:local with a name suitable for your registry or deployment. The final . is significant. It selects the current directory as the context, while Docker looks for ./Dockerfile by default.
For a differently named Dockerfile, keep the context and file selection separate:
$ docker image build --file Dockerfile.production --tag example-app:production .
The --file option selects the Dockerfile. It does not change the context. A Dockerfile cannot safely make an arbitrary file outside the context available with a relative COPY path. Move or deliberately widen the context only after reviewing what that sends to the builder.
Building executes the instructions in the Dockerfile and may download base images or packages. Review those instructions before running an unfamiliar file. A RUN instruction can execute commands with the permissions available to the builder, and a remote context can change when its source changes. Stop if the source or base image is not trusted.
A successful build is not the same as a useful image. Ask Docker for the exact tag and record the immutable image identifier:
$ docker image inspect example-app:local --format '{{.Id}}'
sha256:REPLACE_WITH_THE_ID_PRINTED_ON_YOUR_HOST
$ docker image ls example-app:local
The identifier is host-specific, so do not compare it with a copied example. The inspect command should return one ID. If it says that the image is missing, check the tag spelling and the build output before running another build.
For automation, write the ID to a file during the build and read it back afterwards:
$ docker image build --iidfile /tmp/example-app.iid --tag example-app:local .
$ test -s /tmp/example-app.iid
$ sed -n '1p' /tmp/example-app.iid
The temporary file contains the result identifier. Remove it after recording the value if it is no longer needed:
$ rm -- /tmp/example-app.iid
This removal is reversible only if you have another copy of the identifier. It does not remove the image. To remove a locally built image later, first confirm the exact tag, then run docker image rm example-app:local. That may fail when a container still refers to the image, and removing the tag does not necessarily delete shared layers.
Normal builds may reuse cached layers. Use --no-cache when you need each Dockerfile instruction rebuilt, for example when checking whether a package installation is still reproducible:
$ docker image build --no-cache --tag example-app:clean .
This does not guarantee that every remote dependency is unchanged. Use --pull when the build should attempt to fetch a newer base image:
$ docker image build --pull --tag example-app:latest .
Those flags can make a build slower and can change its result. Record the Dockerfile, context revision, base-image digest and relevant build arguments when reproducibility matters.
--build-arg NAME=value supplies a build-time variable declared by the Dockerfile. Treat its value as non-secret and avoid putting credentials there. The installed manpage also provides --network for the network mode used by RUN instructions. Restricting network access can expose a hidden dependency, but changing it may also break a build that downloads packages.
A message about a missing Dockerfile usually means the context or --file path is wrong. Run pwd, ls -l and docker image build --help, then correct the path rather than copying a Dockerfile into a random directory.
A COPY failed message usually means the source is outside the context, excluded by .dockerignore, or spelled differently from the file on disk. Check both the context root and the ignore rules. Do not remove ignore rules containing secrets just to make a build pass.
If a build fails after executing RUN, read the failing instruction and its exit status. Re-run with normal output while investigating. --quiet suppresses build output and prints only an image ID on success, so it is useful for scripts after the build is stable, not for first diagnosis.
When an image was created with the wrong tag, tag the existing image only after inspecting the source ID, or remove the unwanted tag after confirming it. Avoid broad cleanup commands during an incident: images and layers may be shared by other containers.
docker image inspect returned the image ID for that exact tag.