# ========================================================================= # Multi-stage Production Dockerfile for TautKan (Coolify / Docker Deployment) # Supports BOTH standalone SQLite (No DB service needed) AND PostgreSQL # ========================================================================= # Stage 1: Build Frontend (React + Vite + Tailwind) FROM node:20-alpine AS client-builder WORKDIR /app/client # Ensure development environment during build stage so devDependencies (tsc, vite) are always installed ENV NODE_ENV=development COPY client/package*.json ./ RUN npm ci --no-audit --no-fund --include=dev COPY client/ ./ RUN chmod -R 755 node_modules/.bin || true RUN npm run build # Stage 2: Build Backend (TypeScript + Express + Prisma) FROM node:20-alpine AS server-builder WORKDIR /app/server ENV NODE_ENV=development COPY server/package*.json ./ COPY server/prisma ./prisma/ RUN npm ci --no-audit --no-fund --include=dev RUN npx prisma generate --schema=prisma/schema.sqlite.prisma COPY server/ ./ RUN chmod -R 755 node_modules/.bin || true RUN npx tsc # Stage 3: Production Runner Image FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production ENV PORT=4000 # Install OpenSSL for Prisma engine in Alpine RUN apk add --no-cache openssl libc6-compat wget # Copy server package and install production dependencies only COPY server/package*.json ./ COPY server/prisma ./prisma/ RUN npm ci --only=production --no-audit --no-fund # Copy built server from server-builder COPY --from=server-builder /app/server/dist ./dist # Copy built client static assets to public directory COPY --from=client-builder /app/client/dist ./public # Copy entrypoint script COPY server/entrypoint.sh ./entrypoint.sh RUN chmod +x ./entrypoint.sh # Create persistent storage folder for SQLite RUN mkdir -p /app/data EXPOSE 4000 # Health check HEALTHCHECK --interval=30s --timeout=5s --start-period=5s --retries=3 \ CMD wget --no-verbose --tries=1 --spider http://localhost:4000/health || exit 1 # Start container via entrypoint (auto-detects PostgreSQL vs SQLite) ENTRYPOINT ["./entrypoint.sh"]