mirror of
https://github.com/amir20/dozzle.git
synced 2025-12-28 16:06:40 +01:00
Adds a simple healthcheck every 2s (#1814)
* Adds a simple healthcheck every 5s * Fixes bugs for healthcheck
This commit is contained in:
@@ -34,6 +34,7 @@ COPY --from=node /build/dist ./dist
|
||||
|
||||
# Copy all other files
|
||||
COPY analytics ./analytics
|
||||
COPY healthcheck ./healthcheck
|
||||
COPY docker ./docker
|
||||
COPY web ./web
|
||||
COPY main.go ./
|
||||
@@ -56,6 +57,8 @@ ENV PATH /bin
|
||||
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
|
||||
COPY --from=upx /dozzle /dozzle
|
||||
|
||||
HEALTHCHECK --start-period=4s --interval=2s CMD [ "/dozzle", "healthcheck" ]
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
ENTRYPOINT ["/dozzle"]
|
||||
|
||||
@@ -28,6 +28,7 @@ type dockerProxy interface {
|
||||
Events(context.Context, types.EventsOptions) (<-chan events.Message, <-chan error)
|
||||
ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error)
|
||||
ContainerStats(ctx context.Context, containerID string, stream bool) (types.ContainerStats, error)
|
||||
Ping(ctx context.Context) (types.Ping, error)
|
||||
}
|
||||
|
||||
// Client is a proxy around the docker client
|
||||
@@ -38,6 +39,7 @@ type Client interface {
|
||||
Events(context.Context) (<-chan ContainerEvent, <-chan error)
|
||||
ContainerLogsBetweenDates(context.Context, string, time.Time, time.Time) (io.ReadCloser, error)
|
||||
ContainerStats(context.Context, string, chan<- ContainerStat) error
|
||||
Ping(context.Context) (types.Ping, error)
|
||||
}
|
||||
|
||||
// NewClientWithFilters creates a new instance of Client with docker filters
|
||||
@@ -241,3 +243,7 @@ func (d *dockerClient) ContainerLogsBetweenDates(ctx context.Context, id string,
|
||||
|
||||
return newLogReader(reader, containerJSON.Config.Tty), nil
|
||||
}
|
||||
|
||||
func (d *dockerClient) Ping(ctx context.Context) (types.Ping, error) {
|
||||
return d.cli.Ping(ctx)
|
||||
}
|
||||
|
||||
32
healthcheck/http.go
Normal file
32
healthcheck/http.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package healthcheck
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func HttpRequest(addr string, base string) error {
|
||||
if strings.HasPrefix(addr, ":") {
|
||||
addr = "localhost" + addr
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("http://%s%s/healthcheck", addr, base)
|
||||
log.Info("Checking health of " + url)
|
||||
resp, err := http.Get(url)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode == 200 {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
|
||||
return nil
|
||||
}
|
||||
11
main.go
11
main.go
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/alexflint/go-arg"
|
||||
"github.com/amir20/dozzle/analytics"
|
||||
"github.com/amir20/dozzle/docker"
|
||||
"github.com/amir20/dozzle/healthcheck"
|
||||
"github.com/amir20/dozzle/web"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
@@ -35,6 +36,10 @@ type args struct {
|
||||
WaitForDockerSeconds int `arg:"--wait-for-docker-seconds,env:DOZZLE_WAIT_FOR_DOCKER_SECONDS" help:"wait for docker to be available for at most this many seconds before starting the server."`
|
||||
FilterStrings []string `arg:"env:DOZZLE_FILTER,--filter,separate" help:"filters docker containers using Docker syntax."`
|
||||
Filter map[string][]string `arg:"-"`
|
||||
Healthcheck *HealthcheckCmd `arg:"subcommand:healthcheck" help:"checks if the server is running."`
|
||||
}
|
||||
|
||||
type HealthcheckCmd struct {
|
||||
}
|
||||
|
||||
func (args) Version() string {
|
||||
@@ -68,6 +73,12 @@ func main() {
|
||||
DisableLevelTruncation: true,
|
||||
})
|
||||
|
||||
if args.Healthcheck != nil {
|
||||
if err := healthcheck.HttpRequest(args.Addr, args.Base); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("Dozzle version %s", version)
|
||||
dockerClient := docker.NewClientWithFilters(args.Filter)
|
||||
for i := 1; ; i++ {
|
||||
|
||||
@@ -61,6 +61,7 @@ func createRouter(h *handler) *mux.Router {
|
||||
s.HandleFunc("/api/validateCredentials", h.validateCredentials)
|
||||
s.Handle("/logout", authorizationRequired(h.clearSession))
|
||||
s.Handle("/version", authorizationRequired(h.version))
|
||||
s.HandleFunc("/healthcheck", h.healthcheck)
|
||||
|
||||
if log.IsLevelEnabled(log.DebugLevel) {
|
||||
s.PathPrefix("/debug/pprof/").Handler(http.DefaultServeMux)
|
||||
@@ -131,3 +132,14 @@ func (h *handler) version(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Add("Content-Type", "text/html")
|
||||
fmt.Fprintf(w, "<pre>%v</pre>", h.config.Version)
|
||||
}
|
||||
|
||||
func (h *handler) healthcheck(w http.ResponseWriter, r *http.Request) {
|
||||
log.Trace("Executing healthcheck request")
|
||||
|
||||
if ping, err := h.client.Ping(r.Context()); err != nil {
|
||||
log.Error(err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
} else {
|
||||
fmt.Fprintf(w, "OK API Version %v", ping.APIVersion)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user