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
|
RUN mkdir -p /app/data
|
||||||
VOLUME /app/data
|
VOLUME /app/data
|
||||||
|
|
||||||
# Healthy when the server answers and can reach its database
|
# Healthy when the server answers and can reach its database.
|
||||||
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --start-interval=2s --retries=3 \
|
# (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"]
|
CMD ["/app/rezervator", "-c", "/app/config/config.toml", "--healthcheck"]
|
||||||
|
|
||||||
# Run the server
|
# Run the server
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ The two settings are independent. [Setup with nginx and PostgreSQL on the host](
|
|||||||
|
|
||||||
## Requirements
|
## 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.
|
- 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
|
- 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
|
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() {
|
wait_healthy() {
|
||||||
local container="$1" status
|
local container="$1" state has_check
|
||||||
for _ in $(seq 1 90); do
|
has_check="$(docker inspect --format '{{if .Config.Healthcheck}}yes{{else}}no{{end}}' "$container" 2>/dev/null || echo "no")"
|
||||||
status="$(docker inspect --format '{{.State.Status}} {{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' "$container" 2>/dev/null || echo "missing")"
|
|
||||||
case "$status" in
|
if [ "$has_check" = "no" ]; then
|
||||||
"running healthy")
|
# Image from before the health check: running for a while is the best we can tell
|
||||||
# Traefik picks a new container up a moment after it turns healthy
|
sleep 5
|
||||||
if [ "$PROXY" = "traefik" ]; then sleep 3; fi
|
[ "$(docker inspect --format '{{.State.Status}}' "$container" 2>/dev/null)" = "running" ]
|
||||||
return 0 ;;
|
return
|
||||||
# Image without a health check: running for a while is the best we can tell
|
fi
|
||||||
"running none") sleep 5
|
|
||||||
[ "$(docker inspect --format '{{.State.Status}}' "$container" 2>/dev/null)" = "running" ] && return 0
|
# Probe directly instead of waiting for Docker: its first check comes only after the
|
||||||
return 1 ;;
|
# check interval, and the faster start interval needs Docker 25
|
||||||
"running starting") ;;
|
local ready="no"
|
||||||
"running unhealthy") return 1 ;;
|
for _ in $(seq 1 60); do
|
||||||
running*) ;;
|
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 ;;
|
*) return 1 ;;
|
||||||
esac
|
esac
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
return 1
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_init() {
|
cmd_init() {
|
||||||
|
|||||||
Reference in New Issue
Block a user