# Dockerfile Generation Generate Dockerfiles for components targeting Container Apps (or B1+ App Service) that have no existing Dockerfile. Read this when `iac-generation-rules.md` Step 6b applies. ## When to Generate - Component targets Container Apps and has NO Dockerfile (and no `Dockerfile.azure`) - Component targets App Service B1+ with `deployStrategy.containerized: true` - ⛔ Do NOT generate for F1/D1 SKUs — use platform runtime stack instead - ⛔ Do NOT overwrite an existing Dockerfile — create `Dockerfile.azure` only if BuildKit stripping is needed ## Principles ### Layer ordering Copy dependency manifests and install BEFORE copying source (preserves layer cache): ``` COPY {manifest files} ./ RUN {install command} COPY . . ``` ### Base image selection | Principle | Rule | |-----------|------| | Pin version | `node:{major}-slim`, NOT `node:latest` | | Slim variants | `-slim` or `-alpine` for smaller images | | Multi-stage | Go, .NET, Java, Rust: build in SDK image, copy binary to runtime | | Match runtime | Read `engines`, `python_requires`, `go.mod`, `` | ### Port alignment `EXPOSE` port, app's listening port, and Container App `targetPort` must all match. Mismatch = silent health probe failure. Read app config for listening port, set `EXPOSE {port}`, add `ENV PORT={port}` if app reads `PORT` from env. ### Security defaults - Non-root user — Debian/`-slim` base: `RUN groupadd -r app && useradd -r -g app app`; Alpine base: `RUN addgroup -S app && adduser -S app -G app`. Then `USER app` - Never `COPY .env` or secrets — use `.dockerignore` - Direct exec: `CMD ["node", "server.js"]` not `CMD ["npm", "start"]` ### .dockerignore Always generate alongside Dockerfile. Exclude: `.git`, `node_modules`, `__pycache__`, `*.pyc`, `.env`, `.env.*`, `.azure`, `.copilot-azure`, `infra`, `*.md`. ### Common pitfalls | Mistake | Fix | |---------|-----| | `COPY . .` before deps | Copy manifests first, install, then source | | `npm install` in prod | `npm ci --omit=dev` | | Wrong EXPOSE port | Read actual listening port from app source | ### Next.js multi-container build args `NEXT_PUBLIC_*` env vars are embedded in the client JS bundle at `npm run build` time — runtime Container App env vars have zero effect on client-side code. For multi-container deploys where a Next.js frontend references another component's API: 1. Dockerfile MUST include `ARG NEXT_PUBLIC_API_URL` before the `RUN npm run build` step 2. Deploy phase passes `--build-arg NEXT_PUBLIC_API_URL=https://{api-fqdn}` to `az acr build` Detect from `.env*` files containing `NEXT_PUBLIC_*` pointing to another service (e.g., `NEXT_PUBLIC_API_URL=http://localhost:3001`). ### ACR Build Compatibility — `Dockerfile.azure` Generation ⛔ ACR `az acr build` uses the **classic Docker builder — NOT BuildKit**. Do NOT assume ACR supports BuildKit. **When to generate `Dockerfile.azure`:** If `buildRequirements.hasBuildKitSyntax == true` OR the existing Dockerfile contains any BuildKit-only syntax, create `{component}/Dockerfile.azure` with all BuildKit syntax removed. **BuildKit-only syntax** (strip all): `# syntax=` directives, `RUN --mount=...` (all types: cache, secret, bind, tmpfs), `RUN --network=...`, `RUN --security=...`, `COPY --link`, `COPY --chmod=...`, heredoc syntax (`RUN <