stevearc / pypicloud-docker

Docker image for pypicloud
MIT License
86 stars 34 forks source link

Configuration auto-reloading #29

Closed oleobal closed 4 years ago

oleobal commented 4 years ago

First, apologies, as this isn't so much an issue as a general question. I couldn't find a better place for it.

I'm looking for a way to load configuration changes without re-starting the entire image. I'm unfortunately not too familiar with the ways of python web frameworks.

I notice pserve has an option for monitoring changes in and reloading the config file: is that strictly for development purposes or could it be used in production?

Alternatively, would there be a way to signal that the configuration file has changed? (kind of like how nginx -s reload has the background process hot reload)

Thanks for the help!

stevearc commented 4 years ago

The docker container uses uWSGI to serve pypicloud. They've written an entire treatise on graceful reloading that is well worth a read. The most straightforward way to do this is to send a SIGHUP to uWSGI.

The simplest way to do this with docker:

docker kill --signal=SIGHUP <container>

Unfortunately, nothing is ever as easy as you want it to be. This won't work on the default pypicloud-docker image because it's built on top of baseimage and they don't run the process directly. The docker kill command will send the signal to the root process, but baseimage is actually running its own master process and starting the uWSGI process as a child, so it won't receive the SIGHUP.

This does work on the alpine version of pypicloud, but there is one additional complication. If you use the default command recommended by the README:

docker run -p 8080:8080 -v $(readlink -f docker.ini):/etc/pypicloud/config.ini:ro stevearc/pypicloud:1.0.14-py3-alpine

Then sending it the SIGHUP will cause it to reload and not be able to find the file. This is because we passed a specific file in the mount command. We have to instead create a directory for our config file, name our config file "config.ini", and mount that directory:

docker run -p 8080:8080 -v $(readlink -f configdir):/etc/pypicloud:ro stevearc/pypicloud:1.0.14-py3-alpine

Hopefully this will work for you, and if not, at least give you some ideas on where to look.

oleobal commented 4 years ago

I gather baseimage's custom init system has no special provision for handling either signals or something similar to systemd's ExecReload. I suppose it would be feasible to exec into the container and call kill onto the right process there, but I'd rather keep things streamlined.

If someone googles this, as I happen to be running all of this in Kubernetes, I'll treat conf updates as software updates and force a rollout (kubectl rollout restart) when they happen. It has to be done "by hand" and involves much unnecessary restarts, but I do get a protection against configuration errors from the rollout as a bonus.

I think I have a much better overview of the situation now, thank you very much for all the help.