diff --git a/.drone.yml b/.drone.yml index c11aeff..177909b 100644 --- a/.drone.yml +++ b/.drone.yml @@ -88,4 +88,12 @@ steps: context: gotify dockerfile: gotify/Dockerfile repo: green.wadza.fr:5000/gotify + tags: latest + +- name: liman + image: plugins/docker + settings: + context: liman + dockerfile: liman/Dockerfile + repo: green.wadza.fr:5000/liman tags: latest \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 6a3bf10..b1215ab 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -56,4 +56,9 @@ services: gotify: image: local/gotify build: - context: gotify \ No newline at end of file + context: gotify + + liman: + image: local/liman + build: + context: liman \ No newline at end of file diff --git a/drone/Dockerfile.runner.docker.1 b/drone/Dockerfile.runner.docker.1 index 5ba8007..c952e1f 100644 --- a/drone/Dockerfile.runner.docker.1 +++ b/drone/Dockerfile.runner.docker.1 @@ -4,4 +4,4 @@ RUN set -ex \ && apk add --no-cache curl HEALTHCHECK --interval=5m --timeout=3s \ - CMD curl -f $(hostname -i || echo '127.0.0.1')/__heartbeat__ || exit 1 \ No newline at end of file + CMD curl -f $(hostname -i || echo '127.0.0.1'):3000/healthz || exit 1 \ No newline at end of file diff --git a/liman/Dockerfile b/liman/Dockerfile new file mode 100644 index 0000000..543673b --- /dev/null +++ b/liman/Dockerfile @@ -0,0 +1,7 @@ +FROM salihciftci/liman + +COPY ./healthcheck.js / + +RUN chmod a+x /healthcheck.js + +HEALTHCHECK CMD node /healthcheck.js diff --git a/liman/healthcheck.js b/liman/healthcheck.js new file mode 100644 index 0000000..1fac5d7 --- /dev/null +++ b/liman/healthcheck.js @@ -0,0 +1,25 @@ +var http = require("http"); + +var options = { + host: "localhost", + port: "5000", + path: "/login", + timeout: 2000 +}; + +var request = http.request(options, (res) => { + if (res.statusCode == 200) { + process.exit(0); + } + else { + console.log(`STATUS: ${res.statusCode}`); + process.exit(1); + } +}); + +request.on('error', function (err) { + console.log('ERROR', err); + process.exit(1); +}); + +request.end(); \ No newline at end of file diff --git a/nextcloud/Dockerfile b/nextcloud/Dockerfile index 506a672..91bc79c 100644 --- a/nextcloud/Dockerfile +++ b/nextcloud/Dockerfile @@ -2,7 +2,7 @@ FROM nextcloud:production-fpm RUN mkdir -p /usr/share/man/man1 \ && apt-get update && apt-get install -y \ - supervisor \ + supervisor libfcgi-bin \ && rm -rf /var/lib/apt/lists/* \ && mkdir /var/log/supervisord /var/run/supervisord @@ -10,7 +10,13 @@ COPY supervisord.conf /etc/supervisor/supervisord.conf ENV NEXTCLOUD_UPDATE=1 -HEALTHCHECK --interval=5m --timeout=5s \ - CMD curl -f $(hostname -i || echo '127.0.0.1')/status.php || exit 1 +# Enable php fpm status page +RUN set -xe && echo "pm.status_path = /status" >> /usr/local/etc/php-fpm.d/zz-docker.conf + +COPY ./php-fpm-healthcheck /usr/local/bin/ + +RUN chmod a+x /usr/local/bin/php-fpm-healthcheck + +HEALTHCHECK CMD php-fpm-healthcheck --listen-queue=10 CMD ["/usr/bin/supervisord"] diff --git a/nextcloud/php-fpm-healthcheck b/nextcloud/php-fpm-healthcheck new file mode 100755 index 0000000..aca609f --- /dev/null +++ b/nextcloud/php-fpm-healthcheck @@ -0,0 +1,138 @@ +#!/bin/sh +# vim: set filetype=sh : + +# Author: https://github.com/renatomefi +# The original code lives in https://github.com/renatomefi/php-fpm-healthcheck +# +# A POSIX compliant shell script to healthcheck PHP fpm status, can be used only for pinging the status page +# or check for specific metrics +# +# i.e.: ./php-fpm-healthcheck --verbose --active-processes=6 +# The script will fail in case the 'active processes' is bigger than 6. +# +# You can combine multiple options as well, the first one to fail will fail the healthcheck +# i.e.: ./php-fpm-healthcheck --listen-queue-len=10 --active-processes=6 +# +# Ping mode (exit 0 if php-fpm returned data): ./php-fpm-healthcheck +# +# Ping mode with data (outputs php-fpm status text): ./php-fpm-healthcheck -v +# +# Exit status codes: +# 2,9,111 - Couldn't connect to PHP fpm, is it running? +# 8 - Couldn't reach PHP fpm status page, have you configured it with `pm.status_path = /status`? +# 1 - A healthcheck condition has failed +# 3 - Invalid option given +# 4 - One or more required softwares are missing +# +# Available options: +# -v|--verbose +# +# Metric options, fails in case the CURRENT VALUE is bigger than the GIVEN VALUE +# --accepted-conn=n +# --listen-queue=n +# --max-listen-queue=n +# --idle-processes=n +# --active-processes=n +# --total-processes=n +# --max-active-processes=n +# --max-children-reached=n +# --slow-requests=n +# + +set -eu + +OPTIND=1 # Reset getopt in case it has been used previously in the shell + +# FastCGI variables +export REQUEST_METHOD="GET" +export SCRIPT_NAME="/status" +export SCRIPT_FILENAME="/status" +FCGI_CONNECT_DEFAULT="localhost:9000" + +# Required software +FCGI_CMD_PATH=$(command -v cgi-fcgi) || { >&2 echo "Make sure fcgi is installed (i.e. apk add --no-cache fcgi). Aborting."; exit 4; } +command -v sed 1> /dev/null || { >&2 echo "Make sure sed is installed (i.e. apk add --no-cache busybox). Aborting."; exit 4; } +command -v tail 1> /dev/null || { >&2 echo "Make sure tail is installed (i.e. apk add --no-cache busybox). Aborting."; exit 4; } +command -v grep 1> /dev/null || { >&2 echo "Make sure grep is installed (i.e. apk add --no-cache grep). Aborting."; exit 4; } + +# Get status from fastcgi connection +# $1 - cgi-fcgi connect argument +get_fpm_status() { + if test "$VERBOSE" = 1; then printf "Trying to connect to php-fpm via: %s\\n" "$1"; fi; + + # Since I cannot use pipefail I'll just split these in two commands + FPM_STATUS=$(env -i REQUEST_METHOD="$REQUEST_METHOD" SCRIPT_NAME="$SCRIPT_NAME" SCRIPT_FILENAME="$SCRIPT_FILENAME" "$FCGI_CMD_PATH" -bind -connect "$1" 2> /dev/null) + FPM_STATUS=$(echo "$FPM_STATUS" | tail +5) + + if test "$VERBOSE" = 1; then printf "php-fpm status output:\\n%s\\n" "$FPM_STATUS"; fi; + + if test "$FPM_STATUS" = "File not found."; then + >&2 printf "php-fpm status page non reachable\\n"; + exit 8; + fi; +} + +# $1 - fpm option +# $2 - expected value threshold +check_fpm_health_by() { + OPTION=$(echo "$1" | sed 's/--//g; s/-/ /g;') + VALUE_EXPECTED="$2"; + VALUE_ACTUAL=$(echo "$FPM_STATUS" | grep "^$OPTION:" | cut -d: -f2 | sed 's/ //g') + + if test "$VERBOSE" = 1; then printf "'%s' value '%s' and expected is less than '%s'\\n" "$OPTION" "$VALUE_ACTUAL" "$VALUE_EXPECTED"; fi; + + if test "$VALUE_ACTUAL" -gt "$VALUE_EXPECTED"; then + >&2 printf "'%s' value '%s' is greater than expected '%s'\\n" "$OPTION" "$VALUE_ACTUAL" "$VALUE_EXPECTED"; + exit 1; + fi; +} + +PARAM_AMOUNT=0 + +# $1 - fpm option +# $2 - expected value threshold +check_later() { + # The POSIX sh way to check if it's an integer, also the output is supressed since it's polution + if ! test "$2" -eq "$2" 2> /dev/null; then + >&2 printf "'%s' option value must be an integer, '%s' given\\n" "$1" "$2"; exit 3; + fi + + PARAM_AMOUNT=$(( PARAM_AMOUNT + 1 )) + + eval "PARAM_TO_CHECK$PARAM_AMOUNT=$1" + eval "VALUE_TO_CHECK$PARAM_AMOUNT=$2" +} + +# From the PARAM_TO_CHECK/VALUE_TO_CHECK magic variables, do all the checks +check_fpm_health() { + j=1 + while [ $j -le $PARAM_AMOUNT ]; do + eval "CURRENT_PARAM=\$PARAM_TO_CHECK$j" + eval "CURRENT_VALUE=\$VALUE_TO_CHECK$j" + check_fpm_health_by "$CURRENT_PARAM" "$CURRENT_VALUE" + j=$(( j + 1 )) + done +} + +if ! GETOPT=$(getopt -o v --long verbose,accepted-conn:,listen-queue:,max-listen-queue:,listen-queue-len:,idle-processes:,active-processes:,total-processes:,max-active-processes:,max-children-reached:,slow-requests: -n 'php-fpm-healthcheck' -- "$@"); then + >&2 echo "Invalid options, terminating." ; exit 3 +fi; + +eval set -- "$GETOPT" + +FCGI_CONNECT="${FCGI_CONNECT:-$FCGI_CONNECT_DEFAULT}" + +VERBOSE=0 + +while test "$1"; do + case "$1" in + -v|--verbose ) VERBOSE=1; shift ;; + --) shift ; break ;; + * ) check_later "$1" "$2"; shift 2 ;; + esac +done + +FPM_STATUS=false + +get_fpm_status "$FCGI_CONNECT" +check_fpm_health