Job docker-build-fails-only-in-ci · revised 11 October 2026
Make one Docker image build from a clean checkout in CI and start healthy
One Docker image builds from a fresh checkout on your CI runner for the platform you agreed, and a container from it passes your health check. We inspect its build arguments and history for secrets.
You might be seeing
- A COPY step reports a file that exists on a laptop is not found in the CI build
- The image builds in CI but the server reports an executable format error or the container exits at once
No passwords, keys, card details or admin invites needed to start.
What usually happened
The build depends on something a clean CI checkout does not have or does not match. The build context leaves out a file through an ignore rule or is rooted in the wrong directory, a file name differs in letter case between a laptop and Linux, a build argument or private package token is not passed, a cached layer hid a failure, or the image was built for a different processor architecture from the one that runs it.
Who it’s for: A small team whose container image builds on a developer laptop but fails in CI, or builds in CI and then fails to start on the server.
Usually starts when: The image build step fails with a missing file, a missing build argument or an access error in CI, or the published image is rejected on the server with an architecture or start-up error.
The result: The named image builds from a fresh checkout on the CI runner with no existing layer cache, for the processor platform or platforms agreed before work starts, and a container started from it passes the agreed health check and stays up for the agreed time. No secret value appears in the build arguments or the image history we inspect, and the Dockerfile does not copy any credential file you name. This is an inspection of arguments, history and copy instructions, not a scan of the files inside every layer.
Check whether this job fits
Compare where the image fails. The place decides whether this is a build problem or a platform mismatch.
Checks you can run yourself
Compare the build folder with a fresh clone
Clone the repository into an empty folder and list its top-level files next to the folder you normally build from. Do not edit anything.
Look for: Files the Dockerfile copies that are missing from the clone, ignore rules that would exclude them, and file names that differ only by letter case.
What you get
- A pull request with the change and a note naming the cause
- Links to the failing build and to a passing clean build, with the platform shown
- Health-check output from a container started from the image, and the inspection of the published manifest if the image is pushed
- Steps to revert the change
Included
- One image, built from one Dockerfile in one repository, on one CI system
- Reproduce the failure from a clean checkout, and compare the build context, the build arguments, the secrets route and the target platform with what the Dockerfile expects
- Correct the Dockerfile, the ignore file, the build step or the platform setting with the smallest change
- Build for the agreed platform or platforms, start a container and run the agreed health check
- Inspect the build arguments and image history for secret values, and check the Dockerfile's copy instructions against the credential file names you list
Not included
- Redesigning the application or its configuration
- Shrinking the image or speeding up rebuilds: that is a separate performance job
- Container orchestration, networking, volumes or production deployment
- Registry setup, billing or access policy changes
- Vulnerability remediation or any statement that the image is secure
- A scan of the files inside the image layers for secrets, or any statement that the image holds no secret
How we know it’s done
Agreed with you before work starts. Each check produces evidence you keep.
The named image builds from a fresh checkout on the CI runner with no existing layer cache, for each platform agreed before work starts, and the build step exits successfully.
Evidence: Links to the baseline failing build and the passing clean build, showing the platform and that no cache was used.
A container started from the built image passes the agreed health check and stays up for the agreed time without restarting.
Evidence: The health-check output and container status from the run, and the published manifest listing the agreed platforms if the image is pushed.
The build arguments and the image history show no secret value, the Dockerfile copies none of the credential file names you listed, and no existing image tag was moved. This inspects arguments, history and copy instructions; it does not scan the files inside every layer.
Evidence: The reviewer's inspection of the build arguments and image history, the list of credential file names checked and the list of tags touched.
Your authorised maintainer accepts the evidence and merges the pull request.
Evidence: Your written sign-off and the merged pull request record.
Sign-off. You inspect the clean build, the health check, the build arguments and the image history, sign off in writing and merge the pull request. Payment follows sign-off.
If it fails. If the clean build or the health check does not pass for the agreed platforms, you do not pay for this fixed scope. If the cause is a registry restriction, missing files or a platform we cannot build for, we explain it with the evidence and stop.
When it fits, and when we stop
It fits when
- The build can run from a clean clone of the repository, with no files kept outside it
- You can name the CI step that builds the image and the platform of the machine that runs it
- A private package token or other secret, if needed, can be passed through your CI secret store, which you control
- A health command or URL for the container exists or can be agreed
We stop and tell you if
- The image can only be built with files or credentials that are not in the repository and that you cannot supply safely
- The cause is a registry, quota or billing restriction
- The image needs a service we cannot start without production data
- The runner cannot build for the target platform and a builder for it cannot be provided
What could go wrong
Before merge, closing the pull request leaves your default branch unchanged. After merge, your maintainer can revert the commit. Any scratch image pushed for testing is named so you can delete it, and no production tag is moved.
Scroll the table sideways to read it all.
| Risk | How we handle it |
|---|---|
| A secret passed as a build argument remains in the image history. | Secrets go through the CI secret store and a build secret mount; the reviewer inspects the build arguments and image history, checks the Dockerfile's copy instructions against the credential file names you list, and acceptance fails if a value or a listed file appears. A secret copied into the image as a file that you did not list would not show in the image history, and we say so in the handover. |
| A cached layer makes a broken build look healthy. | Acceptance requires a build from a fresh checkout with no layer cache. |
| A test push overwrites a tag you use. | Test pushes use a scratch name agreed in advance, and no existing tag is moved. |
An independent reviewer checks that the passing build really started from an empty cache, that the target platform is the one named, that no secret value appears in the build arguments or image history and no listed credential file is copied and that the health check ran against the built image. Your maintainer reviews and merges.
How we deliver
We arrange the work and independent review, then show you the result against the agreed checks. You keep authority over your systems.
- Agree the image, the platform or platforms, the health check and the branch-build permission in writing
- Reproduce the failure from a clean checkout on the CI runner without layer cache and record the baseline
- Compare the context, ignore rules, build arguments, secret route and platform with the Dockerfile
- Make the smallest change that lets the clean build succeed for the agreed platform, without passing a secret as a build argument or copying a listed credential file
- Build from a clean checkout again, start a container, run the health check and inspect the build arguments and image history
- Have an independent reviewer check the runs, the diff, the build arguments and the image history, then hand over the pull request and revert notes
This is a one-off job, not emergency cover or a subscription. We confirm eligibility, the total price, a start window and a delivery date before you accept. Work starts only after agreed inputs, secure access and necessary permissions are in place. Platform, runner and supplier charges are excluded unless the written quote includes them. No charge or booking is created by an enquiry.
Need to keep it working?
If images keep breaking as base images change, a monthly rehearsal can build them from a clean checkout and report what changed.
Ongoing work is separately scoped and quoted: no monitoring, response-time guarantee or automatic subscription is included in this job.
Explore an ongoing engineering lane, or mention the responsibility you need in your enquiry.
What you can check
This is a new service. We have not delivered this job for a client yet.
Other ways to get this done
- Docker explains what a build context is and how an ignore file removes files from it before the builder sees them. Your maintainer can check both before buying anything. docs.docker.com
- If the failure is an architecture mismatch, Docker's multi-platform guide explains the build options, including the slower emulated option and cross-compilation. docs.docker.com
Questions
The image works on my laptop. Why would CI differ?
A clean CI checkout lacks local files, may have a different file-name case rule and may build for a different processor architecture. We compare each of those instead of guessing.
Do you push to our production registry tags?
No. A test push, if needed, uses a scratch name that you agree and can delete. No existing tag is moved.
Will you make the image smaller?
Not in this job. Size and rebuild speed are separate changes and are not part of the fixed scope.
Does this prove there is no secret anywhere in the image?
No. We inspect the build arguments and the image history, and check that the Dockerfile does not copy the credential files you name. We do not scan the contents of every file inside the layers, so the job makes no claim that the image is free of secrets.
Send an enquiry
Send us
- The CI build step's first error, with secrets removed
- The Dockerfile's base image line and the processor architecture of your laptop, CI runner and server, if you know them
- Whether the build needs a private package token, and the name of the secret store that holds it
- Do not send credentials, source code or an access invitation in the first enquiry
Later, once you agree
- The Dockerfile, ignore file and build step through an authorised company-controlled repository route, with a branch for the pull request
- Read access to the named build logs
- Written approval for branch builds, and for a test push to a scratch image name if the image must be pushed
- The names (only the names) of any credential files, such as an npm or pip configuration file or a key file, that the Dockerfile must never copy into the image
You own the repository, the CI account, the registry and the secrets. We work from authorised files on a branch through a company-controlled identity and never hold your registry or package credentials. You approve branch builds and merge the pull request.
Email fallback: open your mail app
If website submission is unavailable, review and send the fallback email yourself. An email fallback is not a website receipt. Or write to hello@syntheticindustry.ai with “docker-build-fails-only-in-ci” as the subject.