FROM node:20-alpine WORKDIR /app # Install build tools + OpenSSL (required by Prisma query engine on Alpine) RUN apk add --no-cache python3 make g++ openssl openssl-dev # Configure npm: disable package-lock update, cap network retries/timeout RUN npm config set fetch-retry-mintimeout 5000 \ && npm config set fetch-retry-maxtimeout 30000 \ && npm config set fetch-retries 3 \ && npm config set prefer-offline false # Copy lockfiles + manifests together so npm ci can validate the lockfile COPY package.json package-lock.json ./ COPY client/package.json client/package-lock.json ./client/ # Use npm ci (lockfile-exact, no resolution step, much faster than npm install) RUN npm ci RUN cd client && npm ci # Copy source COPY . . # Generate Prisma client for target platform (must happen before tsc) RUN npx prisma generate # Build server (tsc) + client (vite) RUN npm run build # Ensure data directory exists for SQLite bind mount RUN mkdir -p /app/data # Copy and make entrypoint executable COPY docker-entrypoint.sh /app/docker-entrypoint.sh RUN chmod +x /app/docker-entrypoint.sh EXPOSE 3001 ENTRYPOINT ["/app/docker-entrypoint.sh"]