# Build stage FROM node:26-alpine AS builder WORKDIR /app COPY package.json package-lock.json* ./ RUN npm install COPY . . # Baked in at build time. DOCS_BASE_URL must agree with three things at once: # the Nginx Proxy Manager location that routes to this container, the directory # the runtime stage serves from below, and this value. When they disagree the # HTML loads and every stylesheet and script 404s. ARG DOCS_URL="https://vantage.hostxtra.co.uk" ARG DOCS_BASE_URL="/docs/" ARG APP_URL="https://vantage.hostxtra.co.uk" ARG HQ_URL="https://vantage-hq.hostxtra.co.uk" ENV DOCS_URL=$DOCS_URL ENV DOCS_BASE_URL=$DOCS_BASE_URL ENV APP_URL=$APP_URL ENV HQ_URL=$HQ_URL RUN npm run build # Runtime stage # # Docusaurus emits a fully static site, so unlike web/, site/ and adminsite/ # there is no Node server at runtime. alpine-slim is roughly a quarter the size # of caddy:alpine, and nothing here needs automatic TLS — the host proxy # terminates it. FROM nginx:alpine-slim AS runner # NPM forwards the FULL request path upstream; it does not strip the /docs # prefix. Serving from a matching subdirectory means prefix, asset URLs and # upstream paths agree with no rewrite rule to keep in step. COPY --from=builder /app/build /usr/share/nginx/html/docs COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80