From f463ef27b7f26710d492e606fa7b73732ace91fa Mon Sep 17 00:00:00 2001 From: Ian Fijolek Date: Fri, 22 Nov 2019 12:58:26 -0800 Subject: [PATCH] Update Dockerfiles to make this version runnable Should now have pairity in terms of system utilities and scripts for checking services --- Dockerfile | 20 ++++++++++-- Dockerfile.multi-stage | 22 +++++++++++-- sample-config.yml | 36 ++++++++++++++------- scripts/README.md | 5 +++ scripts/docker_check.sh | 51 +++++++++++++++++++++++++++++ scripts/docker_healthcheck.sh | 61 +++++++++++++++++++++++++++++++++++ 6 files changed, 178 insertions(+), 17 deletions(-) create mode 100644 scripts/README.md create mode 100755 scripts/docker_check.sh create mode 100755 scripts/docker_healthcheck.sh diff --git a/Dockerfile b/Dockerfile index 12c145b..a3ff139 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,22 @@ -ARG REPO=library -FROM ${REPO}/busybox:latest -WORKDIR /root/ +FROM ${REPO}/alpine:latest +RUN mkdir /app +WORKDIR /app/ +# Copy minitor in ARG ARCH=amd64 COPY ./minitor-go ./minitor +# Add common checking tools +RUN apk --no-cache add bash==4.4.19-r1 curl==7.64.0-r3 jq==1.6-r0 + +# Add minitor user for running as non-root +RUN addgroup -S minitor && adduser -S minitor -G minitor + +# Copy scripts +COPY ./scripts /app/scripts +RUN chmod -R 755 /app/scripts + +# Drop to non-root user +USER minitor + ENTRYPOINT [ "./minitor" ] diff --git a/Dockerfile.multi-stage b/Dockerfile.multi-stage index 51423ae..57a09c4 100644 --- a/Dockerfile.multi-stage +++ b/Dockerfile.multi-stage @@ -16,8 +16,26 @@ ARG VERSION=dev ENV CGO_ENABLED=0 GOOS=linux GOARCH=${ARCH} RUN go build -ldflags "-X main.version=${VERSION}" -a -installsuffix nocgo -o minitor . -FROM ${REPO}/busybox:latest -WORKDIR /root/ +FROM ${REPO}/alpine:latest +RUN mkdir /app +WORKDIR /app/ + +# Copy minitor in COPY --from=builder /app/minitor . +# Add common checking tools +RUN apk --no-cache add bash==4.4.19-r1 curl==7.64.0-r3 jq==1.6-r0 + +# Add minitor user for running as non-root +RUN addgroup -S minitor && adduser -S minitor -G minitor + +# Copy scripts +COPY ./scripts /app/scripts +RUN chmod -R 755 /app/scripts + +# Drop to non-root user +USER minitor + ENTRYPOINT [ "./minitor" ] + +# vim: set filetype=dockerfile: diff --git a/sample-config.yml b/sample-config.yml index 2582c2f..550edc0 100644 --- a/sample-config.yml +++ b/sample-config.yml @@ -1,29 +1,41 @@ -check_interval: 30 +--- +check_interval: 5 monitors: - - name: My Website - command: [ 'curl', '-s', '-o', '/dev/null', 'https://minitor.mon' ] - alert_down: [ log, mailgun_down, sms_down ] - alert_up: [ log, email_up ] - check_interval: 30 # Must be at minimum the global `check_interval` + - name: Fake Website + command: ['curl', '-s', '-o', '/dev/null', 'https://minitor.mon'] + alert_down: [log_down, mailgun_down, sms_down] + alert_up: [log_up, email_up] + check_interval: 10 # Must be at minimum the global `check_interval` alert_after: 3 - alert_every: -1 # Defaults to -1 for exponential backoff. 0 to disable repeating + alert_every: -1 # Defaults to -1 for exponential backoff. 0 to disable repeating + - name: Real Website + command: ['curl', '-s', '-o', '/dev/null', 'https://google.com'] + alert_down: [log_down, mailgun_down, sms_down] + alert_up: [log_up, email_up] + check_interval: 5 + alert_after: 3 + alert_every: -1 alerts: + log_down: + command: ["echo", "Minitor failure for {{.MonitorName}}"] + log_up: + command: ["echo", "Minitor recovery for {{.MonitorName}}"] email_up: - command: [ sendmail, "me@minitor.mon", "Recovered: {monitor_name}", "We're back!" ] + command: [sendmail, "me@minitor.mon", "Recovered: {monitor_name}", "We're back!"] mailgun_down: - command: > + command_shell: > curl -s -X POST - -F subject="Alert! {monitor_name} failed" + -F subject="Alert! {{.MonitorName}} failed" -F from="Minitor " -F to=me@minitor.mon -F text="Our monitor failed" https://api.mailgun.net/v3/minitor.mon/messages -u "api:${MAILGUN_API_KEY}" sms_down: - command: > - curl -s -X POST -F "Body=Failure! {monitor_name} has failed" + command_shell: > + curl -s -X POST -F "Body=Failure! {{.MonitorName}} has failed" -F "From=${AVAILABLE_NUMBER}" -F "To=${MY_PHONE}" "https://api.twilio.com/2010-04-01/Accounts/${ACCOUNT_SID}/Messages" -u "${ACCOUNT_SID}:${AUTH_TOKEN}" diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 0000000..328cb77 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,5 @@ +# Minitor Scripts + +A collection of some handy scripts to use with Minitor + +These are not included with the Python package, but they are included in the Docker image in `/app/scripts`. diff --git a/scripts/docker_check.sh b/scripts/docker_check.sh new file mode 100755 index 0000000..4633574 --- /dev/null +++ b/scripts/docker_check.sh @@ -0,0 +1,51 @@ +#! /bin/bash +set -e + +################# +# docker_check.sh +# +# Checks the most recent state exit code of a Docker container +################# + +# Docker host will default to a socket +# To override, export DOCKER_HOST to a new hostname +DOCKER_HOST="${DOCKER_HOST:=socket}" +container_name="$1" + +# Curls Docker either using a socket or URL +function curl_docker { + local path="$1" + if [ "$DOCKER_HOST" == "socket" ]; then + curl --unix-socket /var/run/docker.sock "http://localhost/$path" 2>/dev/null + else + curl "http://${DOCKER_HOST}/$path" 2>/dev/null + fi +} + +# Returns caintainer ID for a given container name +function get_container_id { + local container_name="$1" + curl_docker 'containers/json?all=1' \ + | jq -r ".[] | {Id, Name: .Names[]} | select(.Name == \"/${container_name}\") | .Id" +} + +# Returns container JSON +function inspect_container { + local container_id=$1 + curl_docker "containers/$container_id/json" +} + +if [ -z "$container_name" ]; then + echo "Usage: $0 container_name" + echo "Will exit with the last status code of continer with provided name" + exit 1 +fi + +container_id=$(get_container_id $container_name) +if [ -z "$container_id" ]; then + echo "ERROR: Could not find container with name: $container_name" + exit 1 +fi +exit_code=$(inspect_container "$container_id" | jq -r .State.ExitCode) + +exit "$exit_code" diff --git a/scripts/docker_healthcheck.sh b/scripts/docker_healthcheck.sh new file mode 100755 index 0000000..ec4ace4 --- /dev/null +++ b/scripts/docker_healthcheck.sh @@ -0,0 +1,61 @@ +#! /bin/bash +set -e + +################# +# docker_healthcheck.sh +# +# Returns the results of a Docker Healthcheck for a container +################# + +# Docker host will default to a socket +# To override, export DOCKER_HOST to a new hostname +DOCKER_HOST="${DOCKER_HOST:=socket}" +container_name="$1" + +# Curls Docker either using a socket or URL +function curl_docker { + local path="$1" + if [ "$DOCKER_HOST" == "socket" ]; then + curl --unix-socket /var/run/docker.sock "http://localhost/$path" 2>/dev/null + else + curl "http://${DOCKER_HOST}/$path" 2>/dev/null + fi +} + +# Returns caintainer ID for a given container name +function get_container_id { + local container_name="$1" + curl_docker 'containers/json?all=1' \ + | jq -r ".[] | {Id, Name: .Names[]} | select(.Name == \"/${container_name}\") | .Id" +} + +# Returns container JSON +function inspect_container { + local container_id="$1" + curl_docker "containers/$container_id/json" +} + +if [ -z "$container_name" ]; then + echo "Usage: $0 container_name" + echo "Will return results of healthcheck for continer with provided name" + exit 1 +fi + +container_id=$(get_container_id "$container_name") +if [ -z "$container_id" ]; then + echo "ERROR: Could not find container with name: $container_name" + exit 1 +fi +health=$(inspect_container "$container_id" | jq -r '.State.Health.Status') + +case "$health" in + null) + echo "No healthcheck results" + ;; + starting|healthy) + echo "Status: '$health'" + ;; + *) + echo "Status: '$health'" + exit 1 +esac