Reputation: 997
I have a script which I want to optionally run within a container. I have observed that if I run an intermediate script it can be killed with Ctrl-C
, however if I do not then it can't.
Here is an example:
test1.sh
:
#!/bin/bash
if [ "${1}" = true ]; then
while true; do echo "args: $@"; sleep 1; done
else
docker run --rm -it $(docker build -f basic-Dockerfile -q .) /test2.sh $@
fi
test2.sh
:
#!/bin/bash
/test1.sh true $@
basic-Dockerfile
:
FROM alpine:3.7
RUN apk add --no-cache bash
COPY test1.sh test2.sh /
ENTRYPOINT ["bash"]
Running ./test1.sh true foo bar
will happily print out true foo bar
, and running ./test1.sh foo bar
will do the same in a container. Sending Ctrl-C
will kill the process and delete the container as expected.
However if I try to remove the need for an extra file by changing /test2.sh $@
to /test1.sh true $@
:
test1.sh
#!/bin/bash
if [ "${1}" = true ]; then
while true; do echo "args: $@"; sleep 1; done
else
docker run --rm -it $(docker build -f basic-Dockerfile -q .) /test1.sh true $@
fi
then the process can no longer be terminated with Ctrl-C
, and instead must be stopped with docker kill
.
Why is this happening?
Docker version 18.06.1-ce running on Windows 10 in WSL
Upvotes: 0
Views: 4185
Reputation: 1416
You can also you can also use exec
to replace the current shell with a new one which can be stopped with ctrl-c
For example start.sh script which starts nginx server and runs uwsgi
#!/usr/bin/env bash
service nginx start
uwsgi --ini uwsgi.ini
should changed to
#!/usr/bin/env bash
service nginx start
exec uwsgi --ini uwsgi.ini
After theese changes ctrl c will stop the container
Upvotes: 3
Reputation: 8026
That's a common misunderstanding in docker but it's for a good reason.
When a process run as PID 1 in Linux it behaves a little different. Specifically, it ignores signals as SIGTERM (which you send when hitting Ctrl-C), unless the script is coded to do so. This doesn't occur when PID > 1.
And that's why your second scenario works (The PID 1 is script2.sh, which delegates the signal in script1.sh, which stops because it is not PID1) but not the first one (script1.sh is PID 1 and thus it doesn't stop with SIGTERM).
To solve that, you can trap the signal in script1.sh and exit:
exit_func() {
echo "SIGTERM detected"
exit 1
}
trap exit_func SIGTERM SIGINT
Or tell docker run
to init the container with a different process as PID 1. Specifically, if you add --init
to docker run with no more arguments, it uses a default program, tini, prepared to handle these situations:
docker run --rm -it --init $(docker build -f basic-Dockerfile -q .) /test1.sh true $@
Upvotes: 6