# mcaxl docs — multi-stage build. # # Stages: # deps — install node_modules once, cached by package.json # dev — runs `astro dev` with the source bind-mounted (compose `dev` profile) # build — produces the static site in /app/dist # prod — serves /app/dist with Caddy (static file server, no Node runtime) # ---------- Stage: deps -------------------------------------------------- FROM mirror.gcr.io/library/node:22-alpine AS deps ENV ASTRO_TELEMETRY_DISABLED=1 \ NODE_ENV=development WORKDIR /app COPY package.json package-lock.json* ./ RUN --mount=type=cache,target=/root/.npm \ npm install --no-audit --no-fund # ---------- Stage: dev --------------------------------------------------- FROM mirror.gcr.io/library/node:22-alpine AS dev ENV ASTRO_TELEMETRY_DISABLED=1 \ NODE_ENV=development \ HOST=0.0.0.0 WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . EXPOSE 4321 CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] # ---------- Stage: build ------------------------------------------------- FROM mirror.gcr.io/library/node:22-alpine AS build ENV ASTRO_TELEMETRY_DISABLED=1 \ NODE_ENV=production WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . # DOMAIN must be set at build time so Astro bakes the canonical site URL # (sitemaps, og: tags, etc.) into the static output. ARG DOMAIN ENV DOMAIN=${DOMAIN} RUN npm run build # ---------- Stage: prod -------------------------------------------------- # Static site served by Caddy. No Node in the final image. FROM mirror.gcr.io/library/caddy:2-alpine AS prod COPY --from=build /app/dist /srv COPY Caddyfile /etc/caddy/Caddyfile EXPOSE 80 CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]