SERVICE_FQDN_FRONTEND_8080 is not generated when the domain is assigned without a port suffix; Coolify needs SERVICE_URL_FRONTEND_8080 so Traefik gets loadbalancer.server.port=8080 for Frappe nginx.
121 lines
4 KiB
Bash
Executable file
121 lines
4 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# Validate docker-compose for production/Coolify deploy safety
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
set -euo pipefail
|
|
|
|
REPO="${1:-.}"
|
|
REPO="$(cd "$REPO" && pwd)"
|
|
COOLIFY_STRICT="${COOLIFY_STRICT:-0}"
|
|
|
|
ERR=0
|
|
WARN=0
|
|
|
|
err() { echo "ERROR $*"; ERR=$((ERR + 1)); }
|
|
warn() { echo "WARN $*"; WARN=$((WARN + 1)); }
|
|
info() { echo "INFO $*"; }
|
|
pass() { echo "OK $*"; }
|
|
|
|
COMPOSE_FILE=""
|
|
for f in docker-compose.yml docker-compose.yaml compose.yml; do
|
|
if [ -f "$REPO/$f" ]; then
|
|
COMPOSE_FILE="$REPO/$f"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ -z "$COMPOSE_FILE" ]; then
|
|
echo "INFO No docker-compose file — skip"
|
|
exit 0
|
|
fi
|
|
|
|
echo "=== validate-docker-compose: $COMPOSE_FILE ==="
|
|
|
|
# Coolify-only keys (exclude_from_hc) are stripped before docker compose config
|
|
COMPOSE_VALIDATE_FILE="$COMPOSE_FILE"
|
|
if grep -q 'exclude_from_hc:' "$COMPOSE_FILE"; then
|
|
COMPOSE_VALIDATE_FILE="$(mktemp)"
|
|
sed '/exclude_from_hc:/d' "$COMPOSE_FILE" > "$COMPOSE_VALIDATE_FILE"
|
|
info "[DC-00] stripped exclude_from_hc for docker compose config"
|
|
fi
|
|
|
|
# docker compose config
|
|
if command -v docker >/dev/null 2>&1; then
|
|
if docker compose -f "$COMPOSE_VALIDATE_FILE" config -q 2>/dev/null; then
|
|
pass "[DC-01] docker compose config OK"
|
|
else
|
|
err "[DC-01] docker compose config failed"
|
|
docker compose -f "$COMPOSE_VALIDATE_FILE" config 2>&1 | tail -20 || true
|
|
fi
|
|
else
|
|
warn "[DC-01] docker not available — syntax not fully validated"
|
|
fi
|
|
|
|
[ "$COMPOSE_VALIDATE_FILE" != "$COMPOSE_FILE" ] && rm -f "$COMPOSE_VALIDATE_FILE"
|
|
|
|
# Coolify: no host ports on HTTP services
|
|
if grep -E '^\s+ports:' "$COMPOSE_FILE" >/dev/null 2>&1; then
|
|
err "[DC-02] ports: found — Coolify uses SERVICE_URL_* instead"
|
|
else
|
|
pass "[DC-02] no host ports (Coolify-safe)"
|
|
fi
|
|
|
|
# SERVICE_FQDN on frontend with port 8080 (Frappe nginx default; Coolify Traefik target)
|
|
if grep -q 'SERVICE_URL_FRONTEND_8080' "$COMPOSE_FILE"; then
|
|
pass "[DC-03] SERVICE_URL_FRONTEND_8080 present (Traefik → nginx:8080)"
|
|
else
|
|
err "[DC-03] missing SERVICE_URL_FRONTEND_8080 on frontend"
|
|
fi
|
|
|
|
if grep -q 'SERVICE_FQDN_FRONTEND' "$COMPOSE_FILE"; then
|
|
pass "[DC-07] SERVICE_FQDN_FRONTEND present (Coolify domain → SITE_NAME)"
|
|
else
|
|
warn "[DC-07] missing SERVICE_FQDN_FRONTEND — SITE_NAME will not track Coolify domain"
|
|
fi
|
|
|
|
if grep -q 'CUSTOM_IMAGE' "$COMPOSE_FILE" && grep -q 'CUSTOM_TAG' "$COMPOSE_FILE"; then
|
|
pass "[DC-10] CUSTOM_IMAGE / CUSTOM_TAG configured for Jenkins registry"
|
|
else
|
|
warn "[DC-10] missing CUSTOM_IMAGE or CUSTOM_TAG in compose"
|
|
fi
|
|
|
|
# Bind mounts ./scripts on long-running services (heuristic)
|
|
if grep -E '^\s+-\s+['\''"]?\./scripts' "$COMPOSE_FILE" >/dev/null 2>&1; then
|
|
if grep -B30 './scripts' "$COMPOSE_FILE" | grep -qE 'restart:\s+(unless-stopped|always)'; then
|
|
if [ "$COOLIFY_STRICT" = "1" ]; then
|
|
err "[DC-04] ./scripts bind mount on restarting service — Coolify may miss files"
|
|
else
|
|
warn "[DC-04] ./scripts bind mount — prefer inline compose for Coolify daemons"
|
|
fi
|
|
else
|
|
info "[DC-04] ./scripts mount on non-restarting service (may be OK)"
|
|
fi
|
|
fi
|
|
|
|
# SERVICE_URL on compose (Coolify magic vars)
|
|
if grep -qE 'SERVICE_URL_[A-Z0-9_]+' "$COMPOSE_FILE"; then
|
|
if grep -qE 'networks:' "$COMPOSE_FILE" && ! grep -qE '^\s+default:' "$COMPOSE_FILE"; then
|
|
warn "[DC-05] SERVICE_URL_* with custom networks — risk Traefik 504; see coolify-docker-compose skill"
|
|
fi
|
|
fi
|
|
|
|
# fabric-price-oracle / gateway port hints
|
|
if grep -q 'fabric-gateway' "$COMPOSE_FILE"; then
|
|
if grep -A80 'fabric-gateway:' "$COMPOSE_FILE" | grep -qE "['\"]?3000:3000|GATEWAY_PORT"; then
|
|
pass "[DC-08] fabric-gateway publishes port 3000"
|
|
else
|
|
warn "[DC-08] fabric-gateway may not publish host port 3000"
|
|
fi
|
|
fi
|
|
|
|
# Retired oracle stub
|
|
if grep -q 'fabric-oracle:' "$COMPOSE_FILE"; then
|
|
if grep -A15 'fabric-oracle:' "$COMPOSE_FILE" | grep -qE 'profiles:|legacy|Retired|exit 0'; then
|
|
pass "[DC-09] fabric-oracle retired/profiled"
|
|
else
|
|
warn "[DC-09] fabric-oracle still active — should be legacy stub"
|
|
fi
|
|
fi
|
|
|
|
echo "compose errors=$ERR warnings=$WARN"
|
|
[ "$ERR" -eq 0 ] || exit 1
|
|
exit 0
|