Sending signals to a Docker container

We all know Docker, right? Running processes in Docker containers is nice and we can easily stop, start or restart the container with simple commands. However, you probably don’t want to “fully restart” a container all the time so sending signals to a Docker container becomes important.

 A customer application

We’re running several applications for our customers in a Docker environment. We use Docker because it’s straight-forward to spin-up new applications, especially with a Docker reverse proxy and an SSL wildcard certificate in place. Most of the applications are Python– and Django-based and it’s quite easy to run them via gunicorn. However, you need to restart or reload your Python process (i.e. gunicorn) in order to reload the configuration file or any other changes on the source code.

Restarting vs. reloading

Of course we could easily restart our Docker container by using docker restart <container>. Unfortunately, when we restart the container we’ll produce a downtime. In our case the restart of the containers takes about 30 seconds, since we run database migrations and compress static files in advance for a performance boost. So it doesn’t make any sense to restart the whole application just for a simple config or source code change. Instead of restarting a container we only want to reload the process. Fortunately, gunicorn accepts a SIGHUP for reload.

Sending signals

Sending a signal like SIGHUP to a Linux process is quite easy. We can use kill  or killall to send a signal to a process, but with Docker it gets a bit more tricky. Of course there are many ways to send signals to a Docker container. Here are some of

Option 1: Finding the PID of the container process

Since processes running inside a Docker container are also visible on the Docker host level, we can still use our well-known tools on the Docker host to send signals to the container processes. However, we need to find the right PID with:

Option 2: Executing kill inside the container

Instead of finding the PID we can also use docker exec to run kill (or killall) inside the Docker container:

Because the Docker container is spawning your process ( CMD or ENTRYPOINT) as init process with PID 1, you can always send the signal to PID 1 inside the container.

Option 3: Using docker kill

In my opinion, using the docker kill command is the most sexy way to send signals to a Docker container:

CMD exec vs. shell form

Please pay attention to the CMD statement in your Dockerfile:

Always use the exec form if you want Docker to forward signals to your (sub-)process. This is not only important for sending custom signals to a Docker container, it’s also important to properly stop (i.e. docker stop) a container.

2 Comments

  • Rich Reply

    “docker exec sv hup servicename” seems just as sexy as ‘docker kill’ 🙂

    Assuming you’re running Phusion baseimage-docker… (the my_init script doesn’t support HUP right now but seems doable, but they are using runit so we can use that). (maybe someone will modify it, it’s only 300 lines of python)

    From Runit FAQ:
    I want to send a service daemon the HUP signal, to have it re-read its configuration, or I want to send it the INT signal. How can a send signals to a service daemon?
    Answer: Use the sv program. E.g., to send the dhcp service the HUP signal, do:

    # sv hup dhcp

    http://smarden.org/runit/faq.html#signal

    • Dominique Barton Reply

      Hi Rich

      Thanks for your comment!

      Yeah sv is also working fine to send signals. However, you need to make sure that sv is installed in your container. Unfortunately, all of my images/containers haven’t installed sv, so I can’t use that one.

      Cheers
      Domi

Leave a Reply

Your email address will not be published. Required fields are marked *