Creating Advanced Entrypoints for Containers
Published on 05 Dec 2019Tags #Docker #Container #Kubernetes
There has been much confusion around the container entrypoint and parameters. This post will shed some light on this topic and present an script to serve as an flexible entrypoint.
ENTRYPOINT
and COMMAND
A Dockerfile
can contain ENTRYPOINT
and/or COMMAND
to specify the start behaviour of a container. The relation between the two con be described by a few basic rules:
-
If your
Dockerfile
contains onlyCOMMAND
, the contained command(s) will be executed when the container starts -
If your
Dockerfile
contains onlyENTRYPOINT
, the contained command(s) will be executed when the container starts -
If your
Dockerfile
containsENTRYPOINT
as well asCOMMAND
, the commands contained inENTRYPOINT
will be executed with the command contained inCOMMAND
as parameters
Note that these rule are valid even when ENTRYPOINT
and COMMAND
contain multiple commands.
It is possible to override ENTRYPOINT
by specifying the --entrypoint
parameter. COMMAND
is overridden by specifying parameters to the docker
command line:
docker run myimage these are parameters
Shell versus Exec format
Both ENTRYPOINT
as well as COMMAND
can be expressed in one of two formats:
- In shell format the commands are specified as simple strings:
ENTRYPOINT /entrypoint.sh
COMMAND these are parameters
The commands are prefixed with the contents of the SHELL
commands which defaults to /bin/sh -c
.
- In exec format the commands are expressed as an JSON array:
ENTRYPOINT [ "/entrypoint.sh" ]
COMMAND [ "these", "are", "parameters" ]
In this case, the SHELL
command is ignored and the commands are executed as is.
Writing an advanced entrypoint
It is always a good idea to support different ways to run a container. The default behaviour should be configured to match the primary use case. For example, if the container image is meant to run nginx
, it should be started by default.
Nevertheless, it is often necessary to analyze the behaviour of a container image without building a separate image. An entrypoint can be tailored to start an interactive shell or execute arbitrary commands.
The following entrypoint (/entrypoint.sh
) is making heavy use of the variable $@
which contains all the parameters passed to the script. $1
denotes the first entry of $@
. The contents of $@
are updated by the command set --
. At the end the updated parameters are used to execute the contained commands to replace the current process (exec
).
#!/bin/bash
set -o errexit
case "$1" in
sh|bash)
set -- "$@"
;;
*)
set -- nginx "$@"
;;
esac
exec "$@"
The following Dockerfile
embeds the above entrypoint and specifies the default parameters to execute nginx
in the foreground.
FROM nginx:alpine
COPY entrypoint.sh /
ENTRYPOINT [ "/entrypoint.sh" ]
CMD [ "-g", "daemon off;" ]
After building the above image, it can be used in the folllowing way:
- Allow
nginx
to launch with default behaviour:docker run -d myimage
- Run an interactive shell:
docker run -it myimage sh
- Run a command in the container:
docker run -it myimage sh -c pwd
- Show
nginx
version and test configuration:docker run myimage -vt
Based on this concept, container entrypoints can define more complex startup behaviour.