feat: update environment configuration for production and add Docker support
Some checks are pending
CI/CD / test-and-build (push) Waiting to run
CI/CD / deploy (push) Blocked by required conditions

This commit is contained in:
Najjar\NajjarV02 2026-04-15 10:04:07 +04:00
parent 3fbdc3b187
commit 138e8377a6
6 changed files with 124 additions and 7 deletions

23
.dockerignore Normal file
View File

@ -0,0 +1,23 @@
node_modules
.next
.git
.gitignore
# Local env files — set these as environment variables in Coolify instead
.env
.env.local
.env.*.local
# SQLite database files — mount /app/prisma as a persistent volume in Coolify
prisma/*.db
prisma/*.db-shm
prisma/*.db-wal
prisma/migrations
# Dev/test artifacts
coverage
*.log
vitest.config.ts
src/**/*.test.ts
src/**/*.test.tsx
test/

View File

@ -1,4 +1,18 @@
# Stripe Keys # ─────────────────────────────────────────────────────────────────────────────
# Get your keys from https://dashboard.stripe.com/apikeys # Stripe — https://dashboard.stripe.com/apikeys
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_51RBtf7I7xOcO9rzigsLLK3esMLmBlJoRztbzUadPhQm7tcHQuScViFEkwdfAwDxbaqt5n8BOuJV9wRSMdn2IrxIX00lqGOOJfT # ─────────────────────────────────────────────────────────────────────────────
STRIPE_SECRET_KEY=sk_test_51RBtf7I7xOcO9rzitxMqK3jnTb3SPdEbyGxGBnPccGEfrIrpiEFEOIEG2oHuTumaUejUN4FyAOBg0AVCBRn6AOKI00LeWSDC10 NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...
STRIPE_SECRET_KEY=sk_live_...
STRIPE_WEBHOOK_SECRET=whsec_...
# ─────────────────────────────────────────────────────────────────────────────
# Admin JWT (generate with: openssl rand -hex 32)
# ─────────────────────────────────────────────────────────────────────────────
ADMIN_JWT_SECRET=change_me_generate_with_openssl_rand_hex_32
# ─────────────────────────────────────────────────────────────────────────────
# Database — SQLite via libsql
# In Coolify: set to file:/app/prisma/lootah.db
# and mount /app/prisma as a persistent volume
# ─────────────────────────────────────────────────────────────────────────────
DATABASE_URL=file:./prisma/lootah.db

62
Dockerfile Normal file
View File

@ -0,0 +1,62 @@
# ── Stage 1: install all dependencies ─────────────────────────────────────────
FROM node:22.14-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
# ── Stage 2: build ─────────────────────────────────────────────────────────────
FROM node:22.14-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
# Generate Prisma client (reads prisma/schema.prisma + prisma.config.ts)
RUN npx prisma generate
# Build Next.js — produces .next/standalone (set in next.config.mjs)
RUN npm run build
# ── Stage 3: production runner ─────────────────────────────────────────────────
FROM node:22.14-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000
ENV HOSTNAME=0.0.0.0
# dumb-init: proper PID 1 / signal forwarding
RUN apk add --no-cache dumb-init \
&& addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 nextjs
# ── Next.js standalone server ──────────────────────────────────────────────────
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
# ── Prisma runtime ─────────────────────────────────────────────────────────────
# Config + schema (read by CLI at container startup for db push)
COPY --from=builder --chown=nextjs:nodejs /app/prisma.config.ts ./
COPY --from=builder --chown=nextjs:nodejs /app/prisma/schema.prisma ./prisma/
# Generated Prisma client (imported by the compiled Next.js server bundle)
COPY --from=builder --chown=nextjs:nodejs /app/src/generated ./src/generated
# Prisma CLI + its dependencies (devDeps — not bundled into standalone node_modules)
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/.bin/prisma ./node_modules/.bin/prisma
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/prisma ./node_modules/prisma
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/@prisma ./node_modules/@prisma
COPY --from=builder --chown=nextjs:nodejs /app/node_modules/@libsql ./node_modules/@libsql
# ── Entrypoint ─────────────────────────────────────────────────────────────────
COPY --chown=nextjs:nodejs docker-entrypoint.sh ./
RUN chmod +x /app/docker-entrypoint.sh
USER nextjs
EXPOSE 3000
# dumb-init wraps our entrypoint so SIGTERM is forwarded to node properly
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/app/docker-entrypoint.sh"]

14
docker-entrypoint.sh Normal file
View File

@ -0,0 +1,14 @@
#!/bin/sh
set -e
# Ensure the persistent database directory exists
# (Coolify: mount a volume at /app/prisma so data survives redeployments)
mkdir -p /app/prisma
echo "→ Syncing database schema..."
# db push creates the SQLite file and syncs tables to match schema.prisma
# --skip-generate: client was already generated at build time
/app/node_modules/.bin/prisma db push --skip-generate
echo "→ Starting Next.js on port ${PORT:-3000}..."
exec node /app/server.js

View File

@ -6,6 +6,8 @@ export default defineConfig({
path: "prisma/migrations", path: "prisma/migrations",
}, },
datasource: { datasource: {
url: "file:./prisma/lootah.db", // In production (Coolify), set DATABASE_URL=file:/app/prisma/lootah.db
// and mount /app/prisma as a persistent volume.
url: process.env.DATABASE_URL ?? "file:./prisma/lootah.db",
}, },
}); });

View File

@ -5,8 +5,10 @@ import path from 'path';
const globalForPrisma = globalThis as unknown as { prisma: PrismaClient }; const globalForPrisma = globalThis as unknown as { prisma: PrismaClient };
function createPrismaClient() { function createPrismaClient() {
const dbPath = path.resolve(process.cwd(), 'prisma/lootah.db'); // Use DATABASE_URL if set (production/Coolify), otherwise fall back to local path.
const adapter = new PrismaLibSql({ url: `file:${dbPath}` }); const dbUrl = process.env.DATABASE_URL
?? `file:${path.resolve(process.cwd(), 'prisma/lootah.db')}`;
const adapter = new PrismaLibSql({ url: dbUrl });
return new PrismaClient({ adapter } as ConstructorParameters<typeof PrismaClient>[0]); return new PrismaClient({ adapter } as ConstructorParameters<typeof PrismaClient>[0]);
} }