diff --git a/.dockerignore b/.dockerignore index 0949f4b..b4ad3eb 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,8 +1,21 @@ +.git .github +.gitea +.next +.pnpm-store +.vercel +**/.next +**/.turbo +**/dist +**/node_modules CODE_OF_CONDUCT.md CONTRIBUTING.md +Dockerfile LICENSE README.md docker-compose.yml -Dockerfile -LICENSE +logs +*.log +*.local +.env +.env.* diff --git a/Dockerfile b/Dockerfile index 52b3887..a3fc31d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,4 @@ -FROM node:lts-bookworm-slim - -# Install git and stockfish (native binary) -RUN apt-get update && apt-get install -y --no-install-recommends git stockfish && rm -rf /var/lib/apt/lists/* +FROM node:lts-bookworm-slim AS build ENV PNPM_HOME=/usr/local/bin @@ -9,21 +6,46 @@ WORKDIR /opt/michess/ COPY . . -RUN corepack enable && \ - corepack prepare pnpm@9.15.9 --activate && \ - pnpm config set store-dir /opt/michess/.pnpm-store && \ - pnpm install --no-frozen-lockfile - -# Build-time env vars for Next.js (baked into the frontend bundle) ARG NEXT_PUBLIC_API_URL=http://localhost:3001 ARG NEXT_PUBLIC_APP_URL=http://localhost:3000 ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URL -# Build server and client -RUN pnpm build:server && pnpm build:client +RUN corepack enable && \ + corepack prepare pnpm@9.15.9 --activate && \ + pnpm config set store-dir /opt/michess/.pnpm-store && \ + pnpm install --no-frozen-lockfile && \ + pnpm build:server && \ + pnpm build:client && \ + rm -rf node_modules client/node_modules server/node_modules types/node_modules && \ + pnpm install --prod --no-frozen-lockfile && \ + pnpm store prune && \ + rm -rf \ + /opt/michess/.pnpm-store \ + /root/.cache \ + /tmp/* \ + client/.next/cache \ + client/src \ + server/src \ + .git \ + .github \ + .gitea + +FROM node:lts-bookworm-slim + +RUN apt-get update && \ + apt-get install -y --no-install-recommends stockfish && \ + rm -rf /var/lib/apt/lists/* + +ENV NODE_ENV=production +ENV PNPM_HOME=/usr/local/bin + +WORKDIR /opt/michess/ + +COPY --from=build /opt/michess/ ./ + +RUN corepack enable && corepack prepare pnpm@9.15.9 --activate EXPOSE 3000 3001 -ENTRYPOINT ["pnpm"] -CMD ["start"] +CMD ["node", "scripts/start-production.mjs"] diff --git a/scripts/start-production.mjs b/scripts/start-production.mjs new file mode 100644 index 0000000..ea8bce5 --- /dev/null +++ b/scripts/start-production.mjs @@ -0,0 +1,33 @@ +import { spawn } from "node:child_process"; + +const processes = [ + spawn("node", ["server/dist/server.js"], { stdio: "inherit" }), + spawn("pnpm", ["--filter", "client", "start"], { stdio: "inherit" }) +]; + +let stopping = false; + +function stopAll(signal = "SIGTERM") { + stopping = true; + for (const child of processes) { + if (!child.killed) { + child.kill(signal); + } + } +} + +for (const signal of ["SIGINT", "SIGTERM"]) { + process.on(signal, () => { + stopAll(signal); + }); +} + +for (const child of processes) { + child.on("exit", (code, signal) => { + if (stopping) return; + + stopping = true; + stopAll(); + process.exit(code ?? (signal ? 1 : 0)); + }); +}