I want to create a docker image with a cmdline-specifiable exit code.
From this question, I learned that I must use exit
as an argument to sh
because it is a shell built-in command, not an executable: How to make a docker container exit with a specific error-code with docker-compose?
I.e. I can create a docker container that exits with error-code 42 as follows:
# Dockerfile
FROM alpine:3.15 as base
ENTRYPOINT ["sh", "-c", "exit 42"]
$ docker build -t tmp:tmp . && docker run tmp:tmp
[+] Building 0.4s (5/5) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 181B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [internal] load metadata for docker.io/library/alpine:3.15 0.0s
=> CACHED [1/1] FROM docker.io/library/alpine:3.15 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:3034115e85f4ac9322c3e3e5d69f4445e30cc652f3b836d0145545305fda6ad1 0.0s
=> => naming to docker.io/library/tmp:tmp 0.0s
$ echo $?
42
$
Question:
Can the docker container be made to return an exit-code specified as a cmdline argument?
E.g. is this possible:
$ docker build -t tmp:tmp . && docker run tmp:tmp 64
...
$ echo $?
64
$
?
What I've tried:
This article -- https://goinbigdata.com/docker-run-vs-cmd-vs-entrypoint/ -- led me to try this combination of ENTRYPOINT
and CMD
:
# Dockerfile
FROM alpine:3.15 as base
ENTRYPOINT ["sh", "-c", "exit"]
CMD ["0"]
$ docker build -t tmp:tmp . && docker run tmp:tmp 64
...
$ echo $?
0
Interestingly, this same "pattern" of Dockerfile worked for echo
:
# Dockerfile
FROM alpine:3.15 as base
ENTRYPOINT ["echo", "hello"]
CMD ["world"]
$ docker build -t tmp:tmp . && docker run tmp:tmp
...
hello world
$
$ docker build -t tmp:tmp . && docker run tmp:tmp foo
...
hello foo
$
I think my failed experiment with ENTRYPOINT
and CMD
is explained by this experiment:
$ sh -c "exit 42"
$ echo $?
42
$ sh -c "exit" 42
$ echo $?
0
...I hoped that my Dockerfile with ENTRYPOINT ["sh", "-c", "exit"]
and CMD ["0"]
would result in the former, but I think it results in the latter -- true?
All your docker run arguments are being passed to your entrypoint.sh
if you have one defined.
For example in my Dockerfile I have:
# prepare container
COPY entrypoint.sh /
ENTRYPOINT ["/entrypoint.sh"]
And in my entrypoint.sh
printf "Custom exit code '$*'\n"
exit "$@"
And then just run with args:
$ docker run verify 129
Custom exit code '129'
$ echo $?
129
$ _