author | Alberto Bertogli
<albertito@blitiri.com.ar> 2025-08-04 10:11:50 UTC |
committer | Alberto Bertogli
<albertito@blitiri.com.ar> 2025-08-04 20:18:16 UTC |
parent | d0afe102deff47b840bcdb3d385991afd821a92a |
docker/Dockerfile | +3 | -1 |
docker/entrypoint.sh | +4 | -6 |
docker/supervisord.conf | +63 | -0 |
diff --git a/docker/Dockerfile b/docker/Dockerfile index e5d97d9..ef1ebd0 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -27,7 +27,8 @@ RUN DEBIAN_FRONTEND=noninteractive \ chasquid \ dovecot-lmtpd dovecot-imapd dovecot-pop3d \ dovecot-sieve dovecot-managesieved \ - acl libcap2-bin sudo certbot && \ + supervisor \ + acl libcap2-bin certbot && \ apt-get autoremove --purge -y -q && \ apt-get autoclean -y -q && \ rm -rf /var/lib/apt/lists/* @@ -42,6 +43,7 @@ RUN setcap CAP_NET_BIND_SERVICE=+eip /usr/bin/chasquid # Copy docker-specific configurations. COPY docker/dovecot.conf /etc/dovecot/dovecot.conf COPY docker/chasquid.conf /etc/chasquid/chasquid.conf +COPY docker/supervisord.conf /etc/supervisor/supervisord.conf # Copy utility scripts. COPY docker/add-user.sh docker/entrypoint.sh / diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 5302169..dd6873f 100755 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -102,9 +102,7 @@ done >> /etc/dovecot/auto-ssl.conf sed -i '/^hostname:/d' /etc/chasquid/chasquid.conf echo "hostname: '$ONE_DOMAIN'" >> /etc/chasquid/chasquid.conf -# Start the services: dovecot in background, chasquid in foreground. -start-stop-daemon --start --quiet --pidfile /run/dovecot.pid \ - --exec /usr/sbin/dovecot -- -c /etc/dovecot/dovecot.conf - -# shellcheck disable=SC2086 -sudo -u chasquid -g chasquid /usr/bin/chasquid $CHASQUID_FLAGS +# Start the services (dovecot and chasquid, configured in supervisord.conf). +# We exec, so supervisord becomes our init, and it forwards any signals we +# receive from outside the container. +exec supervisord --nodaemon -c /etc/supervisor/supervisord.conf diff --git a/docker/supervisord.conf b/docker/supervisord.conf new file mode 100644 index 0000000..e9bf42a --- /dev/null +++ b/docker/supervisord.conf @@ -0,0 +1,63 @@ + +# We launch two daemons inside the container: chasquid and dovecot. +# The supervisord program will act as init, and forward signals to them from +# outside the container, so shutdown/restarts/etc. is handled appropriately. + +[supervisord] +user = root +# We run with --nodaemon (as per entrypoint.sh), that implicitly makes +# supervisord log to stdout _in addition_ to logfile. +# So set logfile to /dev/null to avoid duplicated entries. +logfile = /dev/null +logfile_maxbytes = 0 + +[program:dovecot] +command = /usr/sbin/dovecot -F -c /etc/dovecot/dovecot.conf +# TODO: confirm we don't need stopasgroup, or add it. +stdout_logfile = /dev/stdout +stdout_logfile_maxbytes = 0 +stderr_logfile = /dev/stderr +stderr_logfile_maxbytes = 0 +autorestart = false +priority = 201 + +[program:chasquid] +command = /usr/bin/chasquid +user = chasquid +group = chasquid +environment = USER="chasquid" +stdout_logfile = /dev/stdout +stdout_logfile_maxbytes = 0 +stderr_logfile = /dev/stderr +stderr_logfile_maxbytes = 0 +autorestart = false +# chasquid doesn't _need_ dovecot to start earlier, but it will emit a warning +# if dovecot auth it's not ready at startup. To minimize the chances of +# problems, have supervisord start it after dovecot. Still it's not guaranteed +# to be fully up by the time chasquid needs it (because it starts the +# components asynchronously), but it minimizes the problem. +priority = 202 + + +# We intentionally don't auto-restart subprocesses on unexpected crashes, and +# make supervisord exit if that happens. That way, whatever error caused it is +# propagated to the container runner and the user can monitor and decide what +# to do. +[eventlistener:exit_on_process_fatal] +# fatal: when the starting attempts fail (e.g. bad configuration). +# exited: when it fails after starting up (e.g. random crash). +# stopped: when a user wants to stop the container (e.g. requests a restart, +# or a manual stop). We don't interfere with this one because it's +# intentionally targeting a specific process. If the user wanted to stop the +# whole container, they can. +events = PROCESS_STATE_FATAL, PROCESS_STATE_EXITED +priority = 100 +command = /bin/bash -c ' + while true; do + echo "READY"; + read line; + kill -SIGTERM $PPID; + echo "RESULT 2"; + echo -n "OK"; + done; + '