From e7e1b3c8134b3274125b1dcd18883511a0ea0a8d Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Sat, 10 Jun 2023 10:18:46 +0200 Subject: [PATCH 1/2] entrypoint: Launch our entrypoint via tini Even single process containers (which this one is actually not) should have an init system. However most init systems are too big and complex for containerization purposes. [Dumb-init][0] (and tini init) address this problem _specifically_ for Docker containers. See the [dumb-init][0] documentation for more details. [0]: https://github.com/Yelp/dumb-init Signed-off-by: Olliver Schinagl --- Dockerfile-alpine-slim.template | 3 +++ Dockerfile-alpine.template | 5 ++++- Dockerfile-debian.template | 2 ++ entrypoint/docker-entrypoint.sh | 2 +- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Dockerfile-alpine-slim.template b/Dockerfile-alpine-slim.template index 65be8916..f6803565 100644 --- a/Dockerfile-alpine-slim.template +++ b/Dockerfile-alpine-slim.template @@ -99,6 +99,9 @@ RUN set -x \ # forward request and error logs to docker log collector && ln -sf /dev/stdout /var/log/nginx/access.log \ && ln -sf /dev/stderr /var/log/nginx/error.log \ +# Ensure we can run our entrypoint and make it debian compatible + && apk add --no-cache tini \ + && ln -s /sbin/tini /usr/bin/tini \ # create a docker-entrypoint.d directory && mkdir /docker-entrypoint.d diff --git a/Dockerfile-alpine.template b/Dockerfile-alpine.template index 8c464dfd..dede8171 100644 --- a/Dockerfile-alpine.template +++ b/Dockerfile-alpine.template @@ -75,4 +75,7 @@ RUN set -x \ && if [ -n "/etc/apk/keys/abuild-key.rsa.pub" ]; then rm -f /etc/apk/keys/abuild-key.rsa.pub; fi \ && if [ -n "/etc/apk/keys/nginx_signing.rsa.pub" ]; then rm -f /etc/apk/keys/nginx_signing.rsa.pub; fi \ # Bring in curl and ca-certificates to make registering on DNS SD easier - && apk add --no-cache curl ca-certificates + && apk add --no-cache curl ca-certificates \ +# Ensure we can run our entrypoint and do it compatible with alpine + && apk add --no-cache tini \ + && ln -s /sbin/tini /usr/bin/tini diff --git a/Dockerfile-debian.template b/Dockerfile-debian.template index 404094f1..e323235f 100644 --- a/Dockerfile-debian.template +++ b/Dockerfile-debian.template @@ -82,6 +82,8 @@ RUN set -x \ $nginxPackages \ gettext-base \ curl \ + tini \ + && ln -s /usr/bin/tini /sbin/tini \ && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list \ \ # if we have leftovers from building, let's purge them (including extra, unnecessary build deps) diff --git a/entrypoint/docker-entrypoint.sh b/entrypoint/docker-entrypoint.sh index e201fe60..312558c1 100755 --- a/entrypoint/docker-entrypoint.sh +++ b/entrypoint/docker-entrypoint.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/sbin/init /bin/sh # vim:sw=4:ts=4:et set -e From 506fd0f3e3670557be2ecb41424a2702fd7bd01e Mon Sep 17 00:00:00 2001 From: Olliver Schinagl Date: Sun, 4 Jun 2023 16:59:20 +0200 Subject: [PATCH 2/2] entrypoint: Monitor config dir for changes We see a lot of crudges and hacks to notify nginx or the nginx container informing it it needs to restart. While there certainly cases that require manual control, for the most, this could be easily automated. With inotify, we can recursively monitor /etc/nginx (or any directory per config) for changes (currently, not monitoring for for access time changes, e.g. reads or `touch` (not creating new files) events). On an event, we sleep first for (configurable) seconds, the default is 10, so that multiple updates don't cause multiple restarts. E.g. copying 10 certificates into /etc/nginx/certs, won't trigger 10 reloads. The monitor will run indefinably, but to ensure there is 'some' way to exit it, is to remove the pid file (configurable location) and triggering a `/etc/nginx` change (`touch '/etc/nginx/exit'` for example to create a file. It's not perfect, but probably will never be used anyway. The current configuration won't change existing behavior, it needs to be explicitly enabled. Signed-off-by: Olliver Schinagl --- Dockerfile-alpine-slim.template | 2 ++ Dockerfile-alpine.template | 2 ++ Dockerfile-debian.template | 1 + entrypoint/99-monitor-config-changes.sh | 44 +++++++++++++++++++++++++ 4 files changed, 49 insertions(+) create mode 100755 entrypoint/99-monitor-config-changes.sh diff --git a/Dockerfile-alpine-slim.template b/Dockerfile-alpine-slim.template index f6803565..580dbd14 100644 --- a/Dockerfile-alpine-slim.template +++ b/Dockerfile-alpine-slim.template @@ -102,6 +102,8 @@ RUN set -x \ # Ensure we can run our entrypoint and make it debian compatible && apk add --no-cache tini \ && ln -s /sbin/tini /usr/bin/tini \ +# Add support for manually monitoring files to trigger server reloads + && apk add --no-cache inotify-tools \ # create a docker-entrypoint.d directory && mkdir /docker-entrypoint.d diff --git a/Dockerfile-alpine.template b/Dockerfile-alpine.template index dede8171..ac0e81d5 100644 --- a/Dockerfile-alpine.template +++ b/Dockerfile-alpine.template @@ -79,3 +79,5 @@ RUN set -x \ # Ensure we can run our entrypoint and do it compatible with alpine && apk add --no-cache tini \ && ln -s /sbin/tini /usr/bin/tini +# Add support for manually monitoring files to trigger server reloads + && apk add --no-cache inotify-tools diff --git a/Dockerfile-debian.template b/Dockerfile-debian.template index e323235f..dd1cd9bd 100644 --- a/Dockerfile-debian.template +++ b/Dockerfile-debian.template @@ -83,6 +83,7 @@ RUN set -x \ gettext-base \ curl \ tini \ + inotify-tools \ && ln -s /usr/bin/tini /sbin/tini \ && apt-get remove --purge --auto-remove -y && rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/nginx.list \ \ diff --git a/entrypoint/99-monitor-config-changes.sh b/entrypoint/99-monitor-config-changes.sh new file mode 100755 index 00000000..c2ed02b3 --- /dev/null +++ b/entrypoint/99-monitor-config-changes.sh @@ -0,0 +1,44 @@ +#!/bin/sh +# vim:sw=2:ts=2:sts=2:et + +set -eu +if [ -n "${DEBUG_TRACE_SH:-}" ] && \ + [ "${DEBUG_TRACE_SH:-}" != "${DEBUG_TRACE_SH#*"$(basename "${0}")"*}" ] || \ + [ "${DEBUG_TRACE_SH:-}" = 'all' ]; then + set -x +fi + +LC_ALL=C + +if [ -e "${NGINX_ENTRYPOINT_MONITOR_PID:=/run/nginx_monitor.pid}" ] || + [ -z "${NGINX_ENTRYPOINT_MONITOR_CONFIG+monitor}" ] || \ + ! command -v inotifywait; then + exit 0 +fi + +echo "Monitoring for changes in '${NGINX_ENTRYPOINT_MONITOR_CONFIG:=/etc/nginx}'" +while true; do + inotifywait \ + --recursive \ + --event 'create' \ + --event 'delete' \ + --event 'modify' \ + --event 'move' \ + "${NGINX_ENTRYPOINT_MONITOR_CONFIG}" + + sleep "${NGINX_ENTRYPOINT_MONITOR_DELAY:-10s}" + + if [ ! -e "${NGINX_ENTRYPOINT_MONITOR_PID}" ]; then + logger -s -t 'nginx' -p 'local0.3' 'Monitor failure or exit requested' + break + fi + + if nginx -t; then + nginx -s + else + logger -s -t 'nginx' -p 'local0.3' 'Refusing to reload config, config error' + fi +done & +echo "${!}" > "${NGINX_ENTRYPOINT_MONITOR_PID}" + +exit 0