FROM node:24-bookworm AS desktop-build WORKDIR /workspace RUN apt-get update \ && apt-get install -y --no-install-recommends \ build-essential \ clang \ curl \ file \ libayatana-appindicator3-dev \ libssl-dev \ libwebkit2gtk-4.1-dev \ libxdo-dev \ lld \ llvm \ nsis \ patchelf \ pkg-config \ librsvg2-dev \ wget \ && rm -rf /var/lib/apt/lists/* RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \ | sh -s -- -y --profile minimal ENV PATH="/root/.cargo/bin:$PATH" RUN rustup target add x86_64-pc-windows-msvc \ && cargo install --locked cargo-xwin COPY package.json ./ COPY apps/api/package.json apps/api/package.json COPY apps/web/package.json apps/web/package.json COPY apps/print/package.json apps/print/package.json COPY packages/contracts/package.json packages/contracts/package.json COPY packages/fieldlens-core/package.json packages/fieldlens-core/package.json RUN npm install COPY apps/print apps/print RUN npm run bundle:windows --workspace @fieldlens/print \ && npm run bundle:deb --workspace @fieldlens/print \ && mkdir -p /desktop-artifacts \ && windows_file="$(find apps/print/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis -maxdepth 1 -type f -name '*-setup.exe' -print -quit)" \ && linux_file="$(find apps/print/src-tauri/target/release/bundle/deb -maxdepth 1 -type f -name '*.deb' -print -quit)" \ && test -n "$windows_file" \ && test -n "$linux_file" \ && cp "$windows_file" /desktop-artifacts/fieldlens-print-windows-x64-setup.exe \ && cp "$linux_file" /desktop-artifacts/fieldlens-print-linux-x64.deb FROM node:24-alpine AS build WORKDIR /workspace ARG VITE_API_BASE_URL="" ARG VITE_KEYCLOAK_ISSUER="" ARG VITE_KEYCLOAK_CLIENT_ID="fieldlens" ARG VITE_APP_RELEASE="0.1.0" ARG FIELDLENS_VERSION="dev" ENV VITE_API_BASE_URL=$VITE_API_BASE_URL ENV VITE_KEYCLOAK_ISSUER=$VITE_KEYCLOAK_ISSUER ENV VITE_KEYCLOAK_CLIENT_ID=$VITE_KEYCLOAK_CLIENT_ID ENV VITE_APP_RELEASE=$VITE_APP_RELEASE ENV VITE_APP_VERSION=$FIELDLENS_VERSION COPY package.json ./ COPY apps/api/package.json apps/api/package.json COPY apps/web/package.json apps/web/package.json COPY packages/contracts/package.json packages/contracts/package.json COPY packages/fieldlens-core/package.json packages/fieldlens-core/package.json RUN npm install COPY . . RUN npm run verify RUN npm prune --omit=dev FROM node:24-alpine AS runtime WORKDIR /app ENV NODE_ENV=production ENV PORT=3000 ENV STATIC_DIR=/app/web ENV FIELDLENS_PRINT_DOWNLOAD_DIR=/app/downloads COPY --from=build /workspace/package.json /app/package.json COPY --from=build /workspace/node_modules /app/node_modules COPY --from=build /workspace/apps/api/package.json /app/apps/api/package.json COPY --from=build /workspace/apps/api/dist /app/apps/api/dist COPY --from=build /workspace/migrations /app/migrations COPY --from=build /workspace/packages/contracts/package.json /app/packages/contracts/package.json COPY --from=build /workspace/packages/contracts/dist /app/packages/contracts/dist COPY --from=build /workspace/apps/web/dist /app/web COPY --from=desktop-build /desktop-artifacts /app/downloads USER node EXPOSE 3000 HEALTHCHECK --interval=15s --timeout=3s --start-period=20s --retries=5 \ CMD wget -qO- http://127.0.0.1:3000/api/health/live >/dev/null || exit 1 CMD ["node", "apps/api/dist/server.js"]