Proposal: Propagate exit code for failing RUN commands
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 10.3k
- Forks
- 1.5k
- Avg merge
- 1d 23h
- Merged PRs (30d)
- 48
Description
If a RUN command fails when using buildkit, docker currently always exits with exit code 1 no matter what exit code the original command produced. It would be useful to propagate the command's exit code out to the shell so those failures have a chance to be distinguishable from errors of the docker engine.
Docker version 20.10.16, build aa7e414
Example Dockerfile,
FROM alpine:latest
RUN exit 123
Without buildkit, the RUN command's exit status is available to the shell,
$ DOCKER_BUILDKIT=0 docker build .; echo "build exit status is: $?"
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM alpine:latest
---> e66264b98777
Step 2/2 : RUN exit 123
---> Running in 45def427bdd8
The command '/bin/sh -c exit 123' returned a non-zero code: 123
build exit status is: 123
A failure from the engine (I deleted a cache dir) returns a distinguishable 1 exit code,
$ DOCKER_BUILDKIT=0 docker build .; echo "build exit status is: $?"
Sending build context to Docker daemon 2.048kB
Step 1/2 : FROM alpine:latest
---> e66264b98777
Step 2/2 : RUN exit 123
open /var/lib/docker/overlay2/6ae2b51f5d0afdf49509f10a2c55476fc068b7436321c443cd0a23fc09c80d1b/committed: no such file or directory
build exit status is: 1
With buildkit, the exit status is always 1 when the RUN command fails
$ DOCKER_BUILDKIT=1 docker build .; echo "build exit status is: $?"
...
#5 [2/2] RUN exit 123
#5 sha256:136f9a7caa0b737f748cca87a56ede17c6681d8ebec4a05acedf9aac3afd41bd
#5 ERROR: executor failed running [/bin/sh -c exit 123]: exit code: 123
------
> [2/2] RUN exit 123:
------
executor failed running [/bin/sh -c exit 123]: exit code: 123
build exit status is: 1
and when the docker engine fails
$ DOCKER_BUILDKIT=1 docker build .; echo "build exit status is: $?"
[+] Building 0.1s (5/5) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 43B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/alpine:latest 0.0s
=> CACHED [1/2] FROM docker.io/library/alpine:latest 0.0s
=> ERROR [2/2] RUN exit 123 0.0s
------
> [2/2] RUN exit 123:
------
failed to prepare kcywk5z6l6azc6amb8bs9en7h: open /var/lib/docker/overlay2/6ae2b51f5d0afdf49509f10a2c55476fc068b7436321c443cd0a23fc09c80d1b/committed: no such file or directory
build exit status is: 1
This makes it difficult to programmatically determine where the failure is.
In a real use case, in CI pipelines, I would be able to run docker prune to reset the cache and retry the build when the engine fails (almost all of our routine engine errors are because of a corrupt overlay cache). Whereas I could notify the application team if it's a RUN failure.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the issue with the provided Dockerfile containing RUN exit 123, comparing DOCKER_BUILDKIT=0 and DOCKER_BUILDKIT=1 through docker build. Trace the build command's exit status and distinguish a failed RUN command from the documented engine error; done means the original RUN exit code is propagated while engine failures remain distinguishable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, go
- Domain
- build-system, cli
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100