feat: add healthcheck support for container image

- Add 'health' subcommand to ackify binary for Docker HEALTHCHECK
- Add HEALTHCHECK directive to Dockerfile
- Add healthcheck configuration to all compose files
- Supports custom port via ACKIFY_LISTEN_ADDR

Closes #21
This commit is contained in:
Benjamin
2026-02-05 20:50:36 +01:00
parent 635f8c7021
commit f43c3c53a9
5 changed files with 67 additions and 1 deletions

View File

@@ -87,4 +87,7 @@ ENV ACKIFY_LOCALES_DIR=/app/locales
EXPOSE 8080
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD ["/app/ackify", "health"]
ENTRYPOINT ["/app/ackify"]

View File

@@ -4,6 +4,7 @@ import (
"context"
"embed"
"errors"
"fmt"
"log"
"net/http"
"os"
@@ -29,6 +30,11 @@ var (
var frontend embed.FS
func main() {
// Handle health check subcommand for Docker HEALTHCHECK
if len(os.Args) > 1 && os.Args[1] == "health" {
os.Exit(runHealthCheck())
}
ctx := context.Background()
cfg, err := config.Load()
@@ -86,3 +92,42 @@ func main() {
log.Println("Community Edition server exited")
}
// runHealthCheck performs a health check against the local server.
// Returns 0 on success, 1 on failure.
func runHealthCheck() int {
addr := os.Getenv("ACKIFY_LISTEN_ADDR")
if addr == "" {
addr = ":8080"
}
// Build health URL (handle both ":8080" and "0.0.0.0:8080" formats)
host := "localhost"
port := addr
if addr[0] != ':' {
// Format is "host:port", extract port
for i := len(addr) - 1; i >= 0; i-- {
if addr[i] == ':' {
port = addr[i:]
break
}
}
}
url := fmt.Sprintf("http://%s%s/api/v1/health", host, port)
client := &http.Client{Timeout: 5 * time.Second}
resp, err := client.Get(url)
if err != nil {
fmt.Fprintf(os.Stderr, "Health check failed: %v\n", err)
return 1
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
fmt.Fprintf(os.Stderr, "Health check failed: status %d\n", resp.StatusCode)
return 1
}
return 0
}

View File

@@ -65,6 +65,12 @@ services:
condition: service_healthy
ports:
- "8080:8080"
healthcheck:
test: ["CMD", "/app/ackify", "health"]
interval: 30s
timeout: 5s
start_period: 10s
retries: 3
ackify-db:
image: postgres:16-alpine

View File

@@ -68,6 +68,12 @@ services:
- internal
ports:
- "8080:8080"
healthcheck:
test: ["CMD", "/app/ackify", "health"]
interval: 30s
timeout: 5s
start_period: 10s
retries: 3
ackify-db:
image: postgres:16-alpine

View File

@@ -1,4 +1,4 @@
## SPDX-License-Identifier: AGPL-3.0-or-later
## SPDX-License-Identifier: AGPL-3.0-or-later
name: ackify-ce
services:
@@ -104,6 +104,12 @@ services:
ports:
- "8080:8080"
#END:ports
healthcheck:
test: ["CMD", "/app/ackify", "health"]
interval: 30s
timeout: 5s
start_period: 10s
retries: 3
ackify-db:
image: postgres:16-alpine