Docker image can be built with Docker 20.10, deployment script probes health itself.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+3
-2
@@ -56,8 +56,9 @@ VOLUME /app/config
|
||||
RUN mkdir -p /app/data
|
||||
VOLUME /app/data
|
||||
|
||||
# Healthy when the server answers and can reach its database
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --start-interval=2s --retries=3 \
|
||||
# Healthy when the server answers and can reach its database.
|
||||
# (No --start-interval: it needs Docker 25, and deploy/rezervator.sh probes on its own.)
|
||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
|
||||
CMD ["/app/rezervator", "-c", "/app/config/config.toml", "--healthcheck"]
|
||||
|
||||
# Run the server
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ The two settings are independent. [Setup with nginx and PostgreSQL on the host](
|
||||
|
||||
## Requirements
|
||||
|
||||
- Docker with the Compose plugin, `bash` and `openssl` on the host
|
||||
- Docker 20.10 or newer, `bash` and `openssl` on the host. The Compose plugin is needed only when Traefik or PostgreSQL run as containers of this stack.
|
||||
- The application image on the host: `docker build -t rezervator:latest .` in the repository root, or pulled from a registry. The image must match the CPU architecture of the host.
|
||||
- A DNS record for every customer domain pointing to the host
|
||||
|
||||
|
||||
+43
-16
@@ -267,28 +267,55 @@ run_container() {
|
||||
docker run "${args[@]}" "$image" >/dev/null
|
||||
}
|
||||
|
||||
# Waits until the container reports healthy. Returns 1 when it stops or stays unhealthy.
|
||||
# Waits until the application in the container is up and can reach its database.
|
||||
# Returns 1 when the container stops or does not get healthy in time.
|
||||
wait_healthy() {
|
||||
local container="$1" status
|
||||
for _ in $(seq 1 90); do
|
||||
status="$(docker inspect --format '{{.State.Status}} {{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "$container" 2>/dev/null || echo "missing")"
|
||||
case "$status" in
|
||||
"running healthy")
|
||||
# Traefik picks a new container up a moment after it turns healthy
|
||||
if [ "$PROXY" = "traefik" ]; then sleep 3; fi
|
||||
return 0 ;;
|
||||
# Image without a health check: running for a while is the best we can tell
|
||||
"running none") sleep 5
|
||||
[ "$(docker inspect --format '{{.State.Status}}' "$container" 2>/dev/null)" = "running" ] && return 0
|
||||
return 1 ;;
|
||||
"running starting") ;;
|
||||
"running unhealthy") return 1 ;;
|
||||
running*) ;;
|
||||
local container="$1" state has_check
|
||||
has_check="$(docker inspect --format '{{if .Config.Healthcheck}}yes{{else}}no{{end}}' "$container" 2>/dev/null || echo "no")"
|
||||
|
||||
if [ "$has_check" = "no" ]; then
|
||||
# Image from before the health check: running for a while is the best we can tell
|
||||
sleep 5
|
||||
[ "$(docker inspect --format '{{.State.Status}}' "$container" 2>/dev/null)" = "running" ]
|
||||
return
|
||||
fi
|
||||
|
||||
# Probe directly instead of waiting for Docker: its first check comes only after the
|
||||
# check interval, and the faster start interval needs Docker 25
|
||||
local ready="no"
|
||||
for _ in $(seq 1 60); do
|
||||
state="$(docker inspect --format '{{.State.Status}}' "$container" 2>/dev/null || echo "missing")"
|
||||
case "$state" in
|
||||
running)
|
||||
if docker exec "$container" /app/rezervator -c /app/config/config.toml --healthcheck >/dev/null 2>&1; then
|
||||
ready="yes"
|
||||
break
|
||||
fi ;;
|
||||
restarting|created) ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
# A container that fails at start is restarted by Docker over and over
|
||||
if [ "$(docker inspect --format '{{.RestartCount}}' "$container" 2>/dev/null || echo 0)" -ge 3 ]; then
|
||||
return 1
|
||||
fi
|
||||
sleep 2
|
||||
done
|
||||
[ "$ready" = "yes" ] || return 1
|
||||
|
||||
if [ "$PROXY" = "traefik" ]; then
|
||||
# Traefik routes to the container only once Docker itself reports it healthy
|
||||
for _ in $(seq 1 45); do
|
||||
state="$(docker inspect --format '{{.State.Health.Status}}' "$container" 2>/dev/null || echo "missing")"
|
||||
case "$state" in
|
||||
healthy) sleep 3; return 0 ;;
|
||||
starting) ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
sleep 2
|
||||
done
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
cmd_init() {
|
||||
|
||||
Reference in New Issue
Block a user