From 8d76c4d797b829171207d02f1cfa0b5f0af56ed7 Mon Sep 17 00:00:00 2001 From: Oleg Date: Thu, 27 Aug 2026 11:03:56 +0000 Subject: [PATCH] Add Docker Compose deployment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Full node_modules image (not output: standalone — its file-tracing drops argon2's JS loader and segfaults in prod). drizzle.config.ts now honors DATA_DIR like the sibling projects, so db:migrate targets the mounted volume instead of an image-local path. --- .dockerignore | 7 +++++++ Dockerfile | 31 +++++++++++++++++++++++++++++++ docker-compose.yml | 18 ++++++++++++++++++ drizzle.config.ts | 5 ++++- 4 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..56fdd3c --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +node_modules +.next +.git +data +*.env +!.env.example +*.tsbuildinfo diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4e905d5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +FROM node:20-bookworm-slim + +# python3/make/g++ let npm fall back to compiling better-sqlite3/argon2 from +# source if no prebuilt binary matches this platform. +RUN apt-get update && apt-get install -y --no-install-recommends \ + python3 make g++ ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app + +COPY package.json package-lock.json* ./ +RUN npm install + +COPY . . + +# next.config.ts: not using output: "standalone" — its file-tracing only +# copies argon2's native .node binaries, not its JS loader, which segfaults +# in production. Deploying against the full node_modules via `next start` +# (this whole image, no standalone pruning) avoids that. +# +# `next build`'s page-data collection spins up parallel workers that each +# import the db client at module-eval time. If data/db.sqlite doesn't exist +# yet, every worker races to create it from scratch, which can throw +# SQLITE_BUSY. Migrating first, as its own isolated step, avoids the race. +RUN mkdir -p data && npm run db:migrate +RUN npm run build + +ENV NODE_ENV=production +EXPOSE 8180 + +CMD ["sh", "-c", "npm run db:migrate && npm start"] diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..27b174a --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,18 @@ +name: project-claude + +services: + app: + build: . + ports: + - "8180:8180" + env_file: + - .env + environment: + - PORT=8180 + - DATA_DIR=/data + volumes: + - data:/data + restart: unless-stopped + +volumes: + data: diff --git a/drizzle.config.ts b/drizzle.config.ts index 7fa0609..bdc439e 100644 --- a/drizzle.config.ts +++ b/drizzle.config.ts @@ -1,10 +1,13 @@ import { defineConfig } from "drizzle-kit"; +import path from "node:path"; + +const dataDir = process.env.DATA_DIR ?? path.join(process.cwd(), "data"); export default defineConfig({ out: "./src/lib/db/migrations", schema: "./src/lib/db/schema.ts", dialect: "sqlite", dbCredentials: { - url: "./data/db.sqlite", + url: path.join(dataDir, "db.sqlite"), }, });