Search code examples
dockerexit-codedocker-entrypointdocker-command

Docker: can a cmdline argument be appended to a shell built-in command args?


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?


Solution

  • 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
    $ _