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?
2
Answers
All your docker run arguments are being passed to your
entrypoint.sh
if you have one defined.For example in my Dockerfile I have:
And in my entrypoint.sh
And then just run with args:
You are correct,
CMD
always passes its contents as new arguments to the entrypoint. You cannot insert it as part of an argument fromENTRYPOINT
.I’d also recommend Florin’s solution, that is, having a custom entrypoint. However, if you really need to, you can still do it with shell only:
This will run
sh
with 4 arguments, being-c
,exit "$@"
,sh
and42
(or your command). The last two arguments are what will be passed to the script asargv[0]
(which is the name of the shell itself) andargv[1]
, the first argument, which will be substituted into$@
.