# ---- Build stage ---- FROM node:22-alpine AS build WORKDIR /app # Safety valve for the 2 GB host: without a cap a runaway build can exhaust the # server's RAM and take down neighbouring containers. Measured peak for this app # is ~550 MB, so 1 GB leaves headroom while still failing the build rather than # the server. Raise this only if the host gets more RAM. ENV NODE_OPTIONS=--max-old-space-size=1024 # Vite inlines VITE_* vars into the bundle at build time, so these have to be # present here — setting them as runtime env vars in Dokploy does nothing, the # JS is already compiled by then. .env.* is gitignored, so a build from the repo # has no other source for them: without these the app boots with a null app id, # every API call resolves against our own origin, nginx answers with index.html # and the browser shows a blank page. Defaults match this app so a plain # `docker build` works; override via Dokploy's build args to point elsewhere. ARG VITE_BASE44_APP_ID=68fc6cf01386035c266e7a5d ARG VITE_BASE44_BACKEND_URL=https://base44.app ENV VITE_BASE44_APP_ID=$VITE_BASE44_APP_ID ENV VITE_BASE44_BACKEND_URL=$VITE_BASE44_BACKEND_URL # Install deps from the lockfile first so this layer is reused when only src changes COPY package.json package-lock.json ./ RUN npm ci --no-audit --no-fund COPY . . # Fail loudly here rather than shipping an image that serves an empty page. RUN test -n "$VITE_BASE44_APP_ID" || (echo "VITE_BASE44_APP_ID is empty — the build would produce a blank app" && exit 1) RUN npm run build # The build is only useful if it actually emitted an entry point. RUN test -f dist/index.html || (echo "vite build produced no dist/index.html" && exit 1) # ---- Runtime stage ---- FROM nginx:alpine # Remove Nginx's default "Welcome" page files completely RUN rm -rf /usr/share/nginx/html/* # Only the compiled assets reach the final image — no node_modules, no source COPY --from=build /app/dist /usr/share/nginx/html COPY nginx.conf /etc/nginx/nginx.conf # Catch a broken config at build time instead of at container start, where # Dokploy would report the deploy as successful and then serve nothing. RUN nginx -t EXPOSE 80 3000 # Gives Dokploy a real signal that the container is serving, not just running. HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget -q --spider http://127.0.0.1/health || exit 1 CMD ["nginx", "-g", "daemon off;"]