├── supervisor ├── roles │ ├── web │ │ ├── php.conf │ │ └── nginx.conf │ └── worker.conf ├── common.conf ├── supervisor.conf └── start.sh ├── Dockerfile ├── docker-entrypoint.sh ├── worker.php └── README.md /supervisor/roles/web/php.conf: -------------------------------------------------------------------------------- 1 | [program:php-fpm] 2 | command=php-fpm7 -F 3 | -------------------------------------------------------------------------------- /supervisor/roles/worker.conf: -------------------------------------------------------------------------------- 1 | [program:worker] 2 | command=php /worker.php 3 | -------------------------------------------------------------------------------- /supervisor/roles/web/nginx.conf: -------------------------------------------------------------------------------- 1 | [program:nginx] 2 | command=nginx -g 'daemon off;' 3 | -------------------------------------------------------------------------------- /supervisor/common.conf: -------------------------------------------------------------------------------- 1 | # Options common to all processes 2 | 3 | # Ensure all logs go to stdout/stderr 4 | stdout_logfile=/dev/stdout 5 | stdout_logfile_maxbytes=0 6 | stderr_logfile=/dev/stderr 7 | stderr_logfile_maxbytes=0 8 | 9 | # Fail out if we cant start processes 10 | startsecs=3 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.15 2 | 3 | RUN apk add --no-cache php-fpm php-cli nginx supervisor 4 | RUN adduser -D supervisor-user 5 | 6 | COPY supervisor /etc/supervisor 7 | COPY worker.php /worker.php 8 | COPY docker-entrypoint.sh /docker-entrypoint.sh 9 | 10 | 11 | CMD ["/docker-entrypoint.sh"] 12 | -------------------------------------------------------------------------------- /docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Make sure that a role is configured 4 | if [ -z "$ROLES" ]; then 5 | echo "No role configured!" 6 | exit 1 7 | 8 | # We could also set a default role here... 9 | # ROLES=web 10 | fi 11 | 12 | # Set up the supervisor and start it... 13 | /etc/supervisor/start.sh 14 | -------------------------------------------------------------------------------- /worker.php: -------------------------------------------------------------------------------- 1 | > $CONFIG_FILE 11 | if [ -f /etc/supervisor/common.conf ]; then 12 | cat /etc/supervisor/common.conf >> $CONFIG_FILE 13 | fi 14 | } 15 | 16 | # Iterate over the comma seperated list of roles, and add config as appropriate 17 | for ROLE in $(echo "$ROLES" | tr "," "\n"); do 18 | if [ -d /etc/supervisor/roles/$ROLE ]; then 19 | for ROLE_PROCESS in $(ls /etc/supervisor/roles/$ROLE/*.conf); do 20 | add_config $ROLE_PROCESS 21 | done 22 | elif [ -f /etc/supervisor/roles/$ROLE.conf ]; then 23 | add_config /etc/supervisor/roles/$ROLE.conf 24 | fi 25 | done 26 | 27 | # Start supervisor 28 | supervisord -c $CONFIG_FILE 29 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # supervisord-config 2 | My modular [`supervisord`](http://supervisord.org/) configuration for containers, as outlined in [this blog post](https://leigholiver.com/posts/tips-for-supervisord-config/) 3 | 4 | Key features: 5 | - Minimise duplication 6 | - Dynamically set which process groups ("roles") are running 7 | - Ensure that supervisor quits when a process becomes `FATAL` 8 | 9 | ## Usage 10 | - Download the `supervisor/` directory of this repository 11 | - Modify `supervisor.conf`, `common.conf` and the role definitions as required 12 | - Copy the directory into `/etc/supervisor` of your container image 13 | - Configure your container to run `/etc/supervisor/start.sh` on startup 14 | - This can either be set as the entrypoint, or called by your entrypoint script 15 | - When starting a container, set the `ROLES` environment variable to choose which roles to run 16 | 17 | There are three places for configuration: 18 | - `supervisor.conf` is the base supervisor configuration file 19 | - `common.conf` contains configuration lines which are applied to all processes in every role 20 | - The `roles/` directory contains the role definitions 21 | 22 | A role definiton is a [supervisor process configuration](http://supervisord.org/subprocess.html#examples-of-program-configurations) as either: 23 | - A file named `.conf`, containing a single process 24 | - A directory named ``, containing a `*.conf` file for each process to run for the role 25 | - This structure allows the `common.conf` options to be applied to each process properly 26 | 27 | ### Using the example 28 | The example in this repo can be run as a Docker image. 29 | To build the image run `docker build -t supervisord-config .` 30 | 31 | The [entrypoint script](docker-entrypoint.sh) is configured to fail if no role is specified: 32 | - `docker run -it supervisord-config` 33 | 34 | By specifying the `web` role, `nginx` and `php` will be started: 35 | - `docker run -it -e ROLES=web supervisord-config` 36 | 37 | And by specifying the `worker` role, the `worker.php` script will be started. 38 | This script will randomly fail, and supervisor will restart it as needed. 39 | - `docker run -it -e ROLES=worker supervisord-config` 40 | 41 | Both roles can be set to run in the same container: 42 | - `docker run -it -e ROLES=web,worker supervisord-config` 43 | 44 | The worker script can also be configured to fail to start, which will show `nginx` and `php` quitting and the container exiting. 45 | - `docker run -it -e ROLES=web,worker -e FAIL=true supervisord-config` 46 | --------------------------------------------------------------------------------