From 3276adc8f54a9bdd6ceb528564536404460dac22 Mon Sep 17 00:00:00 2001 From: hacka0wi <124970567+hacka0wi@users.noreply.github.com> Date: Fri, 8 May 2026 00:52:32 +0700 Subject: [PATCH] fix(docker): auto-run prisma db push in web container entrypoint (Closes #6) `docker compose up -d` against an empty Postgres was fatal-failing on the engine startup with `relation "schedulers" does not exist` because nothing in the compose stack ran the Prisma migration. The k8s deployment uses a real init container for this; for the docker-compose / single-host install path we run the same `prisma db push` from a shell wrapper before exec'ing into Next.js. Verified by cloning v0.1.2 fresh, `docker compose up -d`, and watching the engine fatal-crash. With the wrapper the engine starts clean against the migrated DB. Opt-out via `SKIP_DB_MIGRATE=true` for ops setups that prefer to time migrations externally (blue/green deploys, etc.). --- apps/runloop/Dockerfile | 10 +++++++++- apps/runloop/docker-entrypoint.sh | 29 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 apps/runloop/docker-entrypoint.sh diff --git a/apps/runloop/Dockerfile b/apps/runloop/Dockerfile index aa4fbc8..40151f9 100644 --- a/apps/runloop/Dockerfile +++ b/apps/runloop/Dockerfile @@ -55,6 +55,14 @@ COPY --from=builder /app/node_modules/prisma ./node_modules/prisma COPY --from=builder /app/node_modules/@prisma ./node_modules/@prisma COPY --from=builder /app/package.json ./package.json +# Startup wrapper that runs `prisma db push` before `node server.js`. +# Without this, the first `docker compose up` against an empty Postgres +# hits a fatal "relation does not exist" in the engine because no init +# container ran the migration. K8s deployments still use their real init +# container; this just covers the docker-compose / single-host path. +COPY --chown=nextjs:nodejs docker-entrypoint.sh /app/docker-entrypoint.sh +RUN chmod +x /app/docker-entrypoint.sh + USER nextjs EXPOSE 3000 @@ -62,4 +70,4 @@ EXPOSE 3000 ENV PORT 3000 ENV HOSTNAME "0.0.0.0" -CMD ["node", "server.js"] +ENTRYPOINT ["/app/docker-entrypoint.sh"] diff --git a/apps/runloop/docker-entrypoint.sh b/apps/runloop/docker-entrypoint.sh new file mode 100644 index 0000000..f301587 --- /dev/null +++ b/apps/runloop/docker-entrypoint.sh @@ -0,0 +1,29 @@ +#!/bin/sh +# Web container startup wrapper. +# +# Why this exists: a `docker compose up -d` against an empty Postgres +# would otherwise hit a fatal "relation \"schedulers\" does not exist" +# the first time the engine starts, because no init container ran the +# Prisma migration. The k8s deployment uses a real init container for +# this; for docker-compose / single-host deployments we run the same +# `prisma db push` here before handing off to Next.js. +# +# `prisma db push` is idempotent — repeated runs against an already- +# in-sync schema cost ~400 ms and make no changes. So leaving this in +# place permanently is fine. + +set -e + +# Skip migration only if explicitly opted out. Useful for ops setups +# that want to control migration timing externally (e.g. blue/green +# deploys where the new pod starts after a coordinated migration job). +if [ "${SKIP_DB_MIGRATE}" != "true" ]; then + echo "[entrypoint] prisma db push (set SKIP_DB_MIGRATE=true to opt out)..." + npx prisma db push --skip-generate --accept-data-loss +else + echo "[entrypoint] SKIP_DB_MIGRATE=true — skipping prisma db push" +fi + +# Hand off to Next.js. exec replaces this shell so signals (SIGTERM +# from `docker stop`) reach Node directly and graceful-shutdown works. +exec node server.js