Dev #9
+77
-3
@@ -3,26 +3,100 @@ set -euo pipefail
|
|||||||
|
|
||||||
cd /var/www/html
|
cd /var/www/html
|
||||||
|
|
||||||
|
# region agent log
|
||||||
|
fc_debug_log() {
|
||||||
|
local hypothesis="$1"
|
||||||
|
|
|||||||
|
local message="$2"
|
||||||
|
local data_json="${3:-{}}"
|
||||||
|
local data_b64
|
||||||
|
data_b64=$(printf '%s' "$data_json" | base64 | tr -d '\n')
|
||||||
|
FC_DEBUG_HYPOTHESIS="$hypothesis" FC_DEBUG_MESSAGE="$message" FC_DEBUG_DATA_B64="$data_b64" php -r '
|
||||||
|
$json = base64_decode(getenv("FC_DEBUG_DATA_B64") ?: "");
|
||||||
|
$data = json_decode($json, true);
|
||||||
|
if (!is_array($data) && str_ends_with($json, "}}")) {
|
||||||
|
$data = json_decode(substr($json, 0, -1), true);
|
||||||
|
}
|
||||||
|
$payload = [
|
||||||
|
"sessionId" => "885d37",
|
||||||
|
"runId" => "coolify-bad-gateway",
|
||||||
|
"hypothesisId" => getenv("FC_DEBUG_HYPOTHESIS") ?: "",
|
||||||
|
"location" => "docker/entrypoint.sh",
|
||||||
|
"message" => getenv("FC_DEBUG_MESSAGE") ?: "",
|
||||||
|
"data" => [
|
||||||
|
"raw_json" => $json,
|
||||||
|
"parsed" => is_array($data) ? $data : null,
|
||||||
|
],
|
||||||
|
"timestamp" => (int) round(microtime(true) * 1000),
|
||||||
|
];
|
||||||
|
$line = json_encode($payload, JSON_UNESCAPED_SLASHES) . PHP_EOL;
|
||||||
|
@file_put_contents("/var/www/html/debug-885d37.log", $line, FILE_APPEND);
|
||||||
|
fwrite(STDERR, "agent_debug " . $line);
|
||||||
|
'
|
||||||
|
}
|
||||||
|
# endregion
|
||||||
|
|
||||||
echo "[flixcooks] Waiting for database..."
|
echo "[flixcooks] Waiting for database..."
|
||||||
TRIES=0
|
TRIES=0
|
||||||
MAX_TRIES="${DB_WAIT_MAX_TRIES:-30}"
|
MAX_TRIES="${DB_WAIT_MAX_TRIES:-30}"
|
||||||
|
start_data=$(php -r 'echo json_encode([
|
||||||
|
"database_url_present" => getenv("DATABASE_URL") !== false && getenv("DATABASE_URL") !== "",
|
||||||
|
"run_db_seed" => getenv("RUN_DB_SEED") ?: "",
|
||||||
|
"db_wait_max_tries" => getenv("DB_WAIT_MAX_TRIES") ?: "30",
|
||||||
|
"entrypoint_args" => array_slice($argv, 1),
|
||||||
|
"schema_file_exists" => file_exists("/var/www/html/scripts/schema.sql"),
|
||||||
|
"seed_file_exists" => file_exists("/var/www/html/data/recipes.json"),
|
||||||
|
]);' -- "$@")
|
||||||
|
fc_debug_log "H1,H2,H4" "entrypoint started" "$start_data"
|
||||||
|
|
||||||
until php scripts/db-check.php >/dev/null 2>&1; do
|
until db_check_output=$(php scripts/db-check.php 2>&1); do
|
||||||
TRIES=$((TRIES + 1))
|
TRIES=$((TRIES + 1))
|
||||||
|
fail_data=$(php -r 'echo json_encode([
|
||||||
|
"attempt" => (int) $argv[1],
|
||||||
|
"max_tries" => (int) $argv[2],
|
||||||
|
"db_check_output" => $argv[3],
|
||||||
|
]);' -- "$TRIES" "$MAX_TRIES" "$db_check_output")
|
||||||
|
fc_debug_log "H1" "db-check failed while waiting" "$fail_data"
|
||||||
if [ "$TRIES" -ge "$MAX_TRIES" ]; then
|
if [ "$TRIES" -ge "$MAX_TRIES" ]; then
|
||||||
echo "[flixcooks] Database not reachable after ${MAX_TRIES} attempts." >&2
|
echo "[flixcooks] Database not reachable after ${MAX_TRIES} attempts." >&2
|
||||||
|
fc_debug_log "H1" "entrypoint exiting because database never became reachable" "$fail_data"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
success_data=$(php -r 'echo json_encode([
|
||||||
|
"attempts_before_success" => (int) $argv[1],
|
||||||
|
"db_check_output" => $argv[2],
|
||||||
|
]);' -- "$TRIES" "$db_check_output")
|
||||||
|
fc_debug_log "H1" "db-check succeeded" "$success_data"
|
||||||
|
|
||||||
echo "[flixcooks] Applying schema..."
|
echo "[flixcooks] Applying schema..."
|
||||||
php -r "require 'helpers.php'; require_database(); echo \"schema ok\n\";"
|
if schema_output=$(php -r "require 'helpers.php'; require_database(); echo \"schema ok\n\";" 2>&1); then
|
||||||
|
schema_data=$(php -r 'echo json_encode(["schema_output" => $argv[1]]);' -- "$schema_output")
|
||||||
|
fc_debug_log "H2,H4" "schema apply succeeded" "$schema_data"
|
||||||
|
else
|
||||||
|
code=$?
|
||||||
|
schema_data=$(php -r 'echo json_encode(["exit_code" => (int) $argv[1], "schema_output" => $argv[2]]);' -- "$code" "$schema_output")
|
||||||
|
fc_debug_log "H2,H4" "schema apply failed, entrypoint exiting" "$schema_data"
|
||||||
|
echo "$schema_output" >&2
|
||||||
|
exit "$code"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "${RUN_DB_SEED:-false}" = "true" ]; then
|
if [ "${RUN_DB_SEED:-false}" = "true" ]; then
|
||||||
echo "[flixcooks] Seeding recipes from data/recipes.json..."
|
echo "[flixcooks] Seeding recipes from data/recipes.json..."
|
||||||
php scripts/db-seed.php
|
if seed_output=$(php scripts/db-seed.php 2>&1); then
|
||||||
|
seed_data=$(php -r 'echo json_encode(["seed_output" => $argv[1]]);' -- "$seed_output")
|
||||||
|
fc_debug_log "H4" "seed succeeded" "$seed_data"
|
||||||
|
else
|
||||||
|
code=$?
|
||||||
|
seed_data=$(php -r 'echo json_encode(["exit_code" => (int) $argv[1], "seed_output" => $argv[2]]);' -- "$code" "$seed_output")
|
||||||
|
fc_debug_log "H4" "seed failed, entrypoint exiting" "$seed_data"
|
||||||
|
echo "$seed_output" >&2
|
||||||
|
exit "$code"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
fc_debug_log "H4" "seed skipped" '{"run_db_seed":"false"}'
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[flixcooks] Starting Apache..."
|
echo "[flixcooks] Starting Apache..."
|
||||||
|
fc_debug_log "H3" "executing web server command" "$(php -r 'echo json_encode(["command" => array_slice($argv, 1)]);' -- "$@")"
|
||||||
exec "$@"
|
exec "$@"
|
||||||
|
|||||||
+30
-21
@@ -26,8 +26,8 @@ Die App startet **nicht**, wenn `DATABASE_URL` fehlt oder Postgres nicht erreich
|
|||||||
|
|
||||||
1. Neues **Database** → PostgreSQL (16).
|
1. Neues **Database** → PostgreSQL (16).
|
||||||
2. Notieren:
|
2. Notieren:
|
||||||
- Benutzer, Passwort, Datenbankname
|
- Benutzer, Passwort, Datenbankname
|
||||||
- **Internal URL** (Host ist oft der Service-Name, z. B. `postgresql-xxxxx` oder was Coolify anzeigt)
|
- **Internal URL** (Host ist oft der Service-Name, z. B. `postgresql-xxxxx` oder was Coolify anzeigt)
|
||||||
3. Format für die App:
|
3. Format für die App:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@@ -50,22 +50,26 @@ postgresql://flixcooks:geheim@postgresql-flixcooks:5432/flixcooks
|
|||||||
2. Dockerfile-Pfad: `Dockerfile` (Root).
|
2. Dockerfile-Pfad: `Dockerfile` (Root).
|
||||||
3. Port: **80** (Container exponiert Apache auf 80).
|
3. Port: **80** (Container exponiert Apache auf 80).
|
||||||
4. Health Check (optional, empfohlen):
|
4. Health Check (optional, empfohlen):
|
||||||
- Path: `/health.php`
|
- Path: `/health.php`
|
||||||
- Erwartet HTTP 200 mit `{"status":"ok"}`
|
- Erwartet HTTP 200 mit `{"status":"ok"}`
|
||||||
|
|
||||||
### Environment Variables (Pflicht)
|
### Environment Variables (Pflicht)
|
||||||
|
|
||||||
| Variable | Beschreibung |
|
|
||||||
|----------|----------------|
|
| Variable | Beschreibung |
|
||||||
| `DATABASE_URL` | Interne Postgres-URL von Coolify |
|
| --------------------- | --------------------------------- |
|
||||||
|
| `DATABASE_URL` | Interne Postgres-URL von Coolify |
|
||||||
| `FLIXCOOKS_ADMIN_KEY` | Starkes Passwort für `/admin.php` |
|
| `FLIXCOOKS_ADMIN_KEY` | Starkes Passwort für `/admin.php` |
|
||||||
|
|
||||||
|
|
||||||
### Environment Variables (optional)
|
### Environment Variables (optional)
|
||||||
|
|
||||||
| Variable | Default | Beschreibung |
|
|
||||||
|----------|---------|----------------|
|
| Variable | Default | Beschreibung |
|
||||||
| `RUN_DB_SEED` | `false` | Einmalig `true` setzen → importiert `data/recipes.json` beim Start |
|
| ------------------- | ------- | ------------------------------------------------------------------ |
|
||||||
| `DB_WAIT_MAX_TRIES` | `30` | Warteversuche bis Postgres da ist (à 2 s) |
|
| `RUN_DB_SEED` | `false` | Einmalig `true` setzen → importiert `data/recipes.json` beim Start |
|
||||||
|
| `DB_WAIT_MAX_TRIES` | `30` | Warteversuche bis Postgres da ist (à 2 s) |
|
||||||
|
|
||||||
|
|
||||||
Nach dem ersten erfolgreichen Deploy: `RUN_DB_SEED` wieder auf `false` oder entfernen.
|
Nach dem ersten erfolgreichen Deploy: `RUN_DB_SEED` wieder auf `false` oder entfernen.
|
||||||
|
|
||||||
@@ -73,9 +77,11 @@ Nach dem ersten erfolgreichen Deploy: `RUN_DB_SEED` wieder auf `false` oder entf
|
|||||||
|
|
||||||
Mount für Impressum/Datenschutz (`data/site.json`):
|
Mount für Impressum/Datenschutz (`data/site.json`):
|
||||||
|
|
||||||
| Mount Path (Container) | Inhalt |
|
|
||||||
|------------------------|--------|
|
| Mount Path (Container) | Inhalt |
|
||||||
| `/var/www/html/data` | `site.json` bleibt nach Redeploy erhalten |
|
| ---------------------- | ----------------------------------------- |
|
||||||
|
| `/var/www/html/data` | `site.json` bleibt nach Redeploy erhalten |
|
||||||
|
|
||||||
|
|
||||||
Rezepte liegen in Postgres – **kein** Volume für Rezepte nötig.
|
Rezepte liegen in Postgres – **kein** Volume für Rezepte nötig.
|
||||||
|
|
||||||
@@ -131,10 +137,13 @@ curl http://127.0.0.1:8080/health.php
|
|||||||
|
|
||||||
## 7. Troubleshooting
|
## 7. Troubleshooting
|
||||||
|
|
||||||
| Problem | Lösung |
|
|
||||||
|---------|--------|
|
| Problem | Lösung |
|
||||||
| Container startet nicht | Logs: DB nicht erreichbar → `DATABASE_URL` Host/Passwort prüfen |
|
| -------------------------------- | --------------------------------------------------------------- |
|
||||||
| 503 „Datenbank nicht verfügbar“ | Gleiches Netzwerk in Coolify? Internal URL? |
|
| Container startet nicht | Logs: DB nicht erreichbar → `DATABASE_URL` Host/Passwort prüfen |
|
||||||
| Leere Seite, Health OK | `RUN_DB_SEED=true` einmalig oder Admin-Rezepte anlegen |
|
| 503 „Datenbank nicht verfügbar“ | Gleiches Netzwerk in Coolify? Internal URL? |
|
||||||
| Admin geht nicht | `FLIXCOOKS_ADMIN_KEY` gesetzt? |
|
| Leere Seite, Health OK | `RUN_DB_SEED=true` einmalig oder Admin-Rezepte anlegen |
|
||||||
| `site.json` verloren nach Deploy | Volume auf `/var/www/html/data` mounten |
|
| Admin geht nicht | `FLIXCOOKS_ADMIN_KEY` gesetzt? |
|
||||||
|
| `site.json` verloren nach Deploy | Volume auf `/var/www/html/data` mounten |
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user
Making the maximum number of retries configurable via an environment variable is a good flexible design. The default of 30 attempts (with a 2-second sleep) provides a generous 60-second wait, which is generally sufficient. Ensure this timeout is documented or understood by users deploying the application.