FROM node:25-alpine AS builder RUN npm install -g pnpm@10 WORKDIR /app COPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile COPY . . # PUBLIC_API_BASE_URL is baked at build time if using $env/static/public. # If using $env/dynamic/public, remove the ARG/ENV below and pass it at runtime. ARG PUBLIC_API_BASE_URL=https://api.marktvogt.de ENV PUBLIC_API_BASE_URL=$PUBLIC_API_BASE_URL ARG PUBLIC_TURNSTILE_SITE_KEY=1x00000000000000000000AA ENV PUBLIC_TURNSTILE_SITE_KEY=$PUBLIC_TURNSTILE_SITE_KEY RUN pnpm run build && pnpm run bundle # ───────────────────────────────────────────── # Bun runtime as drop-in Node replacement. # bundle.mjs is platform-targeted ESM using stdlib node:* APIs that Bun # implements at parity for SSR-typical paths. ~50 MB smaller than the # previous alpine + node-binary copy. # alpine variant (not distroless) so `nobody` 65534 matches podSecurityContext. FROM oven/bun:1-alpine WORKDIR /app COPY --from=builder /app/build/bundle.mjs ./bundle.mjs COPY --from=builder /app/build/client ./client USER nobody:nobody ENV PORT=3000 HOST=0.0.0.0 NODE_ENV=production EXPOSE 3000 CMD ["bun", "bundle.mjs"]