# syntax=docker/dockerfile:1 # ── Dependencies ────────────────────────────────────────────── FROM node:22-bookworm-slim AS deps WORKDIR /app COPY package.json package-lock.json* ./ COPY client/package.json ./client/ COPY server/package.json ./server/ RUN npm ci 2>/dev/null || npm install # ── Build client ────────────────────────────────────────────── FROM deps AS client-build COPY client ./client RUN npm run build -w client # ── Build server ────────────────────────────────────────────── FROM deps AS server-build COPY server ./server WORKDIR /app/server RUN npx prisma generate RUN npm run build # ── Runtime ─────────────────────────────────────────────────── FROM node:22-bookworm-slim AS runtime RUN apt-get update && apt-get install -y --no-install-recommends \ chromium \ ca-certificates \ fonts-liberation \ fonts-dejavu-core \ && rm -rf /var/lib/apt/lists/* ENV NODE_ENV=production \ PORT=3000 \ HOST=0.0.0.0 \ PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium \ PUPPETEER_SKIP_DOWNLOAD=true \ CLIENT_DIST=/app/public \ PUBLIC_DIR=/app/public \ UPLOAD_DIR=/app/data/uploads WORKDIR /app COPY package.json package-lock.json* ./ COPY server/package.json ./server/ COPY client/package.json ./client/ RUN npm ci --omit=dev 2>/dev/null || npm install --omit=dev COPY --from=server-build /app/server/dist ./server/dist COPY --from=server-build /app/server/prisma ./server/prisma COPY --from=server-build /app/node_modules/.prisma ./node_modules/.prisma COPY --from=server-build /app/node_modules/@prisma ./node_modules/@prisma COPY --from=client-build /app/client/dist ./public COPY public/.well-known ./public/.well-known # ArtStation import tooling (tsx available via optional reinstall of dev deps on demand) COPY server/scripts ./server/scripts COPY server/src ./server/src COPY server/tsconfig.json ./server/tsconfig.json COPY server/package.json ./server/package.json RUN mkdir -p /app/data/uploads/originals /app/data/uploads/thumbs /app/data/uploads/videos \ && cd /app/server && npx prisma generate WORKDIR /app/server EXPOSE 3000 HEALTHCHECK --interval=30s --timeout=5s --start-period=60s --retries=3 \ CMD node -e "fetch('http://127.0.0.1:3000/api/v1/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))" CMD ["node", "dist/index.js"]