diff --git a/Dockerfile b/Dockerfile index 9ce1a488..9ffd5eef 100644 --- a/Dockerfile +++ b/Dockerfile @@ -67,7 +67,8 @@ EOF EXPOSE 8000 # Health check -HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ +# start-period must outlast the startup script's 60s database wait. +HEALTHCHECK --interval=30s --timeout=3s --start-period=75s --retries=3 \ CMD curl -f http://localhost:8000/up || exit 1 # Create startup script for production @@ -77,32 +78,44 @@ set -e # Wait for database to be ready echo "Waiting for database..." +db_ready=0 for i in $(seq 1 30); do if mysqladmin ping -h "$DB_HOST" -u "$DB_USERNAME" -p"$DB_PASSWORD" --silent 2>/dev/null; then echo "Database is ready!" + db_ready=1 break fi echo "Waiting for database... ($i/30)" sleep 2 done +if [ "$db_ready" -ne 1 ]; then + echo "Database unreachable at ${DB_HOST} after 60s; exiting so the restart policy retries." >&2 + exit 1 +fi + # Cache config with runtime env vars echo "Caching configuration..." php artisan config:cache -# Run migrations +# Run migrations. A partial schema is worse than a container that refuses to start. echo "Running migrations..." -php artisan migrate --force || echo "Migrations failed or already up-to-date" +php artisan migrate --force # Run seeders (idempotent - uses updateOrInsert) echo "Running seeders..." -php artisan db:seed --force || echo "Seeders failed or already run" +php artisan db:seed --force -# Start Horizon in the background -php artisan horizon & +# Restart a worker that dies instead of leaving the queue unconsumed. +supervise() { + while true; do + "$@" || echo "[supervisor] '$*' exited with $?; restarting in 5s." >&2 + sleep 5 + done +} -# Start the scheduler in the background -php artisan schedule:work & +supervise php artisan horizon & +supervise php artisan schedule:work & # Start FrankenPHP exec frankenphp run --config /etc/caddy/Caddyfile