The Docker platform leverages Docker containers to enable IT operations teams and Developer teams to build, ship and run any application, anywhere. (from docker.com)
I’ve been working with Docker for 3 years now and seen some cases where an image has to perform some steps before booting the application(s). It’s usual to see that done with a bash script that doesn’t launch the application preceded by an exec command. Let me explain:
– Create a start bash script that check if the file /foo exists, print a message about it and simulates an application with netcat:
#!/bin/sh
if [[ -f /foo ]]
then
echo 'File found'
else
echo 'File not found!'
fi
nc -l 4000 -k
– Create a Dockerfile that will add the start script and launch it:
FROM alpine ADD start /start RUN chmod +x /start CMD ./start
– Build, run and test it:
$ docker build -t test-pid .
$ docker run -it -d --name t-pid test-pid
# Now let's run a shell to access the container:
$ docker exec -it t-pid sh
/ # ps
PID USER TIME COMMAND
1 root 0:00 /bin/sh -c ./start
5 root 0:00 {start} /bin/sh ./start
6 root 0:00 nc -l 4000 -k
7 root 0:00 sh
11 root 0:00 ps
You’ve noticed that start script is the one that has PID 1 and that’s bad! Why is it bad? Because start script can’t leverage signals, for example: SIGTERM (docker stop) !
$ # Stop the container $ docker stop t-pid && docker rm t-pid $ # You will notice that it will take $ # 10 seconds to stop: https://github.com/docker/docker/issues/3766 $ # That's the default timeout for docker stop. $ # If the container wasn't able to deal with the SIGTERM, the force kill it.
– Change the above Dockerfile and start script to:
FROM alpine ADD start /start RUN chmod +x /start CMD exec ./start
#!/bin/sh
if [[ -f /foo ]]
then
echo 'File found'
else
echo 'File not found!'
fi
exec nc -l 4000 -k
– Build, run and test it:
$ docker build -t test-pid-ok .
$ docker run -it -d --name t-pid test-pid-ok
# Now let's run a shell to access the container:
$ docker exec -it t-pid sh
/ # ps
PID USER TIME COMMAND
1 root 0:00 nc -l 4000 -k
5 root 0:00 sh
9 root 0:00 ps
/ # # Yay!!
/ # exit
$ # Stop the container and see that it stops immediately!
$ docker stop t-pid && docker rm t-pid