nginx / unit

NGINX Unit - universal web app server - a lightweight and versatile open source server that simplifies the application stack by natively executing application code across eight different programming language runtimes.
https://unit.nginx.org
Apache License 2.0
5.25k stars 320 forks source link

Docker: pre-populating state #1274

Open lcrilly opened 1 month ago

lcrilly commented 1 month ago

Pre-copying the contents of the state directory is not a safe solution because only the Unit daemon is expected to create those files. It requires the same version of Unit to create and consume the state files.

The proposed solution is to use the unitd binary to pre-populate the state files. In this mode, unitd does not daemonize, but instead passes the supplied configuration through the normal configuration loading process so that the state files are written. It then exits, so that Unit can then be started as a daemon and will serve traffic as usual. During configuration, listeners and applications are not started, so that any traffic reaching the server will not be processed.

$ unitd --control-uri /certificates/bundle < bundle.pem
{
    "success": "Reconfiguration done"
}
$ cat conf.json | unitd --control-uri /config
{
    "success": "Reconfiguration done"
}

The --control-uri option specifies the URI to the control API and reads the configuration data from stdin.

The intention is for unitd not to start - simply to use Unit’s configuration parsing code to create a known-good state directory. Multiple iterations are required to load certificates, JavaScript modules, and JSON config. The current entrypoint.sh does this while unitd is running, then kills it. All the while, requests might arrive on “dead end” listeners.

With this change, the standard entrypoint script would be much simpler, and no longer depend on curl(1) to be part of the container.

Container startup times can be further improved by running unitd --control-uri as RUN steps in a custom Dockerfile so that the state-directory is pre-populated before the container starts. In this case the entrypoint script will skip the configuration step.