# syntax=docker/dockerfile:1 # ---- Stage 1: build the static bundle ---- FROM node:22-alpine AS build WORKDIR /app # Deps from the lockfile first, so this layer survives source-only edits. COPY package.json package-lock.json ./ RUN npm ci COPY . . # Build against a placeholder base. The entrypoint swaps it for $BASE_URL at startup, # so one image can be served from any path without rebuilding. RUN npm run build -- --base=/__R2B_BASE__/ # ---- Stage 2: serve it ---- # Ready2Blob is entirely client-side, so the runtime image is just nginx + dist/. FROM nginx:alpine AS runtime # Pristine copy; the entrypoint stages it into the web root on each start. COPY --from=build /app/dist /opt/ready2blob/html COPY docker/security-headers.conf /etc/nginx/snippets/security-headers.conf COPY docker/nginx.conf.template /etc/nginx/ready2blob.conf.template COPY docker/40-ready2blob-base-url.sh /docker-entrypoint.d/40-ready2blob-base-url.sh RUN chmod +x /docker-entrypoint.d/40-ready2blob-base-url.sh # Path the app is served from. "/" for a dedicated (sub)domain, "/ready2blob/" when # mounted under a path on a shared host. ENV BASE_URL=/ EXPOSE 80 HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \ CMD wget -q --spider http://localhost/ || exit 1