#!/usr/bin/env sh set -e # shellcheck disable=2039 set -o pipefail DOCKER_SOCK=${DOCKER_SOCK:-/var/run/docker.sock} UNIX_SOCK="" CURL_TIMEOUT=${CURL_TIMEOUT:-30} WEBHOOK_URL=${WEBHOOK_URL:-""} # only use unix domain socket if no TCP endpoint is defined case "${DOCKER_SOCK}" in "tcp://"*) HTTP_ENDPOINT="$(echo ${DOCKER_SOCK} | sed 's#tcp://#https://#')" CA="--cacert /certs/ca.pem" CLIENT_KEY="--key /certs/client-key.pem" CLIENT_CERT="--cert /certs/client-cert.pem" ;; *) HTTP_ENDPOINT="http://localhost" UNIX_SOCK="--unix-socket ${DOCKER_SOCK}" ;; esac AUTOHEAL_CONTAINER_LABEL=${AUTOHEAL_CONTAINER_LABEL:-autoheal} AUTOHEAL_START_PERIOD=${AUTOHEAL_START_PERIOD:-0} AUTOHEAL_INTERVAL=${AUTOHEAL_INTERVAL:-5} AUTOHEAL_DEFAULT_STOP_TIMEOUT=${AUTOHEAL_DEFAULT_STOP_TIMEOUT:-10} docker_curl() { curl --max-time "${CURL_TIMEOUT}" --no-buffer -s \ ${CA} ${CLIENT_KEY} ${CLIENT_CERT} \ ${UNIX_SOCK} \ "$@" } # shellcheck disable=2039 get_container_info() { local label_filter local url # Set container selector if [ "$AUTOHEAL_CONTAINER_LABEL" = "all" ] then label_filter="" else label_filter=",\"label\":\[\"${AUTOHEAL_CONTAINER_LABEL}=true\"\]" fi url="${HTTP_ENDPOINT}/containers/json?filters=\{\"health\":\[\"unhealthy\"\]${label_filter}\}" docker_curl "$url" } # shellcheck disable=2039 restart_container() { local container_id="$1" local timeout="$2" docker_curl -f -X POST "${HTTP_ENDPOINT}/containers/${container_id}/restart?t=${timeout}" } notify_webhook() { local text="$@" if [ -n "$WEBHOOK_URL" ] then # execute webhook requests as background process to prevent healer from blocking curl -X POST -H "Content-type: application/json" -d "$(generate_webhook_payload $text)" $WEBHOOK_URL fi } # https://towardsdatascience.com/proper-ways-to-pass-environment-variables-in-json-for-curl-post-f797d2698bf3 generate_webhook_payload() { local text="$@" cat <&2 elif [ "$CONTAINER_STATE" = "restarting" ] then echo "$DATE Container $CONTAINER_NAME (${CONTAINER_SHORT_ID}) found to be restarting - don't restart" else echo "$DATE Container $CONTAINER_NAME (${CONTAINER_SHORT_ID}) found to be unhealthy - Restarting container now with ${TIMEOUT}s timeout" if ! restart_container "$CONTAINER_ID" "$TIMEOUT" then echo "$DATE Restarting container $CONTAINER_SHORT_ID failed" >&2 notify_webhook "Container ${CONTAINER_NAME:1} (${CONTAINER_SHORT_ID}) found to be unhealthy. Failed to restart the container!" & else notify_webhook "Container ${CONTAINER_NAME:1} (${CONTAINER_SHORT_ID}) found to be unhealthy. Successfully restarted the container!" & fi fi done sleep "$AUTOHEAL_INTERVAL" & wait $! done else exec "$@" fi