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