fix(deploy): PostgREST env + remove dead nextjs service from compose
Deploy to route.crispygoat.com / deploy (push) Failing after 3s

Build was failing on the 'Start Docker stack' step with two issues:

1. PGRST_DB_URI not set — the env var was only in the 'Deploy' step,
   which runs after PostgREST has already started. PostgREST booted
   with a blank DB URI and the step exited 1.

2. docker-compose.yml had a 'nextjs' service with
   env_file: ../.env.production, but .env.production is written
   later by the 'Deploy' step. docker compose validates the entire
   compose file on 'up' and bailed because the path didn't exist
   yet.

   The 'nextjs' service is dead code anyway: PM2 runs Next.js
   directly from $APP_DIR, never through docker. Removed it.

Also fixed: 'docker compose up -d db postgrest minio minio_init'
referenced services that don't exist in the compose file (Postgres
runs on the host, not in docker). Changed to just 'postgrest', and
the pg_isready check now uses host psql directly instead of
'docker compose exec -T db'.

Changes:
- deploy/docker-compose.yml: drop nextjs service, keep only postgrest
- .gitea/workflows/deploy.yml:
  - Add PGRST_DB_URI / PGRST_DB_ANON_ROLE / PGRST_SERVER_PORT to
    the 'Start Docker stack' step env
  - Write them to $APP_DIR/.env so docker compose picks them up
  - 'docker compose up -d postgrest' (was: db postgrest minio minio_init)
  - pg_isready check uses host psql (was: docker compose exec -T db)
This commit is contained in:
2026-06-06 20:46:52 +00:00
parent 6c5ca6829f
commit 2d55791458
2 changed files with 25 additions and 43 deletions
+18 -4
View File
@@ -25,6 +25,13 @@ jobs:
MINIO_ROOT_USER: ${{ secrets.MINIO_ROOT_USER }}
MINIO_ROOT_PASSWORD: ${{ secrets.MINIO_ROOT_PASSWORD }}
POSTGREST_JWT_SECRET: ${{ secrets.POSTGREST_JWT_SECRET }}
# PostgREST — needs the DB URI at start time (it reads env
# from the container, not from .env.production which is
# written later by the Deploy step).
PGRST_DB_URI: ${{ secrets.PGRST_DB_URI }}
PGRST_DB_ANON_ROLE: ${{ secrets.PGRST_DB_ANON_ROLE }}
PGRST_SERVER_PORT: ${{ secrets.PGRST_SERVER_PORT }}
run: |
APP_DIR=/home/tyler/route-commerce
mkdir -p $APP_DIR
@@ -92,15 +99,22 @@ jobs:
echo "MINIO_ROOT_USER=${MINIO_ROOT_USER}"
echo "MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}"
echo "POSTGREST_JWT_SECRET=${POSTGREST_JWT_SECRET}"
echo "PGRST_DB_URI=${PGRST_DB_URI}"
echo "PGRST_DB_ANON_ROLE=${PGRST_DB_ANON_ROLE:-anon}"
echo "PGRST_SERVER_PORT=${PGRST_SERVER_PORT:-3000}"
echo "POSTGREST_HOST_PORT=$POSTGREST_HOST_PORT"
echo "NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL"
} >> .env
# Bring the stack up fresh — --force-recreate ensures no stale
# network/container references from prior failed attempts
docker compose up -d --force-recreate db postgrest minio minio_init
# Wait for Postgres healthcheck
# network/container references from prior failed attempts.
# Only `postgrest` lives in docker; Postgres itself runs on the
# host (see the migrations step below, which uses
# `psql -h 127.0.0.1`).
docker compose up -d --force-recreate postgrest
# Wait for Postgres to accept connections on the host.
# The DB is on 127.0.0.1, not in a docker service.
for i in $(seq 1 30); do
if docker compose exec -T db pg_isready -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" > /dev/null 2>&1; then
if PGPASSWORD="${POSTGRES_PASSWORD}" psql -h 127.0.0.1 -U "${POSTGRES_USER}" -d "${POSTGRES_DB}" -c "SELECT 1" > /dev/null 2>&1; then
echo "Postgres is ready"
break
fi
+7 -39
View File
@@ -2,17 +2,14 @@
# docker-compose.yml — production stack consumed by deploy.sh
# =============================================================================
#
# The host-side ports (POSTGREST_HOST_PORT, NEXTJS_HOST_PORT) are written by
# deploy.sh into .env.production. We interpolate from there with ${VAR:-3011}
# so a manual `docker compose up` without the deploy script still works.
# Only `postgrest` lives in docker. Postgres itself runs on the host
# (the deploy workflow applies migrations via `psql -h 127.0.0.1`).
# Next.js runs under PM2 on the host — it is NOT a docker service.
#
# Note on networking: the Next.js container calls PostgREST on
# `host.docker.internal:POSTGREST_HOST_PORT` so the inlined
# NEXT_PUBLIC_API_URL (a localhost URL, per the deploy contract) resolves
# correctly. On Linux you may need to add
# extra_hosts:
# - "host.docker.internal:host-gateway"
# which is included below for that reason.
# The host-side port (POSTGREST_HOST_PORT) is written by the deploy
# workflow into $APP_DIR/.env. We interpolate from there with
# ${VAR:-3011} so a manual `docker compose up` without the deploy
# script still works.
# =============================================================================
name: prod-app # default project name; deploy.sh overrides with -p
@@ -39,32 +36,3 @@ services:
timeout: 3s
retries: 6
nextjs:
# Build context is the workspace root (one level up from this file).
build:
context: ..
dockerfile: deploy/Dockerfile.nextjs
container_name: prod-app-nextjs
restart: unless-stopped
ports:
- "${NEXTJS_HOST_PORT:-3012}:3000"
environment:
# Runtime vars — these can change without rebuilding. NEXT_PUBLIC_*
# is also exported here for completeness, but the BROWSER's view of
# NEXT_PUBLIC_API_URL is baked in at build time (see Dockerfile).
NODE_ENV: production
PORT: 3000
NEXT_PUBLIC_API_URL: ${NEXT_PUBLIC_API_URL}
env_file:
- ../.env.production # server-side secrets read at runtime
extra_hosts:
# Lets the container reach the host on the dynamically allocated port.
- "host.docker.internal:host-gateway"
depends_on:
postgrest:
condition: service_healthy
healthcheck:
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:3000/api/health"]
interval: 10s
timeout: 3s
retries: 6