With this image (the Caddy webserver):
docker run --rm -p 80:80 caddy:latest
I can stop it with sending CTRL+C within the terminal.
Some other images won’t work this way, for example MariaDB:
docker run -it --rm -p 3306:3306 -e MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=true mariadb:latest
I’m not able to stop it with CTRL+C
I’ve noticed that in Caddy Dockerfile
there is no ENTRYPOINT
but only CMD
, whereas MariaDB has both an ENTRYPOINT
and a CMD
.
Why? Is there any reason NOT to support the handling of a kill signal? How can one support the SIGTERM
in a docker entrypoint, if that is the reason?
2
Answers
Don’t forget that Docker 1.13 comes with
tini
, originally fromkrallin/tini
.Any image run with
docker run --init
would include aninit
inside the container that forwards signals and reaps processes.As mentioned here,
tini
works transparently, Dockerfiles don’t need to be modified in any way.So, In Unix systems, when you press
CTRL+C
in a terminal, aSIGINT
(Signal Interrupt) is sent to the foreground process group, which in this case is the Docker container. If you useCTRL+
, it sendsSIGQUIT
, and if you useCTRL+Z
, it sendsSIGTSTP
(Signal Stop).Docker containers run a single main process, and this process runs in PID 1.
PID 1 is special on Linux: it is the first process that runs and is the ancestor of all other processes.
It also has a special relationship with Unix signals: it is the only process that can choose to ignore
SIGINT
andSIGTERM
. Other processes cannot ignore these signals, but they can have handlers that execute when they receive them.In Docker, when you use
CMD
to specify the process to run, Docker will wrap that process with a smallinit
system (liketini
), which properly handles Unix signals and forwards them to the main process (I mentioned it originally here).This is why your
caddy
image, which does not have anENTRYPOINT
and only hasCMD
, can handle theCTRL+C
.However, when you use
ENTRYPOINT
, Docker does not wrap the process with this smallinit
system, and the process runs as PID 1.If the process does not have built-in handling for
SIGINT
orSIGTERM
, it will not respond toCTRL+C
. This is why yourmariadb
image, which has anENTRYPOINT
, does not stop when you pressCTRL+C
.The handling of a kill signal is an important part of a graceful shutdown. When a process receives a
SIGTERM
(orSIGINT
), it should stop accepting new work, finish its current work, and then exit. This allows it to clean up any resources it is using and ensure data consistency.If the process does not handle these signals and is simply killed (with
SIGKILL
), it does not have a chance to clean up and may leave resources in an inconsistent state. This could be harmful in the case of a database like MariaDB, which could have uncommitted transactions or partially written data.To support the handling of a kill signal in a Docker entrypoint, you can:
Add signal handling to the entrypoint script itself. This requires modifying the script and might not be feasible if the entrypoint is a binary.
Use an
init
system that can handle signals and forward them to the main process. There are smallinit
systems liketini
that are designed for this purpose. You can use them in your Dockerfile like this:This will run
tini
as PID 1, which will handle signals and forward them to your command.Use Docker’s built-in init, which is a minimal
tini
implementation. You can enable it with the--init
option when you run your container:This will run Docker’s built-in init as PID 1, which will handle signals and forward them to MariaDB.
These methods ensure that your Docker entrypoint can handle kill signals and perform a graceful shutdown when necessary.
Not sure, unless you want your image to be really:
But generally, ignoring termination signals can lead to issues like data loss, resource leakage, or zombie processes, and should be avoided.
MariaDB ignores SIGINT by masking its delivery to the process using
sigprocmask
.This was done a long time ago on some assumptions maybe around accidental triggering on shutdown when started in a terminal. There might be a case in old-school sysv scripts where a closed terminal quickly after
service mariadb start
may have delivered a SIGINT tomariadbd
(unverified). I can’t see any requests to remove the SIGINT masking.The –gdb option on the command line will prevent the ignoring of SIGINT and achieve the results. It can also be provided in a .cnf file.
MariaDB can handle termination at any point, including SIGKILL (cannot be caught except by an init process) or power failures. This is part of the durability (the D in ACID) for transactional databases. Upon restart uncommitted transactions are cleaned up. Doing a graceful termination does mean the startup doesn’t need a crash recovery and its quicker however.