I have bash script which runs as docker entrypoint.
This script does some things and then sleeps.
I need to be able to gracefully stop this script when docker stop
command is issued. AFAIK docker sends SIGTERM
signal to the process 1.
So I created bash script which reacts to SIGTERM
.
It works fine without docker, I can launch it, issue kill -TERM <pid>
and it gracefully stops the script. Unfortunately it does not work in docker.
Dockerfile:
FROM ubuntu:20.04
WORKDIR /root
COPY test.sh .
CMD ./test.sh
test.sh:
#!/bin/sh
trap 'echo TERM; exit' TERM
sleep 1 &
while wait $!
do
sleep 1 &
done
How should I modify script or Dockerfile to allow docker stop to work without issues?
Please note that I'm not allowed to pass -it
argument to docker run
.
CodePudding user response:
The problem comes from the shell form of the CMD
instruction: CMD ./test.sh
.
In this case the command is executed with a /bin/sh -c
shell. So the /bin/sh
runs as PID 1
and then forks test.sh
, PID 1
is /bin/sh -c ./test.sh
. In consequence the SIGTERM
signal is sent to the PID 1
and never reaches test.sh
.
To change this you have to use the exec form: CMD ["./test.sh"]
. In this case, the command will be executed without a shell. So the signal will reach your script.
FROM ubuntu:20.04
WORKDIR /root
COPY test.sh .
CMD ["./test.sh"]
Run and kill.
# run
docker run -d --name trap trap:latest
# send the signal
docker kill --signal=TERM trap
# check if the signal has been received
docker logs trap
# TERM
CodePudding user response:
I suggest you to try with docker kill --signal=SIGTERM <CONTAINER_ID>
.
Please let me know if it will work.
CodePudding user response:
Note if your script happens to spawn child process, you may leave behind orphan process upon your docker exit. Try run with --init flag like docker run --init ...
, the built-in docker-init executable tini
will assumed pid 1 and ensure all child process (such as your sleep example) will be terminated accordingly upon exit.