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_USER: ${{ secrets.MINIO_ROOT_USER }}
MINIO_ROOT_PASSWORD: ${{ secrets.MINIO_ROOT_PASSWORD }} MINIO_ROOT_PASSWORD: ${{ secrets.MINIO_ROOT_PASSWORD }}
POSTGREST_JWT_SECRET: ${{ secrets.POSTGREST_JWT_SECRET }} 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: | run: |
APP_DIR=/home/tyler/route-commerce APP_DIR=/home/tyler/route-commerce
mkdir -p $APP_DIR mkdir -p $APP_DIR
@@ -92,15 +99,22 @@ jobs:
echo "MINIO_ROOT_USER=${MINIO_ROOT_USER}" echo "MINIO_ROOT_USER=${MINIO_ROOT_USER}"
echo "MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}" echo "MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}"
echo "POSTGREST_JWT_SECRET=${POSTGREST_JWT_SECRET}" 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 "POSTGREST_HOST_PORT=$POSTGREST_HOST_PORT"
echo "NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL" echo "NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL"
} >> .env } >> .env
# Bring the stack up fresh — --force-recreate ensures no stale # Bring the stack up fresh — --force-recreate ensures no stale
# network/container references from prior failed attempts # network/container references from prior failed attempts.
docker compose up -d --force-recreate db postgrest minio minio_init # Only `postgrest` lives in docker; Postgres itself runs on the
# Wait for Postgres healthcheck # 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 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" echo "Postgres is ready"
break break
fi fi
+7 -39
View File
@@ -2,17 +2,14 @@
# docker-compose.yml — production stack consumed by deploy.sh # docker-compose.yml — production stack consumed by deploy.sh
# ============================================================================= # =============================================================================
# #
# The host-side ports (POSTGREST_HOST_PORT, NEXTJS_HOST_PORT) are written by # Only `postgrest` lives in docker. Postgres itself runs on the host
# deploy.sh into .env.production. We interpolate from there with ${VAR:-3011} # (the deploy workflow applies migrations via `psql -h 127.0.0.1`).
# so a manual `docker compose up` without the deploy script still works. # Next.js runs under PM2 on the host — it is NOT a docker service.
# #
# Note on networking: the Next.js container calls PostgREST on # The host-side port (POSTGREST_HOST_PORT) is written by the deploy
# `host.docker.internal:POSTGREST_HOST_PORT` so the inlined # workflow into $APP_DIR/.env. We interpolate from there with
# NEXT_PUBLIC_API_URL (a localhost URL, per the deploy contract) resolves # ${VAR:-3011} so a manual `docker compose up` without the deploy
# correctly. On Linux you may need to add # script still works.
# extra_hosts:
# - "host.docker.internal:host-gateway"
# which is included below for that reason.
# ============================================================================= # =============================================================================
name: prod-app # default project name; deploy.sh overrides with -p name: prod-app # default project name; deploy.sh overrides with -p
@@ -39,32 +36,3 @@ services:
timeout: 3s timeout: 3s
retries: 6 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