Docker-nginx: Use `STOPSIGNAL SIGQUIT` instead of `SIGTERM`

Created on 15 Nov 2019  路  6Comments  路  Source: nginxinc/docker-nginx

Docker (and, therefore, Kubernetes) send SIGTERM as the default signal to stop containers. Docker will then wait 10 seconds before sending SIGKILL, Kubernetes will wait 30 seconds. They expect containers to exit gracefully within this grace period:

When you issue a docker stop command Docker will first ask nicely for the process to stop and if it doesn't comply within 10 seconds it will forcibly kill it. If you've ever issued a docker stop and had to wait 10 seconds for the command to return you've seen this in action

From: https://www.ctl.io/developers/blog/post/gracefully-stopping-docker-containers/

It鈥檚 important that your application handle termination gracefully so that there is minimal impact on the end user and the time-to-recovery is as fast as possible!

In practice, this means your application needs to handle the SIGTERM message and begin shutting down when it receives it. This means saving all data that needs to be saved, closing down network connections, finishing any work that is left, and other similar tasks.

From: https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-terminating-with-grace

However, this is not what nginx does:

TERM, INT fast shutdown
QUIT graceful shutdown

From: http://nginx.org/en/docs/control.html

The Dockerfiles in this project use STOPSIGNAL SIGTERM (which actually isn't necessary since this is the default).

What this means in practice is that when Docker or Kubernetes decide to stop a container, nginx will die immediately, closing any connections straight away:

$ curl localhost
curl: (52) Empty reply from server

It would be much healthier, and comply with the ethos of both Docker and Kubernetes if instead the nginx image made an effort to close all connections before shutting down. This can be achieved nicely with:

STOPSIGNAL SIGQUIT

I've verified this behaviour locally with this Dockerfile.

Most helpful comment

Now that https://trac.nginx.org/nginx/ticket/753 is fixed, we can try moving to SIGQUIT.

All 6 comments

We discussed that in https://github.com/nginxinc/docker-nginx/issues/167 - can you check if dangling sockets are still an issue with your approach?

Okay, interesting. We don't use any unix sockets, so it's not an issue for us.

But more generally, this SIGTERM behaviour seems definitely undesirable to me. Given how prevalent nginx is, and how prevalent its usage in e.g. Kubernetes is, the default docker image should really be able to shut down gracefully without causing broken connections.

It seems to me that the correct signal to send is SIGQUIT and the issue with unix signals is a bug that should be fixed. Is the nginx project aware of the issue?

(Either that or nginx should change its behaviour on SIGTERM to be more graceful)

nginx is aware of the issue, see https://trac.nginx.org/nginx/ticket/753 for more details.

Now that https://trac.nginx.org/nginx/ticket/753 is fixed, we can try moving to SIGQUIT.

The fix was released in 1.19.1. Can this be implemented then?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

luckymark picture luckymark  路  4Comments

HeyRobb picture HeyRobb  路  5Comments

M-SIGMA picture M-SIGMA  路  3Comments

ralphsmith80 picture ralphsmith80  路  5Comments

hasancansaral picture hasancansaral  路  6Comments