From 8d1f91d636b8884484ad3356d14de877e5de5400 Mon Sep 17 00:00:00 2001 From: Froidefond Julien Date: Wed, 11 Mar 2026 21:52:49 +0100 Subject: [PATCH] feat: optimize Docker startup with Next.js standalone output and proper migrations - Add `output: standalone` to next.config.js for faster cold start - Rebuild runner stage around standalone bundle (node server.js instead of pnpm start) - Replace prisma db push with prisma migrate deploy (proper migration workflow) - Remove npx/pnpm at runtime, use direct binary paths - Add HOSTNAME=0.0.0.0 for standalone server to listen on all interfaces - Fix next.config.js not copied in builder stage - Update README: pnpm instead of yarn, correct ports, full env vars documentation Co-Authored-By: Claude Sonnet 4.6 --- Dockerfile | 23 +++--- README.md | 33 ++++---- docker-entrypoint.sh | 10 +-- next.config.js | 1 + .../20260311203728_init/migration.sql | 77 +++++++++++++++++++ prisma/migrations/migration_lock.toml | 3 + 6 files changed, 114 insertions(+), 33 deletions(-) create mode 100644 prisma/migrations/20260311203728_init/migration.sql create mode 100644 prisma/migrations/migration_lock.toml diff --git a/Dockerfile b/Dockerfile index 8d84aad..8b29076 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ COPY package.json pnpm-lock.yaml ./ COPY prisma ./prisma # Copy configuration files -COPY tsconfig.json .eslintrc.json ./ +COPY tsconfig.json .eslintrc.json next.config.js ./ COPY tailwind.config.ts postcss.config.js ./ # Install dependencies with pnpm using cache mount for store @@ -43,22 +43,20 @@ WORKDIR /app # Install OpenSSL (required by Prisma) RUN apk add --no-cache openssl libc6-compat -# Copy package files and prisma schema -COPY package.json pnpm-lock.yaml ./ -COPY prisma ./prisma +# Copy standalone output (server.js + minimal node_modules) +COPY --from=builder /app/.next/standalone ./ -# Enable pnpm -RUN corepack enable && corepack prepare pnpm@9.0.0 --activate +# Copy static assets and public directory +COPY --from=builder /app/.next/static ./.next/static +COPY --from=builder /app/public ./public -# Copy the entire node_modules from builder (includes Prisma Client) +# Copy full node_modules for Prisma CLI (pnpm symlinks prevent cherry-picking) COPY --from=builder /app/node_modules ./node_modules -# Copy built application from builder stage -COPY --from=builder /app/.next ./.next -COPY --from=builder /app/public ./public -COPY --from=builder /app/next-env.d.ts ./ -COPY --from=builder /app/tailwind.config.ts ./ +# Copy prisma schema and init scripts +COPY prisma ./prisma COPY --from=builder /app/scripts ./scripts +COPY package.json ./ # Copy entrypoint script COPY docker-entrypoint.sh ./ @@ -76,6 +74,7 @@ USER nextjs # Set environment variables ENV NODE_ENV=production ENV NEXT_TELEMETRY_DISABLED=1 +ENV HOSTNAME="0.0.0.0" # Expose the port the app runs on EXPOSE 3000 diff --git a/README.md b/README.md index 0daa051..6a694ec 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ A modern web application for reading digital comics, built with Next.js 14 and t ## 🛠 Prerequisites - Node.js 20.x or higher -- Yarn 1.22.x or higher +- pnpm 9.x or higher - Docker and Docker Compose (optional) ## 📦 Installation @@ -91,7 +91,7 @@ cd stripstream 2. Install dependencies ```bash -yarn install +pnpm install ``` 3. Copy the example environment file and adjust it to your needs @@ -103,7 +103,7 @@ cp .env.example .env.local 4. Start the development server ```bash -yarn dev +pnpm dev ``` ### With Docker (Build Local) @@ -121,7 +121,7 @@ cd stripstream docker-compose up --build ``` -The application will be accessible at `http://localhost:3000` +The application will be accessible at `http://localhost:3020` ### With Docker (DockerHub Image) @@ -130,18 +130,24 @@ You can also use the pre-built image from DockerHub without cloning the reposito 1. Create a `docker-compose.yml` file: ```yaml -version: '3.8' - services: app: image: julienfroidefond32/stripstream:latest ports: - "3000:3000" environment: - - NODE_ENV=production - # Add your environment variables here or use an .env file + # Required + - NEXTAUTH_SECRET=your_secret_here # openssl rand -base64 32 + - NEXTAUTH_URL=http://localhost:3000 + + # Optional — defaults shown + # - NODE_ENV=production + # - DATABASE_URL=file:/app/prisma/data/stripstream.db + # - ADMIN_DEFAULT_PASSWORD=Admin@2025 + # - AUTH_TRUST_HOST=true + # - KOMGA_MAX_CONCURRENT_REQUESTS=5 volumes: - - ./data:/app/data + - ./data:/app/prisma/data restart: unless-stopped ``` @@ -155,11 +161,10 @@ The application will be accessible at `http://localhost:3000` ## 🔧 Available Scripts -- `yarn dev` - Starts the development server -- `yarn build` - Creates a production build -- `yarn start` - Runs the production version -- `yarn lint` - Checks code with ESLint -- `yarn format` - Formats code with Prettier +- `pnpm dev` - Starts the development server +- `pnpm build` - Creates a production build +- `pnpm start` - Runs the production version +- `pnpm lint` - Checks code with ESLint - `./docker-push.sh [tag]` - Build and push Docker image to DockerHub (default tag: `latest`) ### Docker Push Script diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 4a0ce90..40407b7 100644 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,15 +1,11 @@ #!/bin/sh set -e -echo "📁 Ensuring data directory exists..." -mkdir -p /app/data - -echo "🔄 Pushing Prisma schema to database..." -npx prisma db push --skip-generate --accept-data-loss +echo "🔄 Applying database migrations..." +./node_modules/.bin/prisma migrate deploy echo "🔧 Initializing database..." node scripts/init-db.mjs echo "🚀 Starting application..." -exec pnpm start - +exec node server.js diff --git a/next.config.js b/next.config.js index 76935c9..0280a9d 100644 --- a/next.config.js +++ b/next.config.js @@ -1,5 +1,6 @@ /** @type {import('next').NextConfig} */ const nextConfig = { + output: "standalone", webpack: (config) => { config.resolve.fallback = { ...config.resolve.fallback, diff --git a/prisma/migrations/20260311203728_init/migration.sql b/prisma/migrations/20260311203728_init/migration.sql new file mode 100644 index 0000000..16bab7b --- /dev/null +++ b/prisma/migrations/20260311203728_init/migration.sql @@ -0,0 +1,77 @@ +-- CreateTable +CREATE TABLE "users" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "email" TEXT NOT NULL, + "password" TEXT NOT NULL, + "roles" JSONB NOT NULL DEFAULT ["ROLE_USER"], + "authenticated" BOOLEAN NOT NULL DEFAULT true, + "activeProvider" TEXT, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); + +-- CreateTable +CREATE TABLE "komgaconfigs" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "userId" INTEGER NOT NULL, + "url" TEXT NOT NULL, + "username" TEXT NOT NULL, + "authHeader" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "komgaconfigs_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "stripstreamconfigs" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "userId" INTEGER NOT NULL, + "url" TEXT NOT NULL, + "token" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "stripstreamconfigs_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "preferences" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "userId" INTEGER NOT NULL, + "showThumbnails" BOOLEAN NOT NULL DEFAULT true, + "showOnlyUnread" BOOLEAN NOT NULL DEFAULT false, + "displayMode" JSONB NOT NULL, + "background" JSONB NOT NULL, + "readerPrefetchCount" INTEGER NOT NULL DEFAULT 5, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "preferences_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "favorites" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "userId" INTEGER NOT NULL, + "seriesId" TEXT NOT NULL, + "provider" TEXT NOT NULL DEFAULT 'komga', + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL, + CONSTRAINT "favorites_userId_fkey" FOREIGN KEY ("userId") REFERENCES "users" ("id") ON DELETE CASCADE ON UPDATE CASCADE +); + +-- CreateIndex +CREATE UNIQUE INDEX "users_email_key" ON "users"("email"); + +-- CreateIndex +CREATE UNIQUE INDEX "komgaconfigs_userId_key" ON "komgaconfigs"("userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "stripstreamconfigs_userId_key" ON "stripstreamconfigs"("userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "preferences_userId_key" ON "preferences"("userId"); + +-- CreateIndex +CREATE INDEX "favorites_userId_idx" ON "favorites"("userId"); + +-- CreateIndex +CREATE UNIQUE INDEX "favorites_userId_provider_seriesId_key" ON "favorites"("userId", "provider", "seriesId"); diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..2a5a444 --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "sqlite"