diff --git a/cmd/root.go b/cmd/root.go index 49568b8..90c338c 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -140,6 +140,16 @@ func Run(c *cobra.Command, names []string) { enableMetricsAPI, _ := c.PersistentFlags().GetBool("http-api-metrics") unblockHTTPAPI, _ := c.PersistentFlags().GetBool("http-api-periodic-polls") apiToken, _ := c.PersistentFlags().GetString("http-api-token") + healthCheck, _ := c.PersistentFlags().GetBool("health-check") + + if healthCheck { + // health check should not have pid 1 + if os.Getpid() == 1 { + time.Sleep(1 * time.Second) + log.Fatal("The health check flag should never be passed to the main watchtower container process") + } + os.Exit(0) + } if rollingRestart && monitorOnly { log.Fatal("Rolling restarts is not compatible with the global monitor only flag") diff --git a/dockerfiles/Dockerfile b/dockerfiles/Dockerfile index 26ffb44..b6f8676 100644 --- a/dockerfiles/Dockerfile +++ b/dockerfiles/Dockerfile @@ -17,4 +17,7 @@ COPY --from=alpine \ EXPOSE 8080 COPY watchtower / + +HEALTHCHECK CMD [ "/watchtower", "--health-check"] + ENTRYPOINT ["/watchtower"] diff --git a/dockerfiles/Dockerfile.dev-self-contained b/dockerfiles/Dockerfile.dev-self-contained index 79dbe39..7126459 100644 --- a/dockerfiles/Dockerfile.dev-self-contained +++ b/dockerfiles/Dockerfile.dev-self-contained @@ -35,4 +35,6 @@ COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certifi COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo COPY --from=builder /watchtower/watchtower /watchtower +HEALTHCHECK CMD [ "/watchtower", "--health-check"] + ENTRYPOINT ["/watchtower"] diff --git a/dockerfiles/Dockerfile.self-contained b/dockerfiles/Dockerfile.self-contained index 303fc53..04a6047 100644 --- a/dockerfiles/Dockerfile.self-contained +++ b/dockerfiles/Dockerfile.self-contained @@ -35,4 +35,6 @@ COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certifi COPY --from=builder /usr/share/zoneinfo /usr/share/zoneinfo COPY --from=builder /go/watchtower/watchtower /watchtower +HEALTHCHECK CMD [ "/watchtower", "--health-check"] + ENTRYPOINT ["/watchtower"] diff --git a/docs/arguments.md b/docs/arguments.md index 7563b70..97a2a93 100644 --- a/docs/arguments.md +++ b/docs/arguments.md @@ -419,6 +419,17 @@ Environment Variable: WATCHTOWER_WARN_ON_HEAD_FAILURE Default: auto ``` +## Health check + +Returns a success exit code to enable usage with docker `HEALTHCHECK`. This check is naive and only returns checks whether there is another process running inside the container, as it is the only known form of failure state for watchtowers container. + +!!! note "Only for HEALTHCHECK use" + Never put this on the main container executable command line as it is only meant to be run from docker HEALTHCHECK. + +```text + Argument: --health-check +``` + ## Programatic Output (porcelain) Writes the session results to STDOUT using a stable, machine-readable format (indicated by the argument VERSION). diff --git a/internal/flags/flags.go b/internal/flags/flags.go index c0db557..819f6f3 100644 --- a/internal/flags/flags.go +++ b/internal/flags/flags.go @@ -193,9 +193,15 @@ func RegisterSystemFlags(rootCmd *cobra.Command) { "The maximum log level that will be written to STDERR. Possible values: panic, fatal, error, warn, info, debug or trace") flags.BoolP( + "health-check", + "", + false, + "Do health check and exit") + + flags.BoolP( "label-take-precedence", "", - viper.GetBool("WATCHTOWER_LABEL_TAKE_PRECEDENCE"), + envBool("WATCHTOWER_LABEL_TAKE_PRECEDENCE"), "Label applied to containers take precedence over arguments") }