[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-azure-generate-dockerfile":3,"mdc-y4z3gg-key":34,"related-repo-azure-generate-dockerfile":6169,"related-org-azure-generate-dockerfile":6207},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":24,"repoUrl":25,"updatedAt":26,"license":27,"forks":28,"topics":29,"repo":30,"sourceUrl":32,"mdContent":33},"generate-dockerfile","generate and optimize Dockerfiles","Generate or enhance a Dockerfile for a containerized application using curated base-image recommendations and security best practices. Use AFTER analyze-repo (or after the user has told you the language\u002Fframework). Triggers include \"generate a Dockerfile\", \"containerize this\", \"write Dockerfile for X\", or when running aks-loop and no Dockerfile yet exists. If a Dockerfile already exists, this skill enhances it in place.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"azure","Azure (Microsoft)","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fazure.png","Azure",[13,17,18,21],{"name":14,"slug":15,"type":16},"Security","security","tag",{"name":11,"slug":8,"type":16},{"name":19,"slug":20,"type":16},"Containers","containers",{"name":22,"slug":23,"type":16},"Docker","docker",41,"https:\u002F\u002Fgithub.com\u002FAzure\u002Fcontainerization-assist","2026-07-19T05:40:02.706462",null,16,[],{"repoUrl":25,"stars":24,"forks":28,"topics":31,"description":27},[],"https:\u002F\u002Fgithub.com\u002FAzure\u002Fcontainerization-assist\u002Ftree\u002FHEAD\u002Fskills\u002Fgenerate-dockerfile","---\nname: generate-dockerfile\ndescription: Generate or enhance a Dockerfile for a containerized application using curated base-image recommendations and security best practices. Use AFTER analyze-repo (or after the user has told you the language\u002Fframework). Triggers include \"generate a Dockerfile\", \"containerize this\", \"write Dockerfile for X\", or when running aks-loop and no Dockerfile yet exists. If a Dockerfile already exists, this skill enhances it in place.\nargument-hint: \u003CmodulePath> \u003Clanguage> [framework] [environment=production|development]\n---\n\n# Generate Dockerfile\n\nProduce a production-quality, secure Dockerfile (or enhancement plan for an\nexisting one) for a single module. The output is a complete Dockerfile that\nthe user can write to disk — not a description of one.\n\n## Inputs\n\n| Field | Required | Description |\n|---|---|---|\n| `modulePath` | yes | Absolute path of the module to containerize (one of the modules from `analyze-repo`). |\n| `language` | yes | `java` \\| `dotnet` \\| `javascript` \\| `typescript` \\| `python` \\| `go` \\| `rust` \\| `php` \\| `ruby`. |\n| `languageVersion` | recommended | E.g. `21`, `8.0`, `20`, `3.11`. Substituted into the base image tag. |\n| `framework` | optional | E.g. `spring-boot`, `express`, `next`, `django`, `flask`, `asp.net-core`, `gin`. |\n| `environment` | optional | `production` (default) or `development`. |\n| `targetPlatform` | optional | `linux\u002Famd64` (default) or `linux\u002Farm64`. |\n| `detectedDependencies` | optional | Used to choose extra apt\u002Fapk packages (e.g. native modules). |\n| `detectedEnvVars` | optional | List from `analyze-repo`. Used to add `ENV` instructions for `config`\u002F`database` vars and to WARN about `secret`-classified ones (never bake secrets in). |\n| `existingDockerfile` | optional | If a Dockerfile is already at `\u003CmodulePath>\u002FDockerfile`, read its content and follow the **Enhancement path** instead of the **Generation path**. |\n\n## Prerequisite: analyze-repo\n\nThis skill needs `language`, `framework`, `detectedDependencies`, and\n`detectedEnvVars` from the `analyze-repo` skill. If you don't already\nhave that output for `\u003CmodulePath>` from earlier in this conversation,\nfollow the `analyze-repo` skill against `\u003CmodulePath>` first, then come\nback.\n\n## Decision: generate or enhance?\n\n1. Check if `\u003CmodulePath>\u002FDockerfile` exists.\n2. If **no** → Generation path (Step G1–G4 below).\n3. If **yes** → read the file, run **Dockerfile analysis** (Step E1), then\n   Enhancement path (Step E2–E4).\n\n---\n\n## Generation path\n\n### G1 — Choose build strategy\n\nUse **multi-stage** if any of these:\n\n- `language` ∈ {`java`, `go`, `rust`, `dotnet`}\n- `language` is `typescript` AND build output is required (`tsc`, `next build`, `vite build`, etc.)\n- `buildSystem.type` ∈ {`maven`, `gradle`}\n\nOtherwise use **single-stage**.\n\nThe reason this matters: multi-stage drops compilers, SDKs, and source code\nfrom the final image — typically 70–90% smaller and a smaller attack surface.\n\n### G2 — Choose the base image(s)\n\n**Hard rule: every `FROM` line MUST start with `mcr.microsoft.com\u002F` unless\nthe stack appears in the explicit non-MCR list (G2.3) below.**\n\nThe Dockerfile is the contract for an Azure-hosted image. Public-registry\nimages (`eclipse-temurin`, `tomcat`, `node`, `python`, `golang`, `rust`)\nare **not** \"alternatives\" — they are fallbacks for the few stacks where\nMCR genuinely does not publish a base. Pick from the catalog in G2.1\nfirst; only if no row matches, drop to G2.3.\n\n#### G2.1 — MCR catalog (use these tags, do not invent others)\n\nUse only the tags listed here. If your `\u003CLV>` is not in the list, see\nG2.2 (modernize) or G2.3 (documented fallback) — do NOT guess a tag.\n\n**Java — `mcr.microsoft.com\u002Fopenjdk\u002Fjdk`**\n\n| `\u003CLV>` | Build tag | Runtime tag |\n|---|---|---|\n| 8 | `8-azurelinux` | `8-distroless` |\n| 11 | `11-azurelinux` | `11-distroless` |\n| 17 | `17-azurelinux` | `17-distroless` |\n| 21 | `21-azurelinux` | `21-distroless` |\n| 25 | `25-azurelinux` | `25-distroless` |\n\nThese are the only Java major versions on MCR (verified against\n`https:\u002F\u002Fmcr.microsoft.com\u002Fv2\u002Fopenjdk\u002Fjdk\u002Ftags\u002Flist`). The published tag\nformat is a **single digit major** — `8-azurelinux`, never `1.8-azurelinux`\nor `8u292-jdk-slim` (those do not exist and fail with `image not found`).\nMCR does **not** publish a separate `openjdk\u002Fjre` repository — for the\nruntime stage of a JRE-only image, use the `-distroless` variant of the\nsame major (`8-distroless`, `17-distroless`, …) which ships only the JRE.\n\n**.NET — `mcr.microsoft.com\u002Fdotnet\u002F{sdk,aspnet,runtime}`**\n\n| `\u003CLV>` | SDK | ASP.NET runtime | Generic runtime |\n|---|---|---|---|\n| 8.0 | `sdk:8.0-azurelinux3.0` | `aspnet:8.0-azurelinux3.0` | `runtime:8.0-azurelinux3.0` |\n| 9.0 | `sdk:9.0-azurelinux3.0` | `aspnet:9.0-azurelinux3.0` | `runtime:9.0-azurelinux3.0` |\n\n**Node.js — `mcr.microsoft.com\u002Fazurelinux\u002F{base,distroless}\u002Fnodejs`**\n\n| `\u003CLV>` | Build tag | Runtime tag |\n|---|---|---|\n| 18 | `base\u002Fnodejs:18` | `distroless\u002Fnodejs:18` |\n| 20 | `base\u002Fnodejs:20` | `distroless\u002Fnodejs:20` |\n| 22 | `base\u002Fnodejs:22` | `distroless\u002Fnodejs:22` |\n\n**Python — `mcr.microsoft.com\u002Fazurelinux\u002F{base,distroless}\u002Fpython`**\n\n| `\u003CLV>` | Build tag | Runtime tag |\n|---|---|---|\n| 3.11 | `base\u002Fpython:3.11` | `distroless\u002Fpython:3.11` |\n| 3.12 | `base\u002Fpython:3.12` | `distroless\u002Fpython:3.12` |\n\nDefaults if `languageVersion` is missing: `java=21`, `dotnet=8.0`,\n`node=20`, `python=3.12`.\n\n#### G2.2 — Modernize before falling back\n\nIf the project targets a version not in G2.1 (typically Python 3.9\u002F3.10,\nNode 16, Java 7):\n\n1. **Preferred:** bump the build target to the nearest LTS in G2.1\n   (Python → 3.11, Node → 18). Update package metadata, keep MCR images.\n2. Only if modernization is genuinely impossible, drop to G2.3 and\n   document the reason in a `# WHY-NOT-MCR:` comment above the\n   offending `FROM` line.\n\n#### G2.3 — Allowed non-MCR fallbacks (closed list)\n\nThe following bases may appear when, and only when, no MCR row in G2.1\napplies. Anything not in this list MUST NOT appear in a `FROM` line.\n\n**Hard rule — build images are build-only.** The images in the **Build\nstage** column below (`maven:*`, `gradle:*`, `golang:*`, `rust:*`,\n`composer:*`) are builders. They MUST NOT be the final \u002F runtime stage. Using\na non-MCR build image obligates a **multi-stage** Dockerfile whose final\n`FROM` is the matching **Runtime stage** image (an MCR `*-distroless` row from\nG2.1 wherever one exists). A single-stage Dockerfile that ships a\n`maven` \u002F `gradle` \u002F `golang` \u002F `rust` builder as the runtime image is a policy\nviolation: it defeats the MCR-runtime goal and ships the full build toolchain\nplus source in the running image — even though a lone `maven`\u002F`gradle` `FROM`\nlooks \"allowed\" here.\n\n| Stack \u002F Reason | Build stage | Runtime stage |\n|---|---|---|\n| Maven builder (MCR ships no Maven-with-JDK image) | `maven:3.9-eclipse-temurin-\u003CLV>` (where `\u003CLV>` ∈ {8, 11, 17, 21}) | use the matching MCR `openjdk\u002Fjdk:\u003CLV>-distroless` for runtime |\n| Gradle builder (MCR ships no Gradle image) | `gradle:\u003Cver>-jdk\u003CLV>` | use the matching MCR `openjdk\u002Fjdk:\u003CLV>-distroless` for runtime |\n| Java EE \u002F Jakarta EE app server (EJB, JSF, full profile — MCR ships no app server) | `maven:3.9-eclipse-temurin-\u003CLV>` or MCR `openjdk\u002Fjdk:\u003CLV>-azurelinux` | `jboss\u002Fwildfly:\u003Cver>` (WildFly), `payara\u002Fserver-full:\u003Cver>` (Payara), `tomee:\u003Cver>` (TomEE), or `tomcat:\u003Cver>-jdk\u003CLV>` (servlet-only WAR) |\n| Servlet\u002FJSP WAR with no EJB | MCR `openjdk\u002Fjdk:\u003CLV>-azurelinux` | `tomcat:\u003Cver>-jdk\u003CLV>` |\n| Go (no MCR base) | `golang:\u003CLV>-alpine` | `gcr.io\u002Fdistroless\u002Fstatic-debian12:nonroot` (CGO off) or `gcr.io\u002Fdistroless\u002Fbase-debian12:nonroot` (CGO on) |\n| Rust (no MCR base) | `rust:\u003CLV>-slim` | `gcr.io\u002Fdistroless\u002Fcc-debian12:nonroot` |\n| PHP (no MCR base) | `composer:2` | `php:\u003CLV>-fpm-alpine` or `php:\u003CLV>-apache` |\n| Ruby (no MCR base) | `ruby:\u003CLV>-slim` | `ruby:\u003CLV>-slim` |\n\n**Bare JDK\u002FJRE images (`eclipse-temurin`, `openjdk`, `adoptopenjdk`,\n`amazoncorretto`, `ibmjava`) are NOT on this list.** For Java versions\n8, 11, 17, 21, or 25, the MCR `openjdk\u002Fjdk:\u003CLV>-{azurelinux,distroless}`\nrow in G2.1 is mandatory — falling back to `eclipse-temurin:8-jre-alpine`\nor `adoptopenjdk:8-jre-hotspot` when MCR has the same major is a policy\nviolation, even with a `# WHY-NOT-MCR:` comment.\n\n**Tag-name precision for Docker Hub `maven` images:** the only published\n`maven:3.9-eclipse-temurin-*` tags are `8`, `11`, `17`, `21` — there is\n**no** `…-jdk` suffix on these. Tags such as `maven:3.9-eclipse-temurin-8-jdk`\nor `maven:3.9-eclipse-temurin-17-jdk` do **not** exist and fail with\n`not found`. Use `maven:3.9-eclipse-temurin-17`, not\n`maven:3.9-eclipse-temurin-17-jdk`.\n\nWhen you use any row from G2.3, prepend a `# WHY-NOT-MCR:` comment\nabove the `FROM` line explaining which condition triggered the\nfallback (e.g. `# WHY-NOT-MCR: Java EE app server, no MCR equivalent`).\n\n**Never invent a tag.** If you are tempted to write\n`mcr.microsoft.com\u002F\u003Canything>:\u003CLV>-\u003Csuffix>` and the exact tag is not\nin G2.1, stop — either modernize per G2.2 or fall back per G2.3.\n\n### G3 — Construct the Dockerfile\n\n**Hard rule: every Dockerfile MUST contain\n`LABEL com.azure.containerizationassist.createdby=\"containerization-assist\"`,\nemitted on the line immediately after the `FROM` of the runtime \u002F final\nstage. No exceptions. A Dockerfile without this label is rejected.**\n\nApply every rule in this checklist:\n\n**Layer\u002Fstructure**\n- One `WORKDIR` early (use `\u002Fapp`); never use `cd` in `RUN`.\n- Copy **dependency manifests first**, install deps, then copy source — to\n  preserve layer cache.\n- **Source MUST be copied before any build\u002Fcompile command.** Every build\n  stage that runs `mvn` \u002F `.\u002Fmvnw` \u002F `gradle` \u002F `.\u002Fgradlew` \u002F `npm run build`\n  \u002F `tsc` \u002F `dotnet publish` \u002F `go build` \u002F `cargo build` MUST be preceded\n  by a `COPY src .\u002Fsrc` (or equivalent — `COPY . .` for languages without\n  a conventional `src\u002F` layout). Skipping the source copy produces an empty\n  build that fails with errors like \"Unable to find main class\" or\n  \"no main module\" at runtime.\n- Use `RUN` chaining with `&&` to keep layers small. Aim for ≤ 6 `RUN`\n  instructions.\n- For multi-stage, give each stage a name (`AS build`, `AS runtime`).\n\n**Build output & dependencies (derive, never assume)**\n\nWhere a build writes its artifact, and which dependencies it needs to run,\nare determined by the project's own config — not by framework convention.\nTwo recurring build failures come from guessing instead of reading:\n\n- **Derive the build-output directory; never hardcode it.** Before you\n  `COPY` build output into the runtime stage, find where the build tool\n  actually writes it:\n  1. Read the build tool's config for a configured output path — e.g.\n     `build.outDir` in `vite.config.*`, `compilerOptions.outDir` in\n     `tsconfig.json`, `outputPath` in `angular.json`, `distDir` in\n     `next.config.*`, `output.path` in `webpack.config.*`, `buildDir` in\n     `nuxt.config.*`.\n  2. If none is set, use that tool's documented default.\n  3. If still unsure, run the build in the build stage and `COPY` the\n     directory it actually produced.\n  `build\u002F` is only Create React App's default. Vite, Vue CLI, Angular and\n  most bundlers emit to `dist\u002F`; Next.js to `.next\u002F`. Hardcoding\n  `COPY build\u002F ...` fails with `\"\u002Fapp\u002Fbuild\": not found` on any of them.\n\n- **Install full dependencies in the build stage; prune only for runtime.**\n  Compilers and bundlers (`tsc`, `vite`, `webpack`, `rollup`, `esbuild`)\n  almost always live in `devDependencies`. In the build stage run a full\n  install (`npm ci` \u002F `npm install` with **no** `--omit=dev` \u002F\n  `--production`). Running `npm ci --omit=dev` before `npm run build`\n  removes the compiler and fails with `tsc: not found` \u002F exit 127. Only the\n  **runtime** stage may drop dev deps — or, better, copy just the built\n  artifact into a clean runtime image and install nothing there.\n\nThese two rules hold for any compiled or bundled stack — present or future\n— so they replace per-framework \"copy from X\" recipes rather than adding to\nthem.\n\n**Security baseline (mandatory)**\n- Final stage MUST end with a `USER` instruction set to a non-root user.\n  - If the base image already provides one (e.g. `nonroot`, `appuser`), use\n    it; otherwise create one with **two separate instructions** (`USER` is a\n    Dockerfile instruction, not a shell command — it cannot be chained after\n    `RUN ... &&`):\n    - Alpine:\n      ```\n      RUN adduser -D -u 10001 appuser\n      USER appuser\n      ```\n    - Debian \u002F Azure Linux:\n      ```\n      RUN useradd -m -u 10001 appuser\n      USER appuser\n      ```\n- **Never** include any of these in `ENV`:\n  `PASSWORD`, `PASSWD`, `TOKEN`, `SECRET`, `CREDENTIAL`, `API_KEY`,\n  `PRIVATE_KEY`, `ACCESS_KEY`, `*_DSN`, `DATABASE_URL`, `CONNECTION_STRING`,\n  `REDIS_URL`, `MONGODB_URI`. These get injected at runtime via K8s Secrets.\n- Do NOT run `apt-get upgrade` \u002F `apt-get dist-upgrade`.\n- If using `apt-get install`, clean up:\n  `apt-get update && apt-get install -y --no-install-recommends \u003Cpkgs> && rm -rf \u002Fvar\u002Flib\u002Fapt\u002Flists\u002F*`.\n- **Package manager per base image** — using the wrong one fails with `command not found`:\n\n  | Base image family | Package manager | Install one-liner |\n  |---|---|---|\n  | `mcr.microsoft.com\u002Fopenjdk\u002Fjdk:*-azurelinux`, `mcr.microsoft.com\u002Fazurelinux\u002Fbase\u002F*`, `mcr.microsoft.com\u002Fdotnet\u002F*-azurelinux*`, `*-mariner*` | **`tdnf`** | `tdnf install -y \u003Cpkg> && tdnf clean all` |\n  | `mcr.microsoft.com\u002F*-distroless`, `gcr.io\u002Fdistroless\u002F*` | **none** — no shell, no package manager. Install in the build stage instead and copy artifacts in. |\n  | `eclipse-temurin:*-jre-alpine`, `node:*-alpine`, `python:*-alpine` | `apk` | `apk add --no-cache \u003Cpkg>` |\n  | `eclipse-temurin:*-jdk`, `python:*-slim`, `node:*` (Debian-based) | `apt-get` | as above |\n\n  **`microdnf` does NOT exist on Azure Linux \u002F Mariner.** It ships on RHEL\u002FUBI\n  only. Using `microdnf install …` on any `*-azurelinux` or `*-mariner`\n  base image fails with `microdnf: command not found`. Use `tdnf` instead\n  — same syntax, same flags. Do NOT use `apt-get` on Azure Linux either.\n\n**Distroless final-stage rules (hard):** when the runtime stage `FROM`\nends in `-distroless` (or starts with `gcr.io\u002Fdistroless\u002F`), the image\nhas no shell, no package manager, no `useradd`\u002F`adduser`, no `chmod`,\nno `mkdir`. Any `RUN` in the distroless stage will fail at build time\nwith `exec: \"\u002Fbin\u002Fsh\": stat \u002Fbin\u002Fsh: no such file or directory`. Rules:\n\n- **No `RUN` instructions in the distroless stage.** Do all setup\n  (chmod, package install, user creation) in the build stage and `COPY`\n  the prepared artifacts in.\n- **Do not try to `RUN useradd` \u002F `RUN adduser` on distroless** (no shell).\n  Set the user with a numeric `USER` instead — which non-root user the base\n  provides depends on the image:\n  - **Node.js \u002F Python** (`mcr.microsoft.com\u002Fazurelinux\u002Fdistroless\u002F{nodejs,python}`)\n    predefine a non-root user `app` at UID 1000 — emit `USER 1000` (preferred)\n    or `USER app`.\n  - **Java** (`mcr.microsoft.com\u002Fopenjdk\u002Fjdk:\u003CLV>-distroless`) does **NOT**\n    predefine a non-root user — its default is root, and there is no `app`\n    user. Emit the numeric `USER 1000` (do **not** write `USER app`: that name\n    does not exist on the Java distroless image, and a Kubernetes\n    `runAsNonRoot` securityContext then fails at deploy with\n    `CreateContainerConfigError: ... non-numeric user`).\n  Always prefer the **numeric** `USER 1000` on distroless: a numeric UID\n  satisfies `runAsNonRoot` without needing an `\u002Fetc\u002Fpasswd` entry.\n- **Do not try to `RUN chmod` \u002F `RUN chown` on distroless.** Set the\n  mode\u002Fowner with `COPY --chmod=…` \u002F `COPY --chown=app:app …` instead\n  (BuildKit syntax, supported by default).\n- **Skip `HEALTHCHECK`** on distroless — there is no shell to run the\n  probe command. Document with `# HEALTHCHECK: skipped — distroless,\n  use Kubernetes liveness\u002Freadiness probe`.\n- Pin **major** version tags (`:21`, `:8.0`, `:3.11`), never `:latest` and\n  never floating patch versions like `21.0.3`.\n\n**Quality baseline**\n- Include `HEALTHCHECK` for long-running services (web servers, workers).\n  Pick the simplest probe the runtime image actually supports:\n  - Has `curl`: `HEALTHCHECK CMD curl -fsS http:\u002F\u002Flocalhost:\u003Cport>\u002Fhealth || exit 1`\n  - Alpine \u002F busybox (no curl, has wget): `HEALTHCHECK CMD wget --spider -q http:\u002F\u002Flocalhost:\u003Cport>\u002Fhealth || exit 1`\n  - Distroless \u002F no shell: skip HEALTHCHECK and add a comment `# HEALTHCHECK: skipped — distroless image has no shell. Use Kubernetes liveness\u002Freadiness probe.`\n- `EXPOSE \u003Cport>` for the primary listener.\n- `CMD` in **exec form** (`[\"binary\",\"arg\"]`), required for distroless.\n\n**Env variables**\n- For each entry in `detectedEnvVars` classified as `config` or `database`:\n  if it has a `defaultValue`, emit `ENV NAME=\u003Cvalue>`; otherwise emit\n  `# ENV NAME=\u003Cset at runtime>` as a comment.\n- For each entry classified as `secret`: emit `# SECRET: NAME — inject via\n  Kubernetes Secret at runtime, do NOT bake into the image`.\n\n**Required labels (attribution)**\n\n`LABEL` is a Dockerfile instruction that only takes effect inside a build\nstage — it MUST appear after a `FROM` line or `docker build` errors out\nwith `no build stage in current context`. Emit attribution labels\n**immediately after the `FROM` line of the final \u002F runtime stage** (and\nnot before the first `FROM`, not in the build stage).\n\nAlways emit, in the runtime stage:\n```\nLABEL com.azure.containerizationassist.createdby=\"containerization-assist\"\n```\n\nIf you can read the current `containerization-assist` package version\nfrom the environment (e.g. its `package.json`), also emit:\n```\nLABEL com.azure.containerizationassist.version=\"\u003Cversion>\"\n```\nOtherwise omit the version label — never hard-code a stale version string.\nDo NOT substitute either key for `org.opencontainers.image.*`.\n\n**Framework-specific tweaks (illustrative, not an allowlist)**\n\nThese rows are worked examples of the general rules above — not an\nexhaustive list. For a framework not listed here, apply the same approach:\nderive the build-output directory and the run command from the project's\nown config and the framework's documented defaults. Never skip\ncontainerizing a stack, or fall back to a guess, just because it lacks a\nrow in this table.\n\n| Framework | Add |\n|---|---|\n| Spring Boot | `ENV JAVA_OPTS=\"-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0\"`, copy fat JAR from `target\u002F*.jar`, `ENTRYPOINT [\"java\",\"-jar\",\"\u002Fapp\u002Fapp.jar\"]` |\n| Next.js | Build with `npm run build`; copy `.next\u002Fstandalone`, `.next\u002Fstatic`, `public`; `CMD [\"node\",\"server.js\"]` |\n| Django | `RUN python manage.py collectstatic --noinput`; run with `gunicorn` |\n| FastAPI | `CMD [\"uvicorn\",\"app.main:app\",\"--host\",\"0.0.0.0\",\"--port\",\"8000\"]` |\n| ASP.NET Core | `dotnet publish -c Release -o \u002Fout`; runtime stage runs `dotnet \u003CApp>.dll` |\n| Go | `CGO_ENABLED=0 go build -ldflags=\"-s -w\" -o \u002Fout\u002Fapp`; copy single binary into distroless |\n| Rust | `cargo build --release`; copy `target\u002Frelease\u002F\u003Cbin>` into distroless |\n\n### G4 — Validate the result against this self-check\n\nBefore emitting, confirm:\n\n- [ ] **Required label present.** The runtime stage contains `LABEL com.azure.containerizationassist.createdby=\"containerization-assist\"` immediately after its `FROM` line. (If missing, add it now — do not skip.)\n- [ ] **Azure base.** Every `FROM` line either starts with `mcr.microsoft.com\u002F` (using a tag from the G2.1 catalog) **or** matches a row in the G2.3 fallback list with a `# WHY-NOT-MCR:` comment above it. No invented MCR tags.\n- [ ] **No builder as runtime.** If any `FROM` uses a G2.3 *Build stage* image (`maven`\u002F`gradle`\u002F`golang`\u002F`rust`\u002F`composer`), the Dockerfile is multi-stage and its **final** `FROM` is the matching G2.3 *Runtime stage* image (or an MCR G2.1 image) — never the builder itself.\n- [ ] **Source copied before build.** Every `RUN` that invokes a build tool (`mvn`\u002F`mvnw`, `gradle`\u002F`gradlew`, `npm run build`, `tsc`, `dotnet publish`, `go build`, `cargo build`) is preceded by a `COPY` of the source tree.\n- [ ] Single non-root `USER` in the final stage\n- [ ] No hardcoded secrets in any `ENV`\n- [ ] No `:latest` tag, no `apt-get upgrade`\n- [ ] `WORKDIR` set, no `cd` in `RUN`\n- [ ] Multi-stage chosen per rule G1\n- [ ] `EXPOSE` matches detected listener port\n- [ ] `CMD`\u002F`ENTRYPOINT` in exec form\n\nIf any item fails, fix the Dockerfile **before** showing it to the user.\n\n---\n\n## Enhancement path\n\n### E1 — Analyze the existing Dockerfile\n\nRead the file. Compute:\n\n- `baseImages` = every line starting with `FROM ` (after `FROM `, take the\n  first whitespace-delimited token).\n- `isMultistage` = `baseImages.length > 1`.\n- `hasHealthCheck` = any line starts with `HEALTHCHECK ` (case-insensitive).\n- `hasNonRootUser` = any `USER` line whose argument is not `root` or `0`.\n- `instructionCount` = number of lines whose first token is one of:\n  `FROM, RUN, CMD, LABEL, EXPOSE, ENV, ADD, COPY, ENTRYPOINT, VOLUME,\n  USER, WORKDIR, ARG, ONBUILD, STOPSIGNAL, HEALTHCHECK, SHELL`.\n- `complexity` = `complex` if `instructionCount > 20` or `isMultistage`;\n  else `moderate` if `> 10`; else `simple`.\n- `securityPosture` = `good` if `hasNonRootUser && hasHealthCheck`; `poor`\n  if `!hasNonRootUser && !hasHealthCheck`; else `needs-improvement`.\n\n### E2 — Compute the diff plan\n\n- **Preserve** (always keep): multi-stage structure if present, existing\n  HEALTHCHECK if present, non-root USER if present, existing base image\n  unless it's `:latest` or unsupported.\n- **Improve** (rewrite in place): any rule from G3 that the current file\n  violates (root user, hardcoded secrets, `apt-get upgrade`, missing\n  cleanup, `cd` in `RUN`, floating tags, > 6 `RUN` instructions when\n  combinable, missing labels).\n- **Add missing**: non-root USER if absent, HEALTHCHECK if absent and the\n  image has a shell, required `LABEL`s if absent, `WORKDIR` if absent.\n\n### E3 — Pick the strategy\n\n| Conditions | Strategy |\n|---|---|\n| `securityPosture == \"poor\"` OR (`improve.length + addMissing.length > 5`) | `major-overhaul` |\n| `securityPosture == \"needs-improvement\"` OR (`improve.length + addMissing.length > 2`) | `moderate-refactor` |\n| Otherwise | `minor-tweaks` |\n\n### E4 — Produce the enhanced Dockerfile\n\nCompose the **full** updated Dockerfile (do not show a diff). Apply every\nrelevant item from G3 to bring it to baseline. Preserve the listed items\nverbatim. Re-run the G4 self-check before writing.\n\n---\n\n## Writing the file (mandatory)\n\nAs soon as the Dockerfile passes the G4 self-check, **write it to\n`\u003CmodulePath>\u002FDockerfile`**. Do not ask the user for confirmation first;\ndo not stage it in the response. If a Dockerfile already exists, overwrite\nit (the Enhancement path already incorporates anything worth preserving).\n\nDo **NOT** print the full Dockerfile content in the chat response. The\nuser can open the file on disk. Only include excerpts when:\n\n- the user explicitly asks to see it (\"show me the Dockerfile\", \"print it\"),\n- you need to highlight a specific change (≤ 10 lines of context), or\n- the write failed and you need to surface the content for manual recovery.\n\n## Output format\n\nUse exactly these sections, in order. Keep the response short — the file\non disk is the artifact.\n\n````md\n**Dockerfile \u003Cgeneration|enhancement>** — written to `\u003CmodulePath>\u002FDockerfile`\n\n### Plan\n- **Strategy:** \u003Cmulti-stage build | single-stage build | minor-tweaks | moderate-refactor | major-overhaul>\n- **Base image (build):** `\u003Cimage>` \u003Conly if multi-stage>\n- **Base image (runtime):** `\u003Cimage>`\n- **User:** `appuser` (UID 10001) \u003Cor \"preserved from existing\">\n- **Healthcheck:** \u003Cyes\u002Fno — reason if no>\n\n### Env vars\n- `\u003CNAME>` *\u003Cconfig|database>* → emitted as `ENV`\n- `\u003CNAME>` *secret* → **runtime injection only** (Kubernetes Secret)\n- ...\n\n### Next steps\n1. Build locally: `docker buildx build --platform=\u003CtargetPlatform> -t \u003Cmodule>:dev \u003CmodulePath>`\n2. Run **fix-dockerfile** to lint and remediate the file against the built-in security and best-practice rules.\n3. Once validated, scan the built image and proceed to `generate-k8s-manifests`.\n````\n\nIf the result was an **enhancement**, also include this section between\n**Plan** and **Env vars**:\n\n````md\n### Changes from existing\n- **Preserve:** \u003Cbullet list>\n- **Improve:** \u003Cbullet list>\n- **Add:** \u003Cbullet list>\n````\n\n## Constraints\n\n- The Dockerfile written to disk must be **complete and runnable as-is**\n  (no placeholders, no `\u003CTODO>` markers, no truncation).\n- NEVER use `FROM \u003Cimage>:latest`.\n- NEVER set any of the secret-pattern env vars in the file. If the user\n  insists, refuse and explain why.\n- NEVER include `apt-get upgrade` or `apt-get dist-upgrade`.\n- NEVER end the final stage as `root`.\n- NEVER omit the `com.azure.containerizationassist.createdby` label, and NEVER replace either attribution label key with `org.opencontainers.image.*`.\n- NEVER print the full Dockerfile in the chat response by default — write\n  it to disk and reference the path. Print only when the user asks or to\n  show a short excerpt.\n- The Dockerfile must pass the G4 self-check before being written. If a\n  constraint conflicts with a user instruction, surface the conflict\n  explicitly and ask before proceeding.\n\n## Failure modes\n\n| Symptom | Action |\n|---|---|\n| `modulePath` doesn't exist | Echo the path, ask user to provide a valid one. STOP. |\n| No `language` provided and no manifest file at `modulePath` | Ask the user for the language, OR suggest running `analyze-repo` first. STOP. |\n| Existing Dockerfile is empty or unreadable | Treat as Generation path, note this in **Plan**. |\n| Existing Dockerfile already passes the G4 self-check | Strategy = `minor-tweaks`; report \"no changes required\"; leave the file untouched. |\n| Write to `\u003CmodulePath>\u002FDockerfile` fails (permissions, read-only FS) | Surface the error and the Dockerfile content for manual save. |\n| User has a custom registry \u002F non-standard base image preference | Use the user's choice as base image, still apply all G3 baseline rules. |\n",{"data":35,"body":37},{"name":4,"description":6,"argument-hint":36},"\u003CmodulePath> \u003Clanguage> [framework] [environment=production|development]",{"type":38,"children":39},"root",[40,48,54,61,522,528,588,594,640,644,649,656,668,770,781,786,792,816,869,876,889,903,1062,1148,1162,1266,1280,1385,1399,1478,1519,1525,1530,1563,1569,1580,1707,2005,2080,2186,2212,2230,2236,2259,2264,2272,2465,2473,2478,2768,2773,2781,3302,3380,3688,3696,3790,3798,3869,3877,3932,3937,3946,3967,3976,3988,3996,4001,4215,4221,4226,4596,4608,4611,4616,4622,4627,4842,4848,4929,4935,5034,5040,5052,5055,5061,5078,5089,5107,5113,5118,5758,5783,5912,5918,6015,6021,6163],{"type":41,"tag":42,"props":43,"children":44},"element","h1",{"id":4},[45],{"type":46,"value":47},"text","Generate Dockerfile",{"type":41,"tag":49,"props":50,"children":51},"p",{},[52],{"type":46,"value":53},"Produce a production-quality, secure Dockerfile (or enhancement plan for an\nexisting one) for a single module. The output is a complete Dockerfile that\nthe user can write to disk — not a description of one.",{"type":41,"tag":55,"props":56,"children":58},"h2",{"id":57},"inputs",[59],{"type":46,"value":60},"Inputs",{"type":41,"tag":62,"props":63,"children":64},"table",{},[65,89],{"type":41,"tag":66,"props":67,"children":68},"thead",{},[69],{"type":41,"tag":70,"props":71,"children":72},"tr",{},[73,79,84],{"type":41,"tag":74,"props":75,"children":76},"th",{},[77],{"type":46,"value":78},"Field",{"type":41,"tag":74,"props":80,"children":81},{},[82],{"type":46,"value":83},"Required",{"type":41,"tag":74,"props":85,"children":86},{},[87],{"type":46,"value":88},"Description",{"type":41,"tag":90,"props":91,"children":92},"tbody",{},[93,125,209,261,331,365,398,419,479],{"type":41,"tag":70,"props":94,"children":95},{},[96,107,112],{"type":41,"tag":97,"props":98,"children":99},"td",{},[100],{"type":41,"tag":101,"props":102,"children":104},"code",{"className":103},[],[105],{"type":46,"value":106},"modulePath",{"type":41,"tag":97,"props":108,"children":109},{},[110],{"type":46,"value":111},"yes",{"type":41,"tag":97,"props":113,"children":114},{},[115,117,123],{"type":46,"value":116},"Absolute path of the module to containerize (one of the modules from ",{"type":41,"tag":101,"props":118,"children":120},{"className":119},[],[121],{"type":46,"value":122},"analyze-repo",{"type":46,"value":124},").",{"type":41,"tag":70,"props":126,"children":127},{},[128,137,141],{"type":41,"tag":97,"props":129,"children":130},{},[131],{"type":41,"tag":101,"props":132,"children":134},{"className":133},[],[135],{"type":46,"value":136},"language",{"type":41,"tag":97,"props":138,"children":139},{},[140],{"type":46,"value":111},{"type":41,"tag":97,"props":142,"children":143},{},[144,150,152,158,159,165,166,172,173,179,180,186,187,193,194,200,201,207],{"type":41,"tag":101,"props":145,"children":147},{"className":146},[],[148],{"type":46,"value":149},"java",{"type":46,"value":151}," | ",{"type":41,"tag":101,"props":153,"children":155},{"className":154},[],[156],{"type":46,"value":157},"dotnet",{"type":46,"value":151},{"type":41,"tag":101,"props":160,"children":162},{"className":161},[],[163],{"type":46,"value":164},"javascript",{"type":46,"value":151},{"type":41,"tag":101,"props":167,"children":169},{"className":168},[],[170],{"type":46,"value":171},"typescript",{"type":46,"value":151},{"type":41,"tag":101,"props":174,"children":176},{"className":175},[],[177],{"type":46,"value":178},"python",{"type":46,"value":151},{"type":41,"tag":101,"props":181,"children":183},{"className":182},[],[184],{"type":46,"value":185},"go",{"type":46,"value":151},{"type":41,"tag":101,"props":188,"children":190},{"className":189},[],[191],{"type":46,"value":192},"rust",{"type":46,"value":151},{"type":41,"tag":101,"props":195,"children":197},{"className":196},[],[198],{"type":46,"value":199},"php",{"type":46,"value":151},{"type":41,"tag":101,"props":202,"children":204},{"className":203},[],[205],{"type":46,"value":206},"ruby",{"type":46,"value":208},".",{"type":41,"tag":70,"props":210,"children":211},{},[212,221,226],{"type":41,"tag":97,"props":213,"children":214},{},[215],{"type":41,"tag":101,"props":216,"children":218},{"className":217},[],[219],{"type":46,"value":220},"languageVersion",{"type":41,"tag":97,"props":222,"children":223},{},[224],{"type":46,"value":225},"recommended",{"type":41,"tag":97,"props":227,"children":228},{},[229,231,237,239,245,246,252,253,259],{"type":46,"value":230},"E.g. ",{"type":41,"tag":101,"props":232,"children":234},{"className":233},[],[235],{"type":46,"value":236},"21",{"type":46,"value":238},", ",{"type":41,"tag":101,"props":240,"children":242},{"className":241},[],[243],{"type":46,"value":244},"8.0",{"type":46,"value":238},{"type":41,"tag":101,"props":247,"children":249},{"className":248},[],[250],{"type":46,"value":251},"20",{"type":46,"value":238},{"type":41,"tag":101,"props":254,"children":256},{"className":255},[],[257],{"type":46,"value":258},"3.11",{"type":46,"value":260},". Substituted into the base image tag.",{"type":41,"tag":70,"props":262,"children":263},{},[264,273,278],{"type":41,"tag":97,"props":265,"children":266},{},[267],{"type":41,"tag":101,"props":268,"children":270},{"className":269},[],[271],{"type":46,"value":272},"framework",{"type":41,"tag":97,"props":274,"children":275},{},[276],{"type":46,"value":277},"optional",{"type":41,"tag":97,"props":279,"children":280},{},[281,282,288,289,295,296,302,303,309,310,316,317,323,324,330],{"type":46,"value":230},{"type":41,"tag":101,"props":283,"children":285},{"className":284},[],[286],{"type":46,"value":287},"spring-boot",{"type":46,"value":238},{"type":41,"tag":101,"props":290,"children":292},{"className":291},[],[293],{"type":46,"value":294},"express",{"type":46,"value":238},{"type":41,"tag":101,"props":297,"children":299},{"className":298},[],[300],{"type":46,"value":301},"next",{"type":46,"value":238},{"type":41,"tag":101,"props":304,"children":306},{"className":305},[],[307],{"type":46,"value":308},"django",{"type":46,"value":238},{"type":41,"tag":101,"props":311,"children":313},{"className":312},[],[314],{"type":46,"value":315},"flask",{"type":46,"value":238},{"type":41,"tag":101,"props":318,"children":320},{"className":319},[],[321],{"type":46,"value":322},"asp.net-core",{"type":46,"value":238},{"type":41,"tag":101,"props":325,"children":327},{"className":326},[],[328],{"type":46,"value":329},"gin",{"type":46,"value":208},{"type":41,"tag":70,"props":332,"children":333},{},[334,343,347],{"type":41,"tag":97,"props":335,"children":336},{},[337],{"type":41,"tag":101,"props":338,"children":340},{"className":339},[],[341],{"type":46,"value":342},"environment",{"type":41,"tag":97,"props":344,"children":345},{},[346],{"type":46,"value":277},{"type":41,"tag":97,"props":348,"children":349},{},[350,356,358,364],{"type":41,"tag":101,"props":351,"children":353},{"className":352},[],[354],{"type":46,"value":355},"production",{"type":46,"value":357}," (default) or ",{"type":41,"tag":101,"props":359,"children":361},{"className":360},[],[362],{"type":46,"value":363},"development",{"type":46,"value":208},{"type":41,"tag":70,"props":366,"children":367},{},[368,377,381],{"type":41,"tag":97,"props":369,"children":370},{},[371],{"type":41,"tag":101,"props":372,"children":374},{"className":373},[],[375],{"type":46,"value":376},"targetPlatform",{"type":41,"tag":97,"props":378,"children":379},{},[380],{"type":46,"value":277},{"type":41,"tag":97,"props":382,"children":383},{},[384,390,391,397],{"type":41,"tag":101,"props":385,"children":387},{"className":386},[],[388],{"type":46,"value":389},"linux\u002Famd64",{"type":46,"value":357},{"type":41,"tag":101,"props":392,"children":394},{"className":393},[],[395],{"type":46,"value":396},"linux\u002Farm64",{"type":46,"value":208},{"type":41,"tag":70,"props":399,"children":400},{},[401,410,414],{"type":41,"tag":97,"props":402,"children":403},{},[404],{"type":41,"tag":101,"props":405,"children":407},{"className":406},[],[408],{"type":46,"value":409},"detectedDependencies",{"type":41,"tag":97,"props":411,"children":412},{},[413],{"type":46,"value":277},{"type":41,"tag":97,"props":415,"children":416},{},[417],{"type":46,"value":418},"Used to choose extra apt\u002Fapk packages (e.g. native modules).",{"type":41,"tag":70,"props":420,"children":421},{},[422,431,435],{"type":41,"tag":97,"props":423,"children":424},{},[425],{"type":41,"tag":101,"props":426,"children":428},{"className":427},[],[429],{"type":46,"value":430},"detectedEnvVars",{"type":41,"tag":97,"props":432,"children":433},{},[434],{"type":46,"value":277},{"type":41,"tag":97,"props":436,"children":437},{},[438,440,445,447,453,455,461,463,469,471,477],{"type":46,"value":439},"List from ",{"type":41,"tag":101,"props":441,"children":443},{"className":442},[],[444],{"type":46,"value":122},{"type":46,"value":446},". Used to add ",{"type":41,"tag":101,"props":448,"children":450},{"className":449},[],[451],{"type":46,"value":452},"ENV",{"type":46,"value":454}," instructions for ",{"type":41,"tag":101,"props":456,"children":458},{"className":457},[],[459],{"type":46,"value":460},"config",{"type":46,"value":462},"\u002F",{"type":41,"tag":101,"props":464,"children":466},{"className":465},[],[467],{"type":46,"value":468},"database",{"type":46,"value":470}," vars and to WARN about ",{"type":41,"tag":101,"props":472,"children":474},{"className":473},[],[475],{"type":46,"value":476},"secret",{"type":46,"value":478},"-classified ones (never bake secrets in).",{"type":41,"tag":70,"props":480,"children":481},{},[482,491,495],{"type":41,"tag":97,"props":483,"children":484},{},[485],{"type":41,"tag":101,"props":486,"children":488},{"className":487},[],[489],{"type":46,"value":490},"existingDockerfile",{"type":41,"tag":97,"props":492,"children":493},{},[494],{"type":46,"value":277},{"type":41,"tag":97,"props":496,"children":497},{},[498,500,506,508,514,516,521],{"type":46,"value":499},"If a Dockerfile is already at ",{"type":41,"tag":101,"props":501,"children":503},{"className":502},[],[504],{"type":46,"value":505},"\u003CmodulePath>\u002FDockerfile",{"type":46,"value":507},", read its content and follow the ",{"type":41,"tag":509,"props":510,"children":511},"strong",{},[512],{"type":46,"value":513},"Enhancement path",{"type":46,"value":515}," instead of the ",{"type":41,"tag":509,"props":517,"children":518},{},[519],{"type":46,"value":520},"Generation path",{"type":46,"value":208},{"type":41,"tag":55,"props":523,"children":525},{"id":524},"prerequisite-analyze-repo",[526],{"type":46,"value":527},"Prerequisite: analyze-repo",{"type":41,"tag":49,"props":529,"children":530},{},[531,533,538,539,544,545,550,552,557,559,564,566,572,574,579,581,586],{"type":46,"value":532},"This skill needs ",{"type":41,"tag":101,"props":534,"children":536},{"className":535},[],[537],{"type":46,"value":136},{"type":46,"value":238},{"type":41,"tag":101,"props":540,"children":542},{"className":541},[],[543],{"type":46,"value":272},{"type":46,"value":238},{"type":41,"tag":101,"props":546,"children":548},{"className":547},[],[549],{"type":46,"value":409},{"type":46,"value":551},", and\n",{"type":41,"tag":101,"props":553,"children":555},{"className":554},[],[556],{"type":46,"value":430},{"type":46,"value":558}," from the ",{"type":41,"tag":101,"props":560,"children":562},{"className":561},[],[563],{"type":46,"value":122},{"type":46,"value":565}," skill. If you don't already\nhave that output for ",{"type":41,"tag":101,"props":567,"children":569},{"className":568},[],[570],{"type":46,"value":571},"\u003CmodulePath>",{"type":46,"value":573}," from earlier in this conversation,\nfollow the ",{"type":41,"tag":101,"props":575,"children":577},{"className":576},[],[578],{"type":46,"value":122},{"type":46,"value":580}," skill against ",{"type":41,"tag":101,"props":582,"children":584},{"className":583},[],[585],{"type":46,"value":571},{"type":46,"value":587}," first, then come\nback.",{"type":41,"tag":55,"props":589,"children":591},{"id":590},"decision-generate-or-enhance",[592],{"type":46,"value":593},"Decision: generate or enhance?",{"type":41,"tag":595,"props":596,"children":597},"ol",{},[598,611,623],{"type":41,"tag":599,"props":600,"children":601},"li",{},[602,604,609],{"type":46,"value":603},"Check if ",{"type":41,"tag":101,"props":605,"children":607},{"className":606},[],[608],{"type":46,"value":505},{"type":46,"value":610}," exists.",{"type":41,"tag":599,"props":612,"children":613},{},[614,616,621],{"type":46,"value":615},"If ",{"type":41,"tag":509,"props":617,"children":618},{},[619],{"type":46,"value":620},"no",{"type":46,"value":622}," → Generation path (Step G1–G4 below).",{"type":41,"tag":599,"props":624,"children":625},{},[626,627,631,633,638],{"type":46,"value":615},{"type":41,"tag":509,"props":628,"children":629},{},[630],{"type":46,"value":111},{"type":46,"value":632}," → read the file, run ",{"type":41,"tag":509,"props":634,"children":635},{},[636],{"type":46,"value":637},"Dockerfile analysis",{"type":46,"value":639}," (Step E1), then\nEnhancement path (Step E2–E4).",{"type":41,"tag":641,"props":642,"children":643},"hr",{},[],{"type":41,"tag":55,"props":645,"children":647},{"id":646},"generation-path",[648],{"type":46,"value":520},{"type":41,"tag":650,"props":651,"children":653},"h3",{"id":652},"g1-choose-build-strategy",[654],{"type":46,"value":655},"G1 — Choose build strategy",{"type":41,"tag":49,"props":657,"children":658},{},[659,661,666],{"type":46,"value":660},"Use ",{"type":41,"tag":509,"props":662,"children":663},{},[664],{"type":46,"value":665},"multi-stage",{"type":46,"value":667}," if any of these:",{"type":41,"tag":669,"props":670,"children":671},"ul",{},[672,707,746],{"type":41,"tag":599,"props":673,"children":674},{},[675,680,682,687,688,693,694,699,700,705],{"type":41,"tag":101,"props":676,"children":678},{"className":677},[],[679],{"type":46,"value":136},{"type":46,"value":681}," ∈ {",{"type":41,"tag":101,"props":683,"children":685},{"className":684},[],[686],{"type":46,"value":149},{"type":46,"value":238},{"type":41,"tag":101,"props":689,"children":691},{"className":690},[],[692],{"type":46,"value":185},{"type":46,"value":238},{"type":41,"tag":101,"props":695,"children":697},{"className":696},[],[698],{"type":46,"value":192},{"type":46,"value":238},{"type":41,"tag":101,"props":701,"children":703},{"className":702},[],[704],{"type":46,"value":157},{"type":46,"value":706},"}",{"type":41,"tag":599,"props":708,"children":709},{},[710,715,717,722,724,730,731,737,738,744],{"type":41,"tag":101,"props":711,"children":713},{"className":712},[],[714],{"type":46,"value":136},{"type":46,"value":716}," is ",{"type":41,"tag":101,"props":718,"children":720},{"className":719},[],[721],{"type":46,"value":171},{"type":46,"value":723}," AND build output is required (",{"type":41,"tag":101,"props":725,"children":727},{"className":726},[],[728],{"type":46,"value":729},"tsc",{"type":46,"value":238},{"type":41,"tag":101,"props":732,"children":734},{"className":733},[],[735],{"type":46,"value":736},"next build",{"type":46,"value":238},{"type":41,"tag":101,"props":739,"children":741},{"className":740},[],[742],{"type":46,"value":743},"vite build",{"type":46,"value":745},", etc.)",{"type":41,"tag":599,"props":747,"children":748},{},[749,755,756,762,763,769],{"type":41,"tag":101,"props":750,"children":752},{"className":751},[],[753],{"type":46,"value":754},"buildSystem.type",{"type":46,"value":681},{"type":41,"tag":101,"props":757,"children":759},{"className":758},[],[760],{"type":46,"value":761},"maven",{"type":46,"value":238},{"type":41,"tag":101,"props":764,"children":766},{"className":765},[],[767],{"type":46,"value":768},"gradle",{"type":46,"value":706},{"type":41,"tag":49,"props":771,"children":772},{},[773,775,780],{"type":46,"value":774},"Otherwise use ",{"type":41,"tag":509,"props":776,"children":777},{},[778],{"type":46,"value":779},"single-stage",{"type":46,"value":208},{"type":41,"tag":49,"props":782,"children":783},{},[784],{"type":46,"value":785},"The reason this matters: multi-stage drops compilers, SDKs, and source code\nfrom the final image — typically 70–90% smaller and a smaller attack surface.",{"type":41,"tag":650,"props":787,"children":789},{"id":788},"g2-choose-the-base-images",[790],{"type":46,"value":791},"G2 — Choose the base image(s)",{"type":41,"tag":49,"props":793,"children":794},{},[795],{"type":41,"tag":509,"props":796,"children":797},{},[798,800,806,808,814],{"type":46,"value":799},"Hard rule: every ",{"type":41,"tag":101,"props":801,"children":803},{"className":802},[],[804],{"type":46,"value":805},"FROM",{"type":46,"value":807}," line MUST start with ",{"type":41,"tag":101,"props":809,"children":811},{"className":810},[],[812],{"type":46,"value":813},"mcr.microsoft.com\u002F",{"type":46,"value":815}," unless\nthe stack appears in the explicit non-MCR list (G2.3) below.",{"type":41,"tag":49,"props":817,"children":818},{},[819,821,827,828,834,835,841,842,847,848,854,855,860,862,867],{"type":46,"value":820},"The Dockerfile is the contract for an Azure-hosted image. Public-registry\nimages (",{"type":41,"tag":101,"props":822,"children":824},{"className":823},[],[825],{"type":46,"value":826},"eclipse-temurin",{"type":46,"value":238},{"type":41,"tag":101,"props":829,"children":831},{"className":830},[],[832],{"type":46,"value":833},"tomcat",{"type":46,"value":238},{"type":41,"tag":101,"props":836,"children":838},{"className":837},[],[839],{"type":46,"value":840},"node",{"type":46,"value":238},{"type":41,"tag":101,"props":843,"children":845},{"className":844},[],[846],{"type":46,"value":178},{"type":46,"value":238},{"type":41,"tag":101,"props":849,"children":851},{"className":850},[],[852],{"type":46,"value":853},"golang",{"type":46,"value":238},{"type":41,"tag":101,"props":856,"children":858},{"className":857},[],[859],{"type":46,"value":192},{"type":46,"value":861},")\nare ",{"type":41,"tag":509,"props":863,"children":864},{},[865],{"type":46,"value":866},"not",{"type":46,"value":868}," \"alternatives\" — they are fallbacks for the few stacks where\nMCR genuinely does not publish a base. Pick from the catalog in G2.1\nfirst; only if no row matches, drop to G2.3.",{"type":41,"tag":870,"props":871,"children":873},"h4",{"id":872},"g21-mcr-catalog-use-these-tags-do-not-invent-others",[874],{"type":46,"value":875},"G2.1 — MCR catalog (use these tags, do not invent others)",{"type":41,"tag":49,"props":877,"children":878},{},[879,881,887],{"type":46,"value":880},"Use only the tags listed here. If your ",{"type":41,"tag":101,"props":882,"children":884},{"className":883},[],[885],{"type":46,"value":886},"\u003CLV>",{"type":46,"value":888}," is not in the list, see\nG2.2 (modernize) or G2.3 (documented fallback) — do NOT guess a tag.",{"type":41,"tag":49,"props":890,"children":891},{},[892],{"type":41,"tag":509,"props":893,"children":894},{},[895,897],{"type":46,"value":896},"Java — ",{"type":41,"tag":101,"props":898,"children":900},{"className":899},[],[901],{"type":46,"value":902},"mcr.microsoft.com\u002Fopenjdk\u002Fjdk",{"type":41,"tag":62,"props":904,"children":905},{},[906,930],{"type":41,"tag":66,"props":907,"children":908},{},[909],{"type":41,"tag":70,"props":910,"children":911},{},[912,920,925],{"type":41,"tag":74,"props":913,"children":914},{},[915],{"type":41,"tag":101,"props":916,"children":918},{"className":917},[],[919],{"type":46,"value":886},{"type":41,"tag":74,"props":921,"children":922},{},[923],{"type":46,"value":924},"Build tag",{"type":41,"tag":74,"props":926,"children":927},{},[928],{"type":46,"value":929},"Runtime tag",{"type":41,"tag":90,"props":931,"children":932},{},[933,959,985,1011,1036],{"type":41,"tag":70,"props":934,"children":935},{},[936,941,950],{"type":41,"tag":97,"props":937,"children":938},{},[939],{"type":46,"value":940},"8",{"type":41,"tag":97,"props":942,"children":943},{},[944],{"type":41,"tag":101,"props":945,"children":947},{"className":946},[],[948],{"type":46,"value":949},"8-azurelinux",{"type":41,"tag":97,"props":951,"children":952},{},[953],{"type":41,"tag":101,"props":954,"children":956},{"className":955},[],[957],{"type":46,"value":958},"8-distroless",{"type":41,"tag":70,"props":960,"children":961},{},[962,967,976],{"type":41,"tag":97,"props":963,"children":964},{},[965],{"type":46,"value":966},"11",{"type":41,"tag":97,"props":968,"children":969},{},[970],{"type":41,"tag":101,"props":971,"children":973},{"className":972},[],[974],{"type":46,"value":975},"11-azurelinux",{"type":41,"tag":97,"props":977,"children":978},{},[979],{"type":41,"tag":101,"props":980,"children":982},{"className":981},[],[983],{"type":46,"value":984},"11-distroless",{"type":41,"tag":70,"props":986,"children":987},{},[988,993,1002],{"type":41,"tag":97,"props":989,"children":990},{},[991],{"type":46,"value":992},"17",{"type":41,"tag":97,"props":994,"children":995},{},[996],{"type":41,"tag":101,"props":997,"children":999},{"className":998},[],[1000],{"type":46,"value":1001},"17-azurelinux",{"type":41,"tag":97,"props":1003,"children":1004},{},[1005],{"type":41,"tag":101,"props":1006,"children":1008},{"className":1007},[],[1009],{"type":46,"value":1010},"17-distroless",{"type":41,"tag":70,"props":1012,"children":1013},{},[1014,1018,1027],{"type":41,"tag":97,"props":1015,"children":1016},{},[1017],{"type":46,"value":236},{"type":41,"tag":97,"props":1019,"children":1020},{},[1021],{"type":41,"tag":101,"props":1022,"children":1024},{"className":1023},[],[1025],{"type":46,"value":1026},"21-azurelinux",{"type":41,"tag":97,"props":1028,"children":1029},{},[1030],{"type":41,"tag":101,"props":1031,"children":1033},{"className":1032},[],[1034],{"type":46,"value":1035},"21-distroless",{"type":41,"tag":70,"props":1037,"children":1038},{},[1039,1044,1053],{"type":41,"tag":97,"props":1040,"children":1041},{},[1042],{"type":46,"value":1043},"25",{"type":41,"tag":97,"props":1045,"children":1046},{},[1047],{"type":41,"tag":101,"props":1048,"children":1050},{"className":1049},[],[1051],{"type":46,"value":1052},"25-azurelinux",{"type":41,"tag":97,"props":1054,"children":1055},{},[1056],{"type":41,"tag":101,"props":1057,"children":1059},{"className":1058},[],[1060],{"type":46,"value":1061},"25-distroless",{"type":41,"tag":49,"props":1063,"children":1064},{},[1065,1067,1073,1075,1080,1082,1087,1089,1095,1097,1103,1105,1111,1113,1117,1119,1125,1127,1133,1135,1140,1141,1146],{"type":46,"value":1066},"These are the only Java major versions on MCR (verified against\n",{"type":41,"tag":101,"props":1068,"children":1070},{"className":1069},[],[1071],{"type":46,"value":1072},"https:\u002F\u002Fmcr.microsoft.com\u002Fv2\u002Fopenjdk\u002Fjdk\u002Ftags\u002Flist",{"type":46,"value":1074},"). The published tag\nformat is a ",{"type":41,"tag":509,"props":1076,"children":1077},{},[1078],{"type":46,"value":1079},"single digit major",{"type":46,"value":1081}," — ",{"type":41,"tag":101,"props":1083,"children":1085},{"className":1084},[],[1086],{"type":46,"value":949},{"type":46,"value":1088},", never ",{"type":41,"tag":101,"props":1090,"children":1092},{"className":1091},[],[1093],{"type":46,"value":1094},"1.8-azurelinux",{"type":46,"value":1096},"\nor ",{"type":41,"tag":101,"props":1098,"children":1100},{"className":1099},[],[1101],{"type":46,"value":1102},"8u292-jdk-slim",{"type":46,"value":1104}," (those do not exist and fail with ",{"type":41,"tag":101,"props":1106,"children":1108},{"className":1107},[],[1109],{"type":46,"value":1110},"image not found",{"type":46,"value":1112},").\nMCR does ",{"type":41,"tag":509,"props":1114,"children":1115},{},[1116],{"type":46,"value":866},{"type":46,"value":1118}," publish a separate ",{"type":41,"tag":101,"props":1120,"children":1122},{"className":1121},[],[1123],{"type":46,"value":1124},"openjdk\u002Fjre",{"type":46,"value":1126}," repository — for the\nruntime stage of a JRE-only image, use the ",{"type":41,"tag":101,"props":1128,"children":1130},{"className":1129},[],[1131],{"type":46,"value":1132},"-distroless",{"type":46,"value":1134}," variant of the\nsame major (",{"type":41,"tag":101,"props":1136,"children":1138},{"className":1137},[],[1139],{"type":46,"value":958},{"type":46,"value":238},{"type":41,"tag":101,"props":1142,"children":1144},{"className":1143},[],[1145],{"type":46,"value":1010},{"type":46,"value":1147},", …) which ships only the JRE.",{"type":41,"tag":49,"props":1149,"children":1150},{},[1151],{"type":41,"tag":509,"props":1152,"children":1153},{},[1154,1156],{"type":46,"value":1155},".NET — ",{"type":41,"tag":101,"props":1157,"children":1159},{"className":1158},[],[1160],{"type":46,"value":1161},"mcr.microsoft.com\u002Fdotnet\u002F{sdk,aspnet,runtime}",{"type":41,"tag":62,"props":1163,"children":1164},{},[1165,1194],{"type":41,"tag":66,"props":1166,"children":1167},{},[1168],{"type":41,"tag":70,"props":1169,"children":1170},{},[1171,1179,1184,1189],{"type":41,"tag":74,"props":1172,"children":1173},{},[1174],{"type":41,"tag":101,"props":1175,"children":1177},{"className":1176},[],[1178],{"type":46,"value":886},{"type":41,"tag":74,"props":1180,"children":1181},{},[1182],{"type":46,"value":1183},"SDK",{"type":41,"tag":74,"props":1185,"children":1186},{},[1187],{"type":46,"value":1188},"ASP.NET runtime",{"type":41,"tag":74,"props":1190,"children":1191},{},[1192],{"type":46,"value":1193},"Generic runtime",{"type":41,"tag":90,"props":1195,"children":1196},{},[1197,1231],{"type":41,"tag":70,"props":1198,"children":1199},{},[1200,1204,1213,1222],{"type":41,"tag":97,"props":1201,"children":1202},{},[1203],{"type":46,"value":244},{"type":41,"tag":97,"props":1205,"children":1206},{},[1207],{"type":41,"tag":101,"props":1208,"children":1210},{"className":1209},[],[1211],{"type":46,"value":1212},"sdk:8.0-azurelinux3.0",{"type":41,"tag":97,"props":1214,"children":1215},{},[1216],{"type":41,"tag":101,"props":1217,"children":1219},{"className":1218},[],[1220],{"type":46,"value":1221},"aspnet:8.0-azurelinux3.0",{"type":41,"tag":97,"props":1223,"children":1224},{},[1225],{"type":41,"tag":101,"props":1226,"children":1228},{"className":1227},[],[1229],{"type":46,"value":1230},"runtime:8.0-azurelinux3.0",{"type":41,"tag":70,"props":1232,"children":1233},{},[1234,1239,1248,1257],{"type":41,"tag":97,"props":1235,"children":1236},{},[1237],{"type":46,"value":1238},"9.0",{"type":41,"tag":97,"props":1240,"children":1241},{},[1242],{"type":41,"tag":101,"props":1243,"children":1245},{"className":1244},[],[1246],{"type":46,"value":1247},"sdk:9.0-azurelinux3.0",{"type":41,"tag":97,"props":1249,"children":1250},{},[1251],{"type":41,"tag":101,"props":1252,"children":1254},{"className":1253},[],[1255],{"type":46,"value":1256},"aspnet:9.0-azurelinux3.0",{"type":41,"tag":97,"props":1258,"children":1259},{},[1260],{"type":41,"tag":101,"props":1261,"children":1263},{"className":1262},[],[1264],{"type":46,"value":1265},"runtime:9.0-azurelinux3.0",{"type":41,"tag":49,"props":1267,"children":1268},{},[1269],{"type":41,"tag":509,"props":1270,"children":1271},{},[1272,1274],{"type":46,"value":1273},"Node.js — ",{"type":41,"tag":101,"props":1275,"children":1277},{"className":1276},[],[1278],{"type":46,"value":1279},"mcr.microsoft.com\u002Fazurelinux\u002F{base,distroless}\u002Fnodejs",{"type":41,"tag":62,"props":1281,"children":1282},{},[1283,1305],{"type":41,"tag":66,"props":1284,"children":1285},{},[1286],{"type":41,"tag":70,"props":1287,"children":1288},{},[1289,1297,1301],{"type":41,"tag":74,"props":1290,"children":1291},{},[1292],{"type":41,"tag":101,"props":1293,"children":1295},{"className":1294},[],[1296],{"type":46,"value":886},{"type":41,"tag":74,"props":1298,"children":1299},{},[1300],{"type":46,"value":924},{"type":41,"tag":74,"props":1302,"children":1303},{},[1304],{"type":46,"value":929},{"type":41,"tag":90,"props":1306,"children":1307},{},[1308,1334,1359],{"type":41,"tag":70,"props":1309,"children":1310},{},[1311,1316,1325],{"type":41,"tag":97,"props":1312,"children":1313},{},[1314],{"type":46,"value":1315},"18",{"type":41,"tag":97,"props":1317,"children":1318},{},[1319],{"type":41,"tag":101,"props":1320,"children":1322},{"className":1321},[],[1323],{"type":46,"value":1324},"base\u002Fnodejs:18",{"type":41,"tag":97,"props":1326,"children":1327},{},[1328],{"type":41,"tag":101,"props":1329,"children":1331},{"className":1330},[],[1332],{"type":46,"value":1333},"distroless\u002Fnodejs:18",{"type":41,"tag":70,"props":1335,"children":1336},{},[1337,1341,1350],{"type":41,"tag":97,"props":1338,"children":1339},{},[1340],{"type":46,"value":251},{"type":41,"tag":97,"props":1342,"children":1343},{},[1344],{"type":41,"tag":101,"props":1345,"children":1347},{"className":1346},[],[1348],{"type":46,"value":1349},"base\u002Fnodejs:20",{"type":41,"tag":97,"props":1351,"children":1352},{},[1353],{"type":41,"tag":101,"props":1354,"children":1356},{"className":1355},[],[1357],{"type":46,"value":1358},"distroless\u002Fnodejs:20",{"type":41,"tag":70,"props":1360,"children":1361},{},[1362,1367,1376],{"type":41,"tag":97,"props":1363,"children":1364},{},[1365],{"type":46,"value":1366},"22",{"type":41,"tag":97,"props":1368,"children":1369},{},[1370],{"type":41,"tag":101,"props":1371,"children":1373},{"className":1372},[],[1374],{"type":46,"value":1375},"base\u002Fnodejs:22",{"type":41,"tag":97,"props":1377,"children":1378},{},[1379],{"type":41,"tag":101,"props":1380,"children":1382},{"className":1381},[],[1383],{"type":46,"value":1384},"distroless\u002Fnodejs:22",{"type":41,"tag":49,"props":1386,"children":1387},{},[1388],{"type":41,"tag":509,"props":1389,"children":1390},{},[1391,1393],{"type":46,"value":1392},"Python — ",{"type":41,"tag":101,"props":1394,"children":1396},{"className":1395},[],[1397],{"type":46,"value":1398},"mcr.microsoft.com\u002Fazurelinux\u002F{base,distroless}\u002Fpython",{"type":41,"tag":62,"props":1400,"children":1401},{},[1402,1424],{"type":41,"tag":66,"props":1403,"children":1404},{},[1405],{"type":41,"tag":70,"props":1406,"children":1407},{},[1408,1416,1420],{"type":41,"tag":74,"props":1409,"children":1410},{},[1411],{"type":41,"tag":101,"props":1412,"children":1414},{"className":1413},[],[1415],{"type":46,"value":886},{"type":41,"tag":74,"props":1417,"children":1418},{},[1419],{"type":46,"value":924},{"type":41,"tag":74,"props":1421,"children":1422},{},[1423],{"type":46,"value":929},{"type":41,"tag":90,"props":1425,"children":1426},{},[1427,1452],{"type":41,"tag":70,"props":1428,"children":1429},{},[1430,1434,1443],{"type":41,"tag":97,"props":1431,"children":1432},{},[1433],{"type":46,"value":258},{"type":41,"tag":97,"props":1435,"children":1436},{},[1437],{"type":41,"tag":101,"props":1438,"children":1440},{"className":1439},[],[1441],{"type":46,"value":1442},"base\u002Fpython:3.11",{"type":41,"tag":97,"props":1444,"children":1445},{},[1446],{"type":41,"tag":101,"props":1447,"children":1449},{"className":1448},[],[1450],{"type":46,"value":1451},"distroless\u002Fpython:3.11",{"type":41,"tag":70,"props":1453,"children":1454},{},[1455,1460,1469],{"type":41,"tag":97,"props":1456,"children":1457},{},[1458],{"type":46,"value":1459},"3.12",{"type":41,"tag":97,"props":1461,"children":1462},{},[1463],{"type":41,"tag":101,"props":1464,"children":1466},{"className":1465},[],[1467],{"type":46,"value":1468},"base\u002Fpython:3.12",{"type":41,"tag":97,"props":1470,"children":1471},{},[1472],{"type":41,"tag":101,"props":1473,"children":1475},{"className":1474},[],[1476],{"type":46,"value":1477},"distroless\u002Fpython:3.12",{"type":41,"tag":49,"props":1479,"children":1480},{},[1481,1483,1488,1490,1496,1497,1503,1505,1511,1512,1518],{"type":46,"value":1482},"Defaults if ",{"type":41,"tag":101,"props":1484,"children":1486},{"className":1485},[],[1487],{"type":46,"value":220},{"type":46,"value":1489}," is missing: ",{"type":41,"tag":101,"props":1491,"children":1493},{"className":1492},[],[1494],{"type":46,"value":1495},"java=21",{"type":46,"value":238},{"type":41,"tag":101,"props":1498,"children":1500},{"className":1499},[],[1501],{"type":46,"value":1502},"dotnet=8.0",{"type":46,"value":1504},",\n",{"type":41,"tag":101,"props":1506,"children":1508},{"className":1507},[],[1509],{"type":46,"value":1510},"node=20",{"type":46,"value":238},{"type":41,"tag":101,"props":1513,"children":1515},{"className":1514},[],[1516],{"type":46,"value":1517},"python=3.12",{"type":46,"value":208},{"type":41,"tag":870,"props":1520,"children":1522},{"id":1521},"g22-modernize-before-falling-back",[1523],{"type":46,"value":1524},"G2.2 — Modernize before falling back",{"type":41,"tag":49,"props":1526,"children":1527},{},[1528],{"type":46,"value":1529},"If the project targets a version not in G2.1 (typically Python 3.9\u002F3.10,\nNode 16, Java 7):",{"type":41,"tag":595,"props":1531,"children":1532},{},[1533,1543],{"type":41,"tag":599,"props":1534,"children":1535},{},[1536,1541],{"type":41,"tag":509,"props":1537,"children":1538},{},[1539],{"type":46,"value":1540},"Preferred:",{"type":46,"value":1542}," bump the build target to the nearest LTS in G2.1\n(Python → 3.11, Node → 18). Update package metadata, keep MCR images.",{"type":41,"tag":599,"props":1544,"children":1545},{},[1546,1548,1554,1556,1561],{"type":46,"value":1547},"Only if modernization is genuinely impossible, drop to G2.3 and\ndocument the reason in a ",{"type":41,"tag":101,"props":1549,"children":1551},{"className":1550},[],[1552],{"type":46,"value":1553},"# WHY-NOT-MCR:",{"type":46,"value":1555}," comment above the\noffending ",{"type":41,"tag":101,"props":1557,"children":1559},{"className":1558},[],[1560],{"type":46,"value":805},{"type":46,"value":1562}," line.",{"type":41,"tag":870,"props":1564,"children":1566},{"id":1565},"g23-allowed-non-mcr-fallbacks-closed-list",[1567],{"type":46,"value":1568},"G2.3 — Allowed non-MCR fallbacks (closed list)",{"type":41,"tag":49,"props":1570,"children":1571},{},[1572,1574,1579],{"type":46,"value":1573},"The following bases may appear when, and only when, no MCR row in G2.1\napplies. Anything not in this list MUST NOT appear in a ",{"type":41,"tag":101,"props":1575,"children":1577},{"className":1576},[],[1578],{"type":46,"value":805},{"type":46,"value":1562},{"type":41,"tag":49,"props":1581,"children":1582},{},[1583,1588,1590,1595,1597,1603,1604,1610,1611,1617,1618,1624,1625,1631,1633,1637,1639,1644,1646,1651,1653,1659,1661,1666,1668,1673,1674,1679,1680,1685,1687,1692,1693,1698,1700,1705],{"type":41,"tag":509,"props":1584,"children":1585},{},[1586],{"type":46,"value":1587},"Hard rule — build images are build-only.",{"type":46,"value":1589}," The images in the ",{"type":41,"tag":509,"props":1591,"children":1592},{},[1593],{"type":46,"value":1594},"Build\nstage",{"type":46,"value":1596}," column below (",{"type":41,"tag":101,"props":1598,"children":1600},{"className":1599},[],[1601],{"type":46,"value":1602},"maven:*",{"type":46,"value":238},{"type":41,"tag":101,"props":1605,"children":1607},{"className":1606},[],[1608],{"type":46,"value":1609},"gradle:*",{"type":46,"value":238},{"type":41,"tag":101,"props":1612,"children":1614},{"className":1613},[],[1615],{"type":46,"value":1616},"golang:*",{"type":46,"value":238},{"type":41,"tag":101,"props":1619,"children":1621},{"className":1620},[],[1622],{"type":46,"value":1623},"rust:*",{"type":46,"value":1504},{"type":41,"tag":101,"props":1626,"children":1628},{"className":1627},[],[1629],{"type":46,"value":1630},"composer:*",{"type":46,"value":1632},") are builders. They MUST NOT be the final \u002F runtime stage. Using\na non-MCR build image obligates a ",{"type":41,"tag":509,"props":1634,"children":1635},{},[1636],{"type":46,"value":665},{"type":46,"value":1638}," Dockerfile whose final\n",{"type":41,"tag":101,"props":1640,"children":1642},{"className":1641},[],[1643],{"type":46,"value":805},{"type":46,"value":1645}," is the matching ",{"type":41,"tag":509,"props":1647,"children":1648},{},[1649],{"type":46,"value":1650},"Runtime stage",{"type":46,"value":1652}," image (an MCR ",{"type":41,"tag":101,"props":1654,"children":1656},{"className":1655},[],[1657],{"type":46,"value":1658},"*-distroless",{"type":46,"value":1660}," row from\nG2.1 wherever one exists). A single-stage Dockerfile that ships a\n",{"type":41,"tag":101,"props":1662,"children":1664},{"className":1663},[],[1665],{"type":46,"value":761},{"type":46,"value":1667}," \u002F ",{"type":41,"tag":101,"props":1669,"children":1671},{"className":1670},[],[1672],{"type":46,"value":768},{"type":46,"value":1667},{"type":41,"tag":101,"props":1675,"children":1677},{"className":1676},[],[1678],{"type":46,"value":853},{"type":46,"value":1667},{"type":41,"tag":101,"props":1681,"children":1683},{"className":1682},[],[1684],{"type":46,"value":192},{"type":46,"value":1686}," builder as the runtime image is a policy\nviolation: it defeats the MCR-runtime goal and ships the full build toolchain\nplus source in the running image — even though a lone ",{"type":41,"tag":101,"props":1688,"children":1690},{"className":1689},[],[1691],{"type":46,"value":761},{"type":46,"value":462},{"type":41,"tag":101,"props":1694,"children":1696},{"className":1695},[],[1697],{"type":46,"value":768},{"type":46,"value":1699}," ",{"type":41,"tag":101,"props":1701,"children":1703},{"className":1702},[],[1704],{"type":46,"value":805},{"type":46,"value":1706},"\nlooks \"allowed\" here.",{"type":41,"tag":62,"props":1708,"children":1709},{},[1710,1730],{"type":41,"tag":66,"props":1711,"children":1712},{},[1713],{"type":41,"tag":70,"props":1714,"children":1715},{},[1716,1721,1726],{"type":41,"tag":74,"props":1717,"children":1718},{},[1719],{"type":46,"value":1720},"Stack \u002F Reason",{"type":41,"tag":74,"props":1722,"children":1723},{},[1724],{"type":46,"value":1725},"Build stage",{"type":41,"tag":74,"props":1727,"children":1728},{},[1729],{"type":46,"value":1650},{"type":41,"tag":90,"props":1731,"children":1732},{},[1733,1772,1799,1858,1884,1920,1946,1980],{"type":41,"tag":70,"props":1734,"children":1735},{},[1736,1741,1759],{"type":41,"tag":97,"props":1737,"children":1738},{},[1739],{"type":46,"value":1740},"Maven builder (MCR ships no Maven-with-JDK image)",{"type":41,"tag":97,"props":1742,"children":1743},{},[1744,1750,1752,1757],{"type":41,"tag":101,"props":1745,"children":1747},{"className":1746},[],[1748],{"type":46,"value":1749},"maven:3.9-eclipse-temurin-\u003CLV>",{"type":46,"value":1751}," (where ",{"type":41,"tag":101,"props":1753,"children":1755},{"className":1754},[],[1756],{"type":46,"value":886},{"type":46,"value":1758}," ∈ {8, 11, 17, 21})",{"type":41,"tag":97,"props":1760,"children":1761},{},[1762,1764,1770],{"type":46,"value":1763},"use the matching MCR ",{"type":41,"tag":101,"props":1765,"children":1767},{"className":1766},[],[1768],{"type":46,"value":1769},"openjdk\u002Fjdk:\u003CLV>-distroless",{"type":46,"value":1771}," for runtime",{"type":41,"tag":70,"props":1773,"children":1774},{},[1775,1780,1789],{"type":41,"tag":97,"props":1776,"children":1777},{},[1778],{"type":46,"value":1779},"Gradle builder (MCR ships no Gradle image)",{"type":41,"tag":97,"props":1781,"children":1782},{},[1783],{"type":41,"tag":101,"props":1784,"children":1786},{"className":1785},[],[1787],{"type":46,"value":1788},"gradle:\u003Cver>-jdk\u003CLV>",{"type":41,"tag":97,"props":1790,"children":1791},{},[1792,1793,1798],{"type":46,"value":1763},{"type":41,"tag":101,"props":1794,"children":1796},{"className":1795},[],[1797],{"type":46,"value":1769},{"type":46,"value":1771},{"type":41,"tag":70,"props":1800,"children":1801},{},[1802,1807,1823],{"type":41,"tag":97,"props":1803,"children":1804},{},[1805],{"type":46,"value":1806},"Java EE \u002F Jakarta EE app server (EJB, JSF, full profile — MCR ships no app server)",{"type":41,"tag":97,"props":1808,"children":1809},{},[1810,1815,1817],{"type":41,"tag":101,"props":1811,"children":1813},{"className":1812},[],[1814],{"type":46,"value":1749},{"type":46,"value":1816}," or MCR ",{"type":41,"tag":101,"props":1818,"children":1820},{"className":1819},[],[1821],{"type":46,"value":1822},"openjdk\u002Fjdk:\u003CLV>-azurelinux",{"type":41,"tag":97,"props":1824,"children":1825},{},[1826,1832,1834,1840,1842,1848,1850,1856],{"type":41,"tag":101,"props":1827,"children":1829},{"className":1828},[],[1830],{"type":46,"value":1831},"jboss\u002Fwildfly:\u003Cver>",{"type":46,"value":1833}," (WildFly), ",{"type":41,"tag":101,"props":1835,"children":1837},{"className":1836},[],[1838],{"type":46,"value":1839},"payara\u002Fserver-full:\u003Cver>",{"type":46,"value":1841}," (Payara), ",{"type":41,"tag":101,"props":1843,"children":1845},{"className":1844},[],[1846],{"type":46,"value":1847},"tomee:\u003Cver>",{"type":46,"value":1849}," (TomEE), or ",{"type":41,"tag":101,"props":1851,"children":1853},{"className":1852},[],[1854],{"type":46,"value":1855},"tomcat:\u003Cver>-jdk\u003CLV>",{"type":46,"value":1857}," (servlet-only WAR)",{"type":41,"tag":70,"props":1859,"children":1860},{},[1861,1866,1876],{"type":41,"tag":97,"props":1862,"children":1863},{},[1864],{"type":46,"value":1865},"Servlet\u002FJSP WAR with no EJB",{"type":41,"tag":97,"props":1867,"children":1868},{},[1869,1871],{"type":46,"value":1870},"MCR ",{"type":41,"tag":101,"props":1872,"children":1874},{"className":1873},[],[1875],{"type":46,"value":1822},{"type":41,"tag":97,"props":1877,"children":1878},{},[1879],{"type":41,"tag":101,"props":1880,"children":1882},{"className":1881},[],[1883],{"type":46,"value":1855},{"type":41,"tag":70,"props":1885,"children":1886},{},[1887,1892,1901],{"type":41,"tag":97,"props":1888,"children":1889},{},[1890],{"type":46,"value":1891},"Go (no MCR base)",{"type":41,"tag":97,"props":1893,"children":1894},{},[1895],{"type":41,"tag":101,"props":1896,"children":1898},{"className":1897},[],[1899],{"type":46,"value":1900},"golang:\u003CLV>-alpine",{"type":41,"tag":97,"props":1902,"children":1903},{},[1904,1910,1912,1918],{"type":41,"tag":101,"props":1905,"children":1907},{"className":1906},[],[1908],{"type":46,"value":1909},"gcr.io\u002Fdistroless\u002Fstatic-debian12:nonroot",{"type":46,"value":1911}," (CGO off) or ",{"type":41,"tag":101,"props":1913,"children":1915},{"className":1914},[],[1916],{"type":46,"value":1917},"gcr.io\u002Fdistroless\u002Fbase-debian12:nonroot",{"type":46,"value":1919}," (CGO on)",{"type":41,"tag":70,"props":1921,"children":1922},{},[1923,1928,1937],{"type":41,"tag":97,"props":1924,"children":1925},{},[1926],{"type":46,"value":1927},"Rust (no MCR base)",{"type":41,"tag":97,"props":1929,"children":1930},{},[1931],{"type":41,"tag":101,"props":1932,"children":1934},{"className":1933},[],[1935],{"type":46,"value":1936},"rust:\u003CLV>-slim",{"type":41,"tag":97,"props":1938,"children":1939},{},[1940],{"type":41,"tag":101,"props":1941,"children":1943},{"className":1942},[],[1944],{"type":46,"value":1945},"gcr.io\u002Fdistroless\u002Fcc-debian12:nonroot",{"type":41,"tag":70,"props":1947,"children":1948},{},[1949,1954,1963],{"type":41,"tag":97,"props":1950,"children":1951},{},[1952],{"type":46,"value":1953},"PHP (no MCR base)",{"type":41,"tag":97,"props":1955,"children":1956},{},[1957],{"type":41,"tag":101,"props":1958,"children":1960},{"className":1959},[],[1961],{"type":46,"value":1962},"composer:2",{"type":41,"tag":97,"props":1964,"children":1965},{},[1966,1972,1974],{"type":41,"tag":101,"props":1967,"children":1969},{"className":1968},[],[1970],{"type":46,"value":1971},"php:\u003CLV>-fpm-alpine",{"type":46,"value":1973}," or ",{"type":41,"tag":101,"props":1975,"children":1977},{"className":1976},[],[1978],{"type":46,"value":1979},"php:\u003CLV>-apache",{"type":41,"tag":70,"props":1981,"children":1982},{},[1983,1988,1997],{"type":41,"tag":97,"props":1984,"children":1985},{},[1986],{"type":46,"value":1987},"Ruby (no MCR base)",{"type":41,"tag":97,"props":1989,"children":1990},{},[1991],{"type":41,"tag":101,"props":1992,"children":1994},{"className":1993},[],[1995],{"type":46,"value":1996},"ruby:\u003CLV>-slim",{"type":41,"tag":97,"props":1998,"children":1999},{},[2000],{"type":41,"tag":101,"props":2001,"children":2003},{"className":2002},[],[2004],{"type":46,"value":1996},{"type":41,"tag":49,"props":2006,"children":2007},{},[2008,2048,2050,2056,2058,2064,2065,2071,2073,2078],{"type":41,"tag":509,"props":2009,"children":2010},{},[2011,2013,2018,2019,2025,2026,2032,2033,2039,2040,2046],{"type":46,"value":2012},"Bare JDK\u002FJRE images (",{"type":41,"tag":101,"props":2014,"children":2016},{"className":2015},[],[2017],{"type":46,"value":826},{"type":46,"value":238},{"type":41,"tag":101,"props":2020,"children":2022},{"className":2021},[],[2023],{"type":46,"value":2024},"openjdk",{"type":46,"value":238},{"type":41,"tag":101,"props":2027,"children":2029},{"className":2028},[],[2030],{"type":46,"value":2031},"adoptopenjdk",{"type":46,"value":1504},{"type":41,"tag":101,"props":2034,"children":2036},{"className":2035},[],[2037],{"type":46,"value":2038},"amazoncorretto",{"type":46,"value":238},{"type":41,"tag":101,"props":2041,"children":2043},{"className":2042},[],[2044],{"type":46,"value":2045},"ibmjava",{"type":46,"value":2047},") are NOT on this list.",{"type":46,"value":2049}," For Java versions\n8, 11, 17, 21, or 25, the MCR ",{"type":41,"tag":101,"props":2051,"children":2053},{"className":2052},[],[2054],{"type":46,"value":2055},"openjdk\u002Fjdk:\u003CLV>-{azurelinux,distroless}",{"type":46,"value":2057},"\nrow in G2.1 is mandatory — falling back to ",{"type":41,"tag":101,"props":2059,"children":2061},{"className":2060},[],[2062],{"type":46,"value":2063},"eclipse-temurin:8-jre-alpine",{"type":46,"value":1096},{"type":41,"tag":101,"props":2066,"children":2068},{"className":2067},[],[2069],{"type":46,"value":2070},"adoptopenjdk:8-jre-hotspot",{"type":46,"value":2072}," when MCR has the same major is a policy\nviolation, even with a ",{"type":41,"tag":101,"props":2074,"children":2076},{"className":2075},[],[2077],{"type":46,"value":1553},{"type":46,"value":2079}," comment.",{"type":41,"tag":49,"props":2081,"children":2082},{},[2083,2095,2097,2103,2105,2110,2111,2116,2117,2122,2123,2128,2130,2134,2135,2141,2143,2149,2150,2156,2158,2162,2164,2170,2172,2178,2180,2185],{"type":41,"tag":509,"props":2084,"children":2085},{},[2086,2088,2093],{"type":46,"value":2087},"Tag-name precision for Docker Hub ",{"type":41,"tag":101,"props":2089,"children":2091},{"className":2090},[],[2092],{"type":46,"value":761},{"type":46,"value":2094}," images:",{"type":46,"value":2096}," the only published\n",{"type":41,"tag":101,"props":2098,"children":2100},{"className":2099},[],[2101],{"type":46,"value":2102},"maven:3.9-eclipse-temurin-*",{"type":46,"value":2104}," tags are ",{"type":41,"tag":101,"props":2106,"children":2108},{"className":2107},[],[2109],{"type":46,"value":940},{"type":46,"value":238},{"type":41,"tag":101,"props":2112,"children":2114},{"className":2113},[],[2115],{"type":46,"value":966},{"type":46,"value":238},{"type":41,"tag":101,"props":2118,"children":2120},{"className":2119},[],[2121],{"type":46,"value":992},{"type":46,"value":238},{"type":41,"tag":101,"props":2124,"children":2126},{"className":2125},[],[2127],{"type":46,"value":236},{"type":46,"value":2129}," — there is\n",{"type":41,"tag":509,"props":2131,"children":2132},{},[2133],{"type":46,"value":620},{"type":46,"value":1699},{"type":41,"tag":101,"props":2136,"children":2138},{"className":2137},[],[2139],{"type":46,"value":2140},"…-jdk",{"type":46,"value":2142}," suffix on these. Tags such as ",{"type":41,"tag":101,"props":2144,"children":2146},{"className":2145},[],[2147],{"type":46,"value":2148},"maven:3.9-eclipse-temurin-8-jdk",{"type":46,"value":1096},{"type":41,"tag":101,"props":2151,"children":2153},{"className":2152},[],[2154],{"type":46,"value":2155},"maven:3.9-eclipse-temurin-17-jdk",{"type":46,"value":2157}," do ",{"type":41,"tag":509,"props":2159,"children":2160},{},[2161],{"type":46,"value":866},{"type":46,"value":2163}," exist and fail with\n",{"type":41,"tag":101,"props":2165,"children":2167},{"className":2166},[],[2168],{"type":46,"value":2169},"not found",{"type":46,"value":2171},". Use ",{"type":41,"tag":101,"props":2173,"children":2175},{"className":2174},[],[2176],{"type":46,"value":2177},"maven:3.9-eclipse-temurin-17",{"type":46,"value":2179},", not\n",{"type":41,"tag":101,"props":2181,"children":2183},{"className":2182},[],[2184],{"type":46,"value":2155},{"type":46,"value":208},{"type":41,"tag":49,"props":2187,"children":2188},{},[2189,2191,2196,2198,2203,2205,2211],{"type":46,"value":2190},"When you use any row from G2.3, prepend a ",{"type":41,"tag":101,"props":2192,"children":2194},{"className":2193},[],[2195],{"type":46,"value":1553},{"type":46,"value":2197}," comment\nabove the ",{"type":41,"tag":101,"props":2199,"children":2201},{"className":2200},[],[2202],{"type":46,"value":805},{"type":46,"value":2204}," line explaining which condition triggered the\nfallback (e.g. ",{"type":41,"tag":101,"props":2206,"children":2208},{"className":2207},[],[2209],{"type":46,"value":2210},"# WHY-NOT-MCR: Java EE app server, no MCR equivalent",{"type":46,"value":124},{"type":41,"tag":49,"props":2213,"children":2214},{},[2215,2220,2222,2228],{"type":41,"tag":509,"props":2216,"children":2217},{},[2218],{"type":46,"value":2219},"Never invent a tag.",{"type":46,"value":2221}," If you are tempted to write\n",{"type":41,"tag":101,"props":2223,"children":2225},{"className":2224},[],[2226],{"type":46,"value":2227},"mcr.microsoft.com\u002F\u003Canything>:\u003CLV>-\u003Csuffix>",{"type":46,"value":2229}," and the exact tag is not\nin G2.1, stop — either modernize per G2.2 or fall back per G2.3.",{"type":41,"tag":650,"props":2231,"children":2233},{"id":2232},"g3-construct-the-dockerfile",[2234],{"type":46,"value":2235},"G3 — Construct the Dockerfile",{"type":41,"tag":49,"props":2237,"children":2238},{},[2239],{"type":41,"tag":509,"props":2240,"children":2241},{},[2242,2244,2250,2252,2257],{"type":46,"value":2243},"Hard rule: every Dockerfile MUST contain\n",{"type":41,"tag":101,"props":2245,"children":2247},{"className":2246},[],[2248],{"type":46,"value":2249},"LABEL com.azure.containerizationassist.createdby=\"containerization-assist\"",{"type":46,"value":2251},",\nemitted on the line immediately after the ",{"type":41,"tag":101,"props":2253,"children":2255},{"className":2254},[],[2256],{"type":46,"value":805},{"type":46,"value":2258}," of the runtime \u002F final\nstage. No exceptions. A Dockerfile without this label is rejected.",{"type":41,"tag":49,"props":2260,"children":2261},{},[2262],{"type":46,"value":2263},"Apply every rule in this checklist:",{"type":41,"tag":49,"props":2265,"children":2266},{},[2267],{"type":41,"tag":509,"props":2268,"children":2269},{},[2270],{"type":46,"value":2271},"Layer\u002Fstructure",{"type":41,"tag":669,"props":2273,"children":2274},{},[2275,2311,2323,2420,2446],{"type":41,"tag":599,"props":2276,"children":2277},{},[2278,2280,2286,2288,2294,2296,2302,2304,2310],{"type":46,"value":2279},"One ",{"type":41,"tag":101,"props":2281,"children":2283},{"className":2282},[],[2284],{"type":46,"value":2285},"WORKDIR",{"type":46,"value":2287}," early (use ",{"type":41,"tag":101,"props":2289,"children":2291},{"className":2290},[],[2292],{"type":46,"value":2293},"\u002Fapp",{"type":46,"value":2295},"); never use ",{"type":41,"tag":101,"props":2297,"children":2299},{"className":2298},[],[2300],{"type":46,"value":2301},"cd",{"type":46,"value":2303}," in ",{"type":41,"tag":101,"props":2305,"children":2307},{"className":2306},[],[2308],{"type":46,"value":2309},"RUN",{"type":46,"value":208},{"type":41,"tag":599,"props":2312,"children":2313},{},[2314,2316,2321],{"type":46,"value":2315},"Copy ",{"type":41,"tag":509,"props":2317,"children":2318},{},[2319],{"type":46,"value":2320},"dependency manifests first",{"type":46,"value":2322},", install deps, then copy source — to\npreserve layer cache.",{"type":41,"tag":599,"props":2324,"children":2325},{},[2326,2331,2333,2339,2340,2346,2347,2352,2353,2359,2360,2366,2368,2373,2374,2380,2381,2387,2388,2394,2396,2402,2404,2410,2412,2418],{"type":41,"tag":509,"props":2327,"children":2328},{},[2329],{"type":46,"value":2330},"Source MUST be copied before any build\u002Fcompile command.",{"type":46,"value":2332}," Every build\nstage that runs ",{"type":41,"tag":101,"props":2334,"children":2336},{"className":2335},[],[2337],{"type":46,"value":2338},"mvn",{"type":46,"value":1667},{"type":41,"tag":101,"props":2341,"children":2343},{"className":2342},[],[2344],{"type":46,"value":2345},".\u002Fmvnw",{"type":46,"value":1667},{"type":41,"tag":101,"props":2348,"children":2350},{"className":2349},[],[2351],{"type":46,"value":768},{"type":46,"value":1667},{"type":41,"tag":101,"props":2354,"children":2356},{"className":2355},[],[2357],{"type":46,"value":2358},".\u002Fgradlew",{"type":46,"value":1667},{"type":41,"tag":101,"props":2361,"children":2363},{"className":2362},[],[2364],{"type":46,"value":2365},"npm run build",{"type":46,"value":2367},"\n\u002F ",{"type":41,"tag":101,"props":2369,"children":2371},{"className":2370},[],[2372],{"type":46,"value":729},{"type":46,"value":1667},{"type":41,"tag":101,"props":2375,"children":2377},{"className":2376},[],[2378],{"type":46,"value":2379},"dotnet publish",{"type":46,"value":1667},{"type":41,"tag":101,"props":2382,"children":2384},{"className":2383},[],[2385],{"type":46,"value":2386},"go build",{"type":46,"value":1667},{"type":41,"tag":101,"props":2389,"children":2391},{"className":2390},[],[2392],{"type":46,"value":2393},"cargo build",{"type":46,"value":2395}," MUST be preceded\nby a ",{"type":41,"tag":101,"props":2397,"children":2399},{"className":2398},[],[2400],{"type":46,"value":2401},"COPY src .\u002Fsrc",{"type":46,"value":2403}," (or equivalent — ",{"type":41,"tag":101,"props":2405,"children":2407},{"className":2406},[],[2408],{"type":46,"value":2409},"COPY . .",{"type":46,"value":2411}," for languages without\na conventional ",{"type":41,"tag":101,"props":2413,"children":2415},{"className":2414},[],[2416],{"type":46,"value":2417},"src\u002F",{"type":46,"value":2419}," layout). Skipping the source copy produces an empty\nbuild that fails with errors like \"Unable to find main class\" or\n\"no main module\" at runtime.",{"type":41,"tag":599,"props":2421,"children":2422},{},[2423,2424,2429,2431,2437,2439,2444],{"type":46,"value":660},{"type":41,"tag":101,"props":2425,"children":2427},{"className":2426},[],[2428],{"type":46,"value":2309},{"type":46,"value":2430}," chaining with ",{"type":41,"tag":101,"props":2432,"children":2434},{"className":2433},[],[2435],{"type":46,"value":2436},"&&",{"type":46,"value":2438}," to keep layers small. Aim for ≤ 6 ",{"type":41,"tag":101,"props":2440,"children":2442},{"className":2441},[],[2443],{"type":46,"value":2309},{"type":46,"value":2445},"\ninstructions.",{"type":41,"tag":599,"props":2447,"children":2448},{},[2449,2451,2457,2458,2464],{"type":46,"value":2450},"For multi-stage, give each stage a name (",{"type":41,"tag":101,"props":2452,"children":2454},{"className":2453},[],[2455],{"type":46,"value":2456},"AS build",{"type":46,"value":238},{"type":41,"tag":101,"props":2459,"children":2461},{"className":2460},[],[2462],{"type":46,"value":2463},"AS runtime",{"type":46,"value":124},{"type":41,"tag":49,"props":2466,"children":2467},{},[2468],{"type":41,"tag":509,"props":2469,"children":2470},{},[2471],{"type":46,"value":2472},"Build output & dependencies (derive, never assume)",{"type":41,"tag":49,"props":2474,"children":2475},{},[2476],{"type":46,"value":2477},"Where a build writes its artifact, and which dependencies it needs to run,\nare determined by the project's own config — not by framework convention.\nTwo recurring build failures come from guessing instead of reading:",{"type":41,"tag":669,"props":2479,"children":2480},{},[2481,2649],{"type":41,"tag":599,"props":2482,"children":2483},{},[2484,2489,2491,2497,2499],{"type":41,"tag":509,"props":2485,"children":2486},{},[2487],{"type":46,"value":2488},"Derive the build-output directory; never hardcode it.",{"type":46,"value":2490}," Before you\n",{"type":41,"tag":101,"props":2492,"children":2494},{"className":2493},[],[2495],{"type":46,"value":2496},"COPY",{"type":46,"value":2498}," build output into the runtime stage, find where the build tool\nactually writes it:",{"type":41,"tag":595,"props":2500,"children":2501},{},[2502,2592,2597],{"type":41,"tag":599,"props":2503,"children":2504},{},[2505,2507,2513,2514,2520,2521,2527,2529,2535,2536,2542,2543,2549,2550,2556,2557,2563,2564,2570,2571,2577,2578,2584,2585,2591],{"type":46,"value":2506},"Read the build tool's config for a configured output path — e.g.\n",{"type":41,"tag":101,"props":2508,"children":2510},{"className":2509},[],[2511],{"type":46,"value":2512},"build.outDir",{"type":46,"value":2303},{"type":41,"tag":101,"props":2515,"children":2517},{"className":2516},[],[2518],{"type":46,"value":2519},"vite.config.*",{"type":46,"value":238},{"type":41,"tag":101,"props":2522,"children":2524},{"className":2523},[],[2525],{"type":46,"value":2526},"compilerOptions.outDir",{"type":46,"value":2528}," in\n",{"type":41,"tag":101,"props":2530,"children":2532},{"className":2531},[],[2533],{"type":46,"value":2534},"tsconfig.json",{"type":46,"value":238},{"type":41,"tag":101,"props":2537,"children":2539},{"className":2538},[],[2540],{"type":46,"value":2541},"outputPath",{"type":46,"value":2303},{"type":41,"tag":101,"props":2544,"children":2546},{"className":2545},[],[2547],{"type":46,"value":2548},"angular.json",{"type":46,"value":238},{"type":41,"tag":101,"props":2551,"children":2553},{"className":2552},[],[2554],{"type":46,"value":2555},"distDir",{"type":46,"value":2528},{"type":41,"tag":101,"props":2558,"children":2560},{"className":2559},[],[2561],{"type":46,"value":2562},"next.config.*",{"type":46,"value":238},{"type":41,"tag":101,"props":2565,"children":2567},{"className":2566},[],[2568],{"type":46,"value":2569},"output.path",{"type":46,"value":2303},{"type":41,"tag":101,"props":2572,"children":2574},{"className":2573},[],[2575],{"type":46,"value":2576},"webpack.config.*",{"type":46,"value":238},{"type":41,"tag":101,"props":2579,"children":2581},{"className":2580},[],[2582],{"type":46,"value":2583},"buildDir",{"type":46,"value":2528},{"type":41,"tag":101,"props":2586,"children":2588},{"className":2587},[],[2589],{"type":46,"value":2590},"nuxt.config.*",{"type":46,"value":208},{"type":41,"tag":599,"props":2593,"children":2594},{},[2595],{"type":46,"value":2596},"If none is set, use that tool's documented default.",{"type":41,"tag":599,"props":2598,"children":2599},{},[2600,2602,2607,2609,2615,2617,2623,2625,2631,2633,2639,2641,2647],{"type":46,"value":2601},"If still unsure, run the build in the build stage and ",{"type":41,"tag":101,"props":2603,"children":2605},{"className":2604},[],[2606],{"type":46,"value":2496},{"type":46,"value":2608}," the\ndirectory it actually produced.\n",{"type":41,"tag":101,"props":2610,"children":2612},{"className":2611},[],[2613],{"type":46,"value":2614},"build\u002F",{"type":46,"value":2616}," is only Create React App's default. Vite, Vue CLI, Angular and\nmost bundlers emit to ",{"type":41,"tag":101,"props":2618,"children":2620},{"className":2619},[],[2621],{"type":46,"value":2622},"dist\u002F",{"type":46,"value":2624},"; Next.js to ",{"type":41,"tag":101,"props":2626,"children":2628},{"className":2627},[],[2629],{"type":46,"value":2630},".next\u002F",{"type":46,"value":2632},". Hardcoding\n",{"type":41,"tag":101,"props":2634,"children":2636},{"className":2635},[],[2637],{"type":46,"value":2638},"COPY build\u002F ...",{"type":46,"value":2640}," fails with ",{"type":41,"tag":101,"props":2642,"children":2644},{"className":2643},[],[2645],{"type":46,"value":2646},"\"\u002Fapp\u002Fbuild\": not found",{"type":46,"value":2648}," on any of them.",{"type":41,"tag":599,"props":2650,"children":2651},{},[2652,2657,2659,2664,2665,2671,2672,2678,2679,2685,2686,2692,2694,2700,2702,2708,2709,2715,2717,2721,2722,2728,2730,2736,2738,2744,2746,2751,2753,2759,2761,2766],{"type":41,"tag":509,"props":2653,"children":2654},{},[2655],{"type":46,"value":2656},"Install full dependencies in the build stage; prune only for runtime.",{"type":46,"value":2658},"\nCompilers and bundlers (",{"type":41,"tag":101,"props":2660,"children":2662},{"className":2661},[],[2663],{"type":46,"value":729},{"type":46,"value":238},{"type":41,"tag":101,"props":2666,"children":2668},{"className":2667},[],[2669],{"type":46,"value":2670},"vite",{"type":46,"value":238},{"type":41,"tag":101,"props":2673,"children":2675},{"className":2674},[],[2676],{"type":46,"value":2677},"webpack",{"type":46,"value":238},{"type":41,"tag":101,"props":2680,"children":2682},{"className":2681},[],[2683],{"type":46,"value":2684},"rollup",{"type":46,"value":238},{"type":41,"tag":101,"props":2687,"children":2689},{"className":2688},[],[2690],{"type":46,"value":2691},"esbuild",{"type":46,"value":2693},")\nalmost always live in ",{"type":41,"tag":101,"props":2695,"children":2697},{"className":2696},[],[2698],{"type":46,"value":2699},"devDependencies",{"type":46,"value":2701},". In the build stage run a full\ninstall (",{"type":41,"tag":101,"props":2703,"children":2705},{"className":2704},[],[2706],{"type":46,"value":2707},"npm ci",{"type":46,"value":1667},{"type":41,"tag":101,"props":2710,"children":2712},{"className":2711},[],[2713],{"type":46,"value":2714},"npm install",{"type":46,"value":2716}," with ",{"type":41,"tag":509,"props":2718,"children":2719},{},[2720],{"type":46,"value":620},{"type":46,"value":1699},{"type":41,"tag":101,"props":2723,"children":2725},{"className":2724},[],[2726],{"type":46,"value":2727},"--omit=dev",{"type":46,"value":2729}," \u002F\n",{"type":41,"tag":101,"props":2731,"children":2733},{"className":2732},[],[2734],{"type":46,"value":2735},"--production",{"type":46,"value":2737},"). Running ",{"type":41,"tag":101,"props":2739,"children":2741},{"className":2740},[],[2742],{"type":46,"value":2743},"npm ci --omit=dev",{"type":46,"value":2745}," before ",{"type":41,"tag":101,"props":2747,"children":2749},{"className":2748},[],[2750],{"type":46,"value":2365},{"type":46,"value":2752},"\nremoves the compiler and fails with ",{"type":41,"tag":101,"props":2754,"children":2756},{"className":2755},[],[2757],{"type":46,"value":2758},"tsc: not found",{"type":46,"value":2760}," \u002F exit 127. Only the\n",{"type":41,"tag":509,"props":2762,"children":2763},{},[2764],{"type":46,"value":2765},"runtime",{"type":46,"value":2767}," stage may drop dev deps — or, better, copy just the built\nartifact into a clean runtime image and install nothing there.",{"type":41,"tag":49,"props":2769,"children":2770},{},[2771],{"type":46,"value":2772},"These two rules hold for any compiled or bundled stack — present or future\n— so they replace per-framework \"copy from X\" recipes rather than adding to\nthem.",{"type":41,"tag":49,"props":2774,"children":2775},{},[2776],{"type":41,"tag":509,"props":2777,"children":2778},{},[2779],{"type":46,"value":2780},"Security baseline (mandatory)",{"type":41,"tag":669,"props":2782,"children":2783},{},[2784,2876,2985,3004,3024],{"type":41,"tag":599,"props":2785,"children":2786},{},[2787,2789,2795,2797],{"type":46,"value":2788},"Final stage MUST end with a ",{"type":41,"tag":101,"props":2790,"children":2792},{"className":2791},[],[2793],{"type":46,"value":2794},"USER",{"type":46,"value":2796}," instruction set to a non-root user.",{"type":41,"tag":669,"props":2798,"children":2799},{},[2800],{"type":41,"tag":599,"props":2801,"children":2802},{},[2803,2805,2811,2812,2818,2820,2825,2827,2832,2834,2840,2842],{"type":46,"value":2804},"If the base image already provides one (e.g. ",{"type":41,"tag":101,"props":2806,"children":2808},{"className":2807},[],[2809],{"type":46,"value":2810},"nonroot",{"type":46,"value":238},{"type":41,"tag":101,"props":2813,"children":2815},{"className":2814},[],[2816],{"type":46,"value":2817},"appuser",{"type":46,"value":2819},"), use\nit; otherwise create one with ",{"type":41,"tag":509,"props":2821,"children":2822},{},[2823],{"type":46,"value":2824},"two separate instructions",{"type":46,"value":2826}," (",{"type":41,"tag":101,"props":2828,"children":2830},{"className":2829},[],[2831],{"type":46,"value":2794},{"type":46,"value":2833}," is a\nDockerfile instruction, not a shell command — it cannot be chained after\n",{"type":41,"tag":101,"props":2835,"children":2837},{"className":2836},[],[2838],{"type":46,"value":2839},"RUN ... &&",{"type":46,"value":2841},"):\n",{"type":41,"tag":669,"props":2843,"children":2844},{},[2845,2862],{"type":41,"tag":599,"props":2846,"children":2847},{},[2848,2850],{"type":46,"value":2849},"Alpine:\n",{"type":41,"tag":2851,"props":2852,"children":2856},"pre",{"className":2853,"code":2855,"language":46},[2854],"language-text","RUN adduser -D -u 10001 appuser\nUSER appuser\n",[2857],{"type":41,"tag":101,"props":2858,"children":2860},{"__ignoreMap":2859},"",[2861],{"type":46,"value":2855},{"type":41,"tag":599,"props":2863,"children":2864},{},[2865,2867],{"type":46,"value":2866},"Debian \u002F Azure Linux:\n",{"type":41,"tag":2851,"props":2868,"children":2871},{"className":2869,"code":2870,"language":46},[2854],"RUN useradd -m -u 10001 appuser\nUSER appuser\n",[2872],{"type":41,"tag":101,"props":2873,"children":2874},{"__ignoreMap":2859},[2875],{"type":46,"value":2870},{"type":41,"tag":599,"props":2877,"children":2878},{},[2879,2884,2886,2891,2893,2899,2900,2906,2907,2913,2914,2920,2921,2927,2928,2934,2935,2941,2942,2948,2949,2955,2956,2962,2963,2969,2970,2976,2977,2983],{"type":41,"tag":509,"props":2880,"children":2881},{},[2882],{"type":46,"value":2883},"Never",{"type":46,"value":2885}," include any of these in ",{"type":41,"tag":101,"props":2887,"children":2889},{"className":2888},[],[2890],{"type":46,"value":452},{"type":46,"value":2892},":\n",{"type":41,"tag":101,"props":2894,"children":2896},{"className":2895},[],[2897],{"type":46,"value":2898},"PASSWORD",{"type":46,"value":238},{"type":41,"tag":101,"props":2901,"children":2903},{"className":2902},[],[2904],{"type":46,"value":2905},"PASSWD",{"type":46,"value":238},{"type":41,"tag":101,"props":2908,"children":2910},{"className":2909},[],[2911],{"type":46,"value":2912},"TOKEN",{"type":46,"value":238},{"type":41,"tag":101,"props":2915,"children":2917},{"className":2916},[],[2918],{"type":46,"value":2919},"SECRET",{"type":46,"value":238},{"type":41,"tag":101,"props":2922,"children":2924},{"className":2923},[],[2925],{"type":46,"value":2926},"CREDENTIAL",{"type":46,"value":238},{"type":41,"tag":101,"props":2929,"children":2931},{"className":2930},[],[2932],{"type":46,"value":2933},"API_KEY",{"type":46,"value":1504},{"type":41,"tag":101,"props":2936,"children":2938},{"className":2937},[],[2939],{"type":46,"value":2940},"PRIVATE_KEY",{"type":46,"value":238},{"type":41,"tag":101,"props":2943,"children":2945},{"className":2944},[],[2946],{"type":46,"value":2947},"ACCESS_KEY",{"type":46,"value":238},{"type":41,"tag":101,"props":2950,"children":2952},{"className":2951},[],[2953],{"type":46,"value":2954},"*_DSN",{"type":46,"value":238},{"type":41,"tag":101,"props":2957,"children":2959},{"className":2958},[],[2960],{"type":46,"value":2961},"DATABASE_URL",{"type":46,"value":238},{"type":41,"tag":101,"props":2964,"children":2966},{"className":2965},[],[2967],{"type":46,"value":2968},"CONNECTION_STRING",{"type":46,"value":1504},{"type":41,"tag":101,"props":2971,"children":2973},{"className":2972},[],[2974],{"type":46,"value":2975},"REDIS_URL",{"type":46,"value":238},{"type":41,"tag":101,"props":2978,"children":2980},{"className":2979},[],[2981],{"type":46,"value":2982},"MONGODB_URI",{"type":46,"value":2984},". These get injected at runtime via K8s Secrets.",{"type":41,"tag":599,"props":2986,"children":2987},{},[2988,2990,2996,2997,3003],{"type":46,"value":2989},"Do NOT run ",{"type":41,"tag":101,"props":2991,"children":2993},{"className":2992},[],[2994],{"type":46,"value":2995},"apt-get upgrade",{"type":46,"value":1667},{"type":41,"tag":101,"props":2998,"children":3000},{"className":2999},[],[3001],{"type":46,"value":3002},"apt-get dist-upgrade",{"type":46,"value":208},{"type":41,"tag":599,"props":3005,"children":3006},{},[3007,3009,3015,3017,3023],{"type":46,"value":3008},"If using ",{"type":41,"tag":101,"props":3010,"children":3012},{"className":3011},[],[3013],{"type":46,"value":3014},"apt-get install",{"type":46,"value":3016},", clean up:\n",{"type":41,"tag":101,"props":3018,"children":3020},{"className":3019},[],[3021],{"type":46,"value":3022},"apt-get update && apt-get install -y --no-install-recommends \u003Cpkgs> && rm -rf \u002Fvar\u002Flib\u002Fapt\u002Flists\u002F*",{"type":46,"value":208},{"type":41,"tag":599,"props":3025,"children":3026},{},[3027,3032,3034,3040,3042,3241,3245,3256,3258,3264,3266,3272,3273,3279,3281,3287,3288,3293,3295,3300],{"type":41,"tag":509,"props":3028,"children":3029},{},[3030],{"type":46,"value":3031},"Package manager per base image",{"type":46,"value":3033}," — using the wrong one fails with ",{"type":41,"tag":101,"props":3035,"children":3037},{"className":3036},[],[3038],{"type":46,"value":3039},"command not found",{"type":46,"value":3041},":",{"type":41,"tag":62,"props":3043,"children":3044},{},[3045,3066],{"type":41,"tag":66,"props":3046,"children":3047},{},[3048],{"type":41,"tag":70,"props":3049,"children":3050},{},[3051,3056,3061],{"type":41,"tag":74,"props":3052,"children":3053},{},[3054],{"type":46,"value":3055},"Base image family",{"type":41,"tag":74,"props":3057,"children":3058},{},[3059],{"type":46,"value":3060},"Package manager",{"type":41,"tag":74,"props":3062,"children":3063},{},[3064],{"type":46,"value":3065},"Install one-liner",{"type":41,"tag":90,"props":3067,"children":3068},{},[3069,3123,3155,3199],{"type":41,"tag":70,"props":3070,"children":3071},{},[3072,3102,3114],{"type":41,"tag":97,"props":3073,"children":3074},{},[3075,3081,3082,3088,3089,3095,3096],{"type":41,"tag":101,"props":3076,"children":3078},{"className":3077},[],[3079],{"type":46,"value":3080},"mcr.microsoft.com\u002Fopenjdk\u002Fjdk:*-azurelinux",{"type":46,"value":238},{"type":41,"tag":101,"props":3083,"children":3085},{"className":3084},[],[3086],{"type":46,"value":3087},"mcr.microsoft.com\u002Fazurelinux\u002Fbase\u002F*",{"type":46,"value":238},{"type":41,"tag":101,"props":3090,"children":3092},{"className":3091},[],[3093],{"type":46,"value":3094},"mcr.microsoft.com\u002Fdotnet\u002F*-azurelinux*",{"type":46,"value":238},{"type":41,"tag":101,"props":3097,"children":3099},{"className":3098},[],[3100],{"type":46,"value":3101},"*-mariner*",{"type":41,"tag":97,"props":3103,"children":3104},{},[3105],{"type":41,"tag":509,"props":3106,"children":3107},{},[3108],{"type":41,"tag":101,"props":3109,"children":3111},{"className":3110},[],[3112],{"type":46,"value":3113},"tdnf",{"type":41,"tag":97,"props":3115,"children":3116},{},[3117],{"type":41,"tag":101,"props":3118,"children":3120},{"className":3119},[],[3121],{"type":46,"value":3122},"tdnf install -y \u003Cpkg> && tdnf clean all",{"type":41,"tag":70,"props":3124,"children":3125},{},[3126,3142,3152],{"type":41,"tag":97,"props":3127,"children":3128},{},[3129,3135,3136],{"type":41,"tag":101,"props":3130,"children":3132},{"className":3131},[],[3133],{"type":46,"value":3134},"mcr.microsoft.com\u002F*-distroless",{"type":46,"value":238},{"type":41,"tag":101,"props":3137,"children":3139},{"className":3138},[],[3140],{"type":46,"value":3141},"gcr.io\u002Fdistroless\u002F*",{"type":41,"tag":97,"props":3143,"children":3144},{},[3145,3150],{"type":41,"tag":509,"props":3146,"children":3147},{},[3148],{"type":46,"value":3149},"none",{"type":46,"value":3151}," — no shell, no package manager. Install in the build stage instead and copy artifacts in.",{"type":41,"tag":97,"props":3153,"children":3154},{},[],{"type":41,"tag":70,"props":3156,"children":3157},{},[3158,3181,3190],{"type":41,"tag":97,"props":3159,"children":3160},{},[3161,3167,3168,3174,3175],{"type":41,"tag":101,"props":3162,"children":3164},{"className":3163},[],[3165],{"type":46,"value":3166},"eclipse-temurin:*-jre-alpine",{"type":46,"value":238},{"type":41,"tag":101,"props":3169,"children":3171},{"className":3170},[],[3172],{"type":46,"value":3173},"node:*-alpine",{"type":46,"value":238},{"type":41,"tag":101,"props":3176,"children":3178},{"className":3177},[],[3179],{"type":46,"value":3180},"python:*-alpine",{"type":41,"tag":97,"props":3182,"children":3183},{},[3184],{"type":41,"tag":101,"props":3185,"children":3187},{"className":3186},[],[3188],{"type":46,"value":3189},"apk",{"type":41,"tag":97,"props":3191,"children":3192},{},[3193],{"type":41,"tag":101,"props":3194,"children":3196},{"className":3195},[],[3197],{"type":46,"value":3198},"apk add --no-cache \u003Cpkg>",{"type":41,"tag":70,"props":3200,"children":3201},{},[3202,3227,3236],{"type":41,"tag":97,"props":3203,"children":3204},{},[3205,3211,3212,3218,3219,3225],{"type":41,"tag":101,"props":3206,"children":3208},{"className":3207},[],[3209],{"type":46,"value":3210},"eclipse-temurin:*-jdk",{"type":46,"value":238},{"type":41,"tag":101,"props":3213,"children":3215},{"className":3214},[],[3216],{"type":46,"value":3217},"python:*-slim",{"type":46,"value":238},{"type":41,"tag":101,"props":3220,"children":3222},{"className":3221},[],[3223],{"type":46,"value":3224},"node:*",{"type":46,"value":3226}," (Debian-based)",{"type":41,"tag":97,"props":3228,"children":3229},{},[3230],{"type":41,"tag":101,"props":3231,"children":3233},{"className":3232},[],[3234],{"type":46,"value":3235},"apt-get",{"type":41,"tag":97,"props":3237,"children":3238},{},[3239],{"type":46,"value":3240},"as above",{"type":41,"tag":3242,"props":3243,"children":3244},"br",{},[],{"type":41,"tag":509,"props":3246,"children":3247},{},[3248,3254],{"type":41,"tag":101,"props":3249,"children":3251},{"className":3250},[],[3252],{"type":46,"value":3253},"microdnf",{"type":46,"value":3255}," does NOT exist on Azure Linux \u002F Mariner.",{"type":46,"value":3257}," It ships on RHEL\u002FUBI\nonly. Using ",{"type":41,"tag":101,"props":3259,"children":3261},{"className":3260},[],[3262],{"type":46,"value":3263},"microdnf install …",{"type":46,"value":3265}," on any ",{"type":41,"tag":101,"props":3267,"children":3269},{"className":3268},[],[3270],{"type":46,"value":3271},"*-azurelinux",{"type":46,"value":1973},{"type":41,"tag":101,"props":3274,"children":3276},{"className":3275},[],[3277],{"type":46,"value":3278},"*-mariner",{"type":46,"value":3280},"\nbase image fails with ",{"type":41,"tag":101,"props":3282,"children":3284},{"className":3283},[],[3285],{"type":46,"value":3286},"microdnf: command not found",{"type":46,"value":2171},{"type":41,"tag":101,"props":3289,"children":3291},{"className":3290},[],[3292],{"type":46,"value":3113},{"type":46,"value":3294}," instead\n— same syntax, same flags. Do NOT use ",{"type":41,"tag":101,"props":3296,"children":3298},{"className":3297},[],[3299],{"type":46,"value":3235},{"type":46,"value":3301}," on Azure Linux either.",{"type":41,"tag":49,"props":3303,"children":3304},{},[3305,3310,3312,3317,3319,3324,3326,3332,3334,3340,3341,3347,3349,3355,3357,3363,3365,3370,3372,3378],{"type":41,"tag":509,"props":3306,"children":3307},{},[3308],{"type":46,"value":3309},"Distroless final-stage rules (hard):",{"type":46,"value":3311}," when the runtime stage ",{"type":41,"tag":101,"props":3313,"children":3315},{"className":3314},[],[3316],{"type":46,"value":805},{"type":46,"value":3318},"\nends in ",{"type":41,"tag":101,"props":3320,"children":3322},{"className":3321},[],[3323],{"type":46,"value":1132},{"type":46,"value":3325}," (or starts with ",{"type":41,"tag":101,"props":3327,"children":3329},{"className":3328},[],[3330],{"type":46,"value":3331},"gcr.io\u002Fdistroless\u002F",{"type":46,"value":3333},"), the image\nhas no shell, no package manager, no ",{"type":41,"tag":101,"props":3335,"children":3337},{"className":3336},[],[3338],{"type":46,"value":3339},"useradd",{"type":46,"value":462},{"type":41,"tag":101,"props":3342,"children":3344},{"className":3343},[],[3345],{"type":46,"value":3346},"adduser",{"type":46,"value":3348},", no ",{"type":41,"tag":101,"props":3350,"children":3352},{"className":3351},[],[3353],{"type":46,"value":3354},"chmod",{"type":46,"value":3356},",\nno ",{"type":41,"tag":101,"props":3358,"children":3360},{"className":3359},[],[3361],{"type":46,"value":3362},"mkdir",{"type":46,"value":3364},". Any ",{"type":41,"tag":101,"props":3366,"children":3368},{"className":3367},[],[3369],{"type":46,"value":2309},{"type":46,"value":3371}," in the distroless stage will fail at build time\nwith ",{"type":41,"tag":101,"props":3373,"children":3375},{"className":3374},[],[3376],{"type":46,"value":3377},"exec: \"\u002Fbin\u002Fsh\": stat \u002Fbin\u002Fsh: no such file or directory",{"type":46,"value":3379},". Rules:",{"type":41,"tag":669,"props":3381,"children":3382},{},[3383,3407,3577,3616,3639],{"type":41,"tag":599,"props":3384,"children":3385},{},[3386,3398,3400,3405],{"type":41,"tag":509,"props":3387,"children":3388},{},[3389,3391,3396],{"type":46,"value":3390},"No ",{"type":41,"tag":101,"props":3392,"children":3394},{"className":3393},[],[3395],{"type":46,"value":2309},{"type":46,"value":3397}," instructions in the distroless stage.",{"type":46,"value":3399}," Do all setup\n(chmod, package install, user creation) in the build stage and ",{"type":41,"tag":101,"props":3401,"children":3403},{"className":3402},[],[3404],{"type":46,"value":2496},{"type":46,"value":3406},"\nthe prepared artifacts in.",{"type":41,"tag":599,"props":3408,"children":3409},{},[3410,3430,3432,3437,3439],{"type":41,"tag":509,"props":3411,"children":3412},{},[3413,3415,3421,3422,3428],{"type":46,"value":3414},"Do not try to ",{"type":41,"tag":101,"props":3416,"children":3418},{"className":3417},[],[3419],{"type":46,"value":3420},"RUN useradd",{"type":46,"value":1667},{"type":41,"tag":101,"props":3423,"children":3425},{"className":3424},[],[3426],{"type":46,"value":3427},"RUN adduser",{"type":46,"value":3429}," on distroless",{"type":46,"value":3431}," (no shell).\nSet the user with a numeric ",{"type":41,"tag":101,"props":3433,"children":3435},{"className":3434},[],[3436],{"type":46,"value":2794},{"type":46,"value":3438}," instead — which non-root user the base\nprovides depends on the image:\n",{"type":41,"tag":669,"props":3440,"children":3441},{},[3442,3482],{"type":41,"tag":599,"props":3443,"children":3444},{},[3445,3450,3451,3457,3459,3465,3467,3473,3475,3481],{"type":41,"tag":509,"props":3446,"children":3447},{},[3448],{"type":46,"value":3449},"Node.js \u002F Python",{"type":46,"value":2826},{"type":41,"tag":101,"props":3452,"children":3454},{"className":3453},[],[3455],{"type":46,"value":3456},"mcr.microsoft.com\u002Fazurelinux\u002Fdistroless\u002F{nodejs,python}",{"type":46,"value":3458},")\npredefine a non-root user ",{"type":41,"tag":101,"props":3460,"children":3462},{"className":3461},[],[3463],{"type":46,"value":3464},"app",{"type":46,"value":3466}," at UID 1000 — emit ",{"type":41,"tag":101,"props":3468,"children":3470},{"className":3469},[],[3471],{"type":46,"value":3472},"USER 1000",{"type":46,"value":3474}," (preferred)\nor ",{"type":41,"tag":101,"props":3476,"children":3478},{"className":3477},[],[3479],{"type":46,"value":3480},"USER app",{"type":46,"value":208},{"type":41,"tag":599,"props":3483,"children":3484},{},[3485,3490,3491,3497,3499,3504,3506,3511,3513,3518,3520,3524,3526,3531,3533,3539,3541,3547,3549,3554,3555,3560,3562,3567,3569,3575],{"type":41,"tag":509,"props":3486,"children":3487},{},[3488],{"type":46,"value":3489},"Java",{"type":46,"value":2826},{"type":41,"tag":101,"props":3492,"children":3494},{"className":3493},[],[3495],{"type":46,"value":3496},"mcr.microsoft.com\u002Fopenjdk\u002Fjdk:\u003CLV>-distroless",{"type":46,"value":3498},") does ",{"type":41,"tag":509,"props":3500,"children":3501},{},[3502],{"type":46,"value":3503},"NOT",{"type":46,"value":3505},"\npredefine a non-root user — its default is root, and there is no ",{"type":41,"tag":101,"props":3507,"children":3509},{"className":3508},[],[3510],{"type":46,"value":3464},{"type":46,"value":3512},"\nuser. Emit the numeric ",{"type":41,"tag":101,"props":3514,"children":3516},{"className":3515},[],[3517],{"type":46,"value":3472},{"type":46,"value":3519}," (do ",{"type":41,"tag":509,"props":3521,"children":3522},{},[3523],{"type":46,"value":866},{"type":46,"value":3525}," write ",{"type":41,"tag":101,"props":3527,"children":3529},{"className":3528},[],[3530],{"type":46,"value":3480},{"type":46,"value":3532},": that name\ndoes not exist on the Java distroless image, and a Kubernetes\n",{"type":41,"tag":101,"props":3534,"children":3536},{"className":3535},[],[3537],{"type":46,"value":3538},"runAsNonRoot",{"type":46,"value":3540}," securityContext then fails at deploy with\n",{"type":41,"tag":101,"props":3542,"children":3544},{"className":3543},[],[3545],{"type":46,"value":3546},"CreateContainerConfigError: ... non-numeric user",{"type":46,"value":3548},").\nAlways prefer the ",{"type":41,"tag":509,"props":3550,"children":3551},{},[3552],{"type":46,"value":3553},"numeric",{"type":46,"value":1699},{"type":41,"tag":101,"props":3556,"children":3558},{"className":3557},[],[3559],{"type":46,"value":3472},{"type":46,"value":3561}," on distroless: a numeric UID\nsatisfies ",{"type":41,"tag":101,"props":3563,"children":3565},{"className":3564},[],[3566],{"type":46,"value":3538},{"type":46,"value":3568}," without needing an ",{"type":41,"tag":101,"props":3570,"children":3572},{"className":3571},[],[3573],{"type":46,"value":3574},"\u002Fetc\u002Fpasswd",{"type":46,"value":3576}," entry.",{"type":41,"tag":599,"props":3578,"children":3579},{},[3580,3599,3601,3607,3608,3614],{"type":41,"tag":509,"props":3581,"children":3582},{},[3583,3584,3590,3591,3597],{"type":46,"value":3414},{"type":41,"tag":101,"props":3585,"children":3587},{"className":3586},[],[3588],{"type":46,"value":3589},"RUN chmod",{"type":46,"value":1667},{"type":41,"tag":101,"props":3592,"children":3594},{"className":3593},[],[3595],{"type":46,"value":3596},"RUN chown",{"type":46,"value":3598}," on distroless.",{"type":46,"value":3600}," Set the\nmode\u002Fowner with ",{"type":41,"tag":101,"props":3602,"children":3604},{"className":3603},[],[3605],{"type":46,"value":3606},"COPY --chmod=…",{"type":46,"value":1667},{"type":41,"tag":101,"props":3609,"children":3611},{"className":3610},[],[3612],{"type":46,"value":3613},"COPY --chown=app:app …",{"type":46,"value":3615}," instead\n(BuildKit syntax, supported by default).",{"type":41,"tag":599,"props":3617,"children":3618},{},[3619,3630,3632,3638],{"type":41,"tag":509,"props":3620,"children":3621},{},[3622,3624],{"type":46,"value":3623},"Skip ",{"type":41,"tag":101,"props":3625,"children":3627},{"className":3626},[],[3628],{"type":46,"value":3629},"HEALTHCHECK",{"type":46,"value":3631}," on distroless — there is no shell to run the\nprobe command. Document with ",{"type":41,"tag":101,"props":3633,"children":3635},{"className":3634},[],[3636],{"type":46,"value":3637},"# HEALTHCHECK: skipped — distroless, use Kubernetes liveness\u002Freadiness probe",{"type":46,"value":208},{"type":41,"tag":599,"props":3640,"children":3641},{},[3642,3644,3649,3651,3657,3658,3664,3665,3671,3673,3679,3681,3687],{"type":46,"value":3643},"Pin ",{"type":41,"tag":509,"props":3645,"children":3646},{},[3647],{"type":46,"value":3648},"major",{"type":46,"value":3650}," version tags (",{"type":41,"tag":101,"props":3652,"children":3654},{"className":3653},[],[3655],{"type":46,"value":3656},":21",{"type":46,"value":238},{"type":41,"tag":101,"props":3659,"children":3661},{"className":3660},[],[3662],{"type":46,"value":3663},":8.0",{"type":46,"value":238},{"type":41,"tag":101,"props":3666,"children":3668},{"className":3667},[],[3669],{"type":46,"value":3670},":3.11",{"type":46,"value":3672},"), never ",{"type":41,"tag":101,"props":3674,"children":3676},{"className":3675},[],[3677],{"type":46,"value":3678},":latest",{"type":46,"value":3680}," and\nnever floating patch versions like ",{"type":41,"tag":101,"props":3682,"children":3684},{"className":3683},[],[3685],{"type":46,"value":3686},"21.0.3",{"type":46,"value":208},{"type":41,"tag":49,"props":3689,"children":3690},{},[3691],{"type":41,"tag":509,"props":3692,"children":3693},{},[3694],{"type":46,"value":3695},"Quality baseline",{"type":41,"tag":669,"props":3697,"children":3698},{},[3699,3755,3766],{"type":41,"tag":599,"props":3700,"children":3701},{},[3702,3704,3709,3711],{"type":46,"value":3703},"Include ",{"type":41,"tag":101,"props":3705,"children":3707},{"className":3706},[],[3708],{"type":46,"value":3629},{"type":46,"value":3710}," for long-running services (web servers, workers).\nPick the simplest probe the runtime image actually supports:\n",{"type":41,"tag":669,"props":3712,"children":3713},{},[3714,3733,3744],{"type":41,"tag":599,"props":3715,"children":3716},{},[3717,3719,3725,3727],{"type":46,"value":3718},"Has ",{"type":41,"tag":101,"props":3720,"children":3722},{"className":3721},[],[3723],{"type":46,"value":3724},"curl",{"type":46,"value":3726},": ",{"type":41,"tag":101,"props":3728,"children":3730},{"className":3729},[],[3731],{"type":46,"value":3732},"HEALTHCHECK CMD curl -fsS http:\u002F\u002Flocalhost:\u003Cport>\u002Fhealth || exit 1",{"type":41,"tag":599,"props":3734,"children":3735},{},[3736,3738],{"type":46,"value":3737},"Alpine \u002F busybox (no curl, has wget): ",{"type":41,"tag":101,"props":3739,"children":3741},{"className":3740},[],[3742],{"type":46,"value":3743},"HEALTHCHECK CMD wget --spider -q http:\u002F\u002Flocalhost:\u003Cport>\u002Fhealth || exit 1",{"type":41,"tag":599,"props":3745,"children":3746},{},[3747,3749],{"type":46,"value":3748},"Distroless \u002F no shell: skip HEALTHCHECK and add a comment ",{"type":41,"tag":101,"props":3750,"children":3752},{"className":3751},[],[3753],{"type":46,"value":3754},"# HEALTHCHECK: skipped — distroless image has no shell. Use Kubernetes liveness\u002Freadiness probe.",{"type":41,"tag":599,"props":3756,"children":3757},{},[3758,3764],{"type":41,"tag":101,"props":3759,"children":3761},{"className":3760},[],[3762],{"type":46,"value":3763},"EXPOSE \u003Cport>",{"type":46,"value":3765}," for the primary listener.",{"type":41,"tag":599,"props":3767,"children":3768},{},[3769,3775,3776,3781,3782,3788],{"type":41,"tag":101,"props":3770,"children":3772},{"className":3771},[],[3773],{"type":46,"value":3774},"CMD",{"type":46,"value":2303},{"type":41,"tag":509,"props":3777,"children":3778},{},[3779],{"type":46,"value":3780},"exec form",{"type":46,"value":2826},{"type":41,"tag":101,"props":3783,"children":3785},{"className":3784},[],[3786],{"type":46,"value":3787},"[\"binary\",\"arg\"]",{"type":46,"value":3789},"), required for distroless.",{"type":41,"tag":49,"props":3791,"children":3792},{},[3793],{"type":41,"tag":509,"props":3794,"children":3795},{},[3796],{"type":46,"value":3797},"Env variables",{"type":41,"tag":669,"props":3799,"children":3800},{},[3801,3850],{"type":41,"tag":599,"props":3802,"children":3803},{},[3804,3806,3811,3813,3818,3819,3824,3826,3832,3834,3840,3842,3848],{"type":46,"value":3805},"For each entry in ",{"type":41,"tag":101,"props":3807,"children":3809},{"className":3808},[],[3810],{"type":46,"value":430},{"type":46,"value":3812}," classified as ",{"type":41,"tag":101,"props":3814,"children":3816},{"className":3815},[],[3817],{"type":46,"value":460},{"type":46,"value":1973},{"type":41,"tag":101,"props":3820,"children":3822},{"className":3821},[],[3823],{"type":46,"value":468},{"type":46,"value":3825},":\nif it has a ",{"type":41,"tag":101,"props":3827,"children":3829},{"className":3828},[],[3830],{"type":46,"value":3831},"defaultValue",{"type":46,"value":3833},", emit ",{"type":41,"tag":101,"props":3835,"children":3837},{"className":3836},[],[3838],{"type":46,"value":3839},"ENV NAME=\u003Cvalue>",{"type":46,"value":3841},"; otherwise emit\n",{"type":41,"tag":101,"props":3843,"children":3845},{"className":3844},[],[3846],{"type":46,"value":3847},"# ENV NAME=\u003Cset at runtime>",{"type":46,"value":3849}," as a comment.",{"type":41,"tag":599,"props":3851,"children":3852},{},[3853,3855,3860,3862,3868],{"type":46,"value":3854},"For each entry classified as ",{"type":41,"tag":101,"props":3856,"children":3858},{"className":3857},[],[3859],{"type":46,"value":476},{"type":46,"value":3861},": emit ",{"type":41,"tag":101,"props":3863,"children":3865},{"className":3864},[],[3866],{"type":46,"value":3867},"# SECRET: NAME — inject via Kubernetes Secret at runtime, do NOT bake into the image",{"type":46,"value":208},{"type":41,"tag":49,"props":3870,"children":3871},{},[3872],{"type":41,"tag":509,"props":3873,"children":3874},{},[3875],{"type":46,"value":3876},"Required labels (attribution)",{"type":41,"tag":49,"props":3878,"children":3879},{},[3880,3886,3888,3893,3895,3901,3903,3909,3911,3923,3925,3930],{"type":41,"tag":101,"props":3881,"children":3883},{"className":3882},[],[3884],{"type":46,"value":3885},"LABEL",{"type":46,"value":3887}," is a Dockerfile instruction that only takes effect inside a build\nstage — it MUST appear after a ",{"type":41,"tag":101,"props":3889,"children":3891},{"className":3890},[],[3892],{"type":46,"value":805},{"type":46,"value":3894}," line or ",{"type":41,"tag":101,"props":3896,"children":3898},{"className":3897},[],[3899],{"type":46,"value":3900},"docker build",{"type":46,"value":3902}," errors out\nwith ",{"type":41,"tag":101,"props":3904,"children":3906},{"className":3905},[],[3907],{"type":46,"value":3908},"no build stage in current context",{"type":46,"value":3910},". Emit attribution labels\n",{"type":41,"tag":509,"props":3912,"children":3913},{},[3914,3916,3921],{"type":46,"value":3915},"immediately after the ",{"type":41,"tag":101,"props":3917,"children":3919},{"className":3918},[],[3920],{"type":46,"value":805},{"type":46,"value":3922}," line of the final \u002F runtime stage",{"type":46,"value":3924}," (and\nnot before the first ",{"type":41,"tag":101,"props":3926,"children":3928},{"className":3927},[],[3929],{"type":46,"value":805},{"type":46,"value":3931},", not in the build stage).",{"type":41,"tag":49,"props":3933,"children":3934},{},[3935],{"type":46,"value":3936},"Always emit, in the runtime stage:",{"type":41,"tag":2851,"props":3938,"children":3941},{"className":3939,"code":3940,"language":46},[2854],"LABEL com.azure.containerizationassist.createdby=\"containerization-assist\"\n",[3942],{"type":41,"tag":101,"props":3943,"children":3944},{"__ignoreMap":2859},[3945],{"type":46,"value":3940},{"type":41,"tag":49,"props":3947,"children":3948},{},[3949,3951,3957,3959,3965],{"type":46,"value":3950},"If you can read the current ",{"type":41,"tag":101,"props":3952,"children":3954},{"className":3953},[],[3955],{"type":46,"value":3956},"containerization-assist",{"type":46,"value":3958}," package version\nfrom the environment (e.g. its ",{"type":41,"tag":101,"props":3960,"children":3962},{"className":3961},[],[3963],{"type":46,"value":3964},"package.json",{"type":46,"value":3966},"), also emit:",{"type":41,"tag":2851,"props":3968,"children":3971},{"className":3969,"code":3970,"language":46},[2854],"LABEL com.azure.containerizationassist.version=\"\u003Cversion>\"\n",[3972],{"type":41,"tag":101,"props":3973,"children":3974},{"__ignoreMap":2859},[3975],{"type":46,"value":3970},{"type":41,"tag":49,"props":3977,"children":3978},{},[3979,3981,3987],{"type":46,"value":3980},"Otherwise omit the version label — never hard-code a stale version string.\nDo NOT substitute either key for ",{"type":41,"tag":101,"props":3982,"children":3984},{"className":3983},[],[3985],{"type":46,"value":3986},"org.opencontainers.image.*",{"type":46,"value":208},{"type":41,"tag":49,"props":3989,"children":3990},{},[3991],{"type":41,"tag":509,"props":3992,"children":3993},{},[3994],{"type":46,"value":3995},"Framework-specific tweaks (illustrative, not an allowlist)",{"type":41,"tag":49,"props":3997,"children":3998},{},[3999],{"type":46,"value":4000},"These rows are worked examples of the general rules above — not an\nexhaustive list. For a framework not listed here, apply the same approach:\nderive the build-output directory and the run command from the project's\nown config and the framework's documented defaults. Never skip\ncontainerizing a stack, or fall back to a guess, just because it lacks a\nrow in this table.",{"type":41,"tag":62,"props":4002,"children":4003},{},[4004,4020],{"type":41,"tag":66,"props":4005,"children":4006},{},[4007],{"type":41,"tag":70,"props":4008,"children":4009},{},[4010,4015],{"type":41,"tag":74,"props":4011,"children":4012},{},[4013],{"type":46,"value":4014},"Framework",{"type":41,"tag":74,"props":4016,"children":4017},{},[4018],{"type":46,"value":4019},"Add",{"type":41,"tag":90,"props":4021,"children":4022},{},[4023,4055,4103,4128,4145,4170,4189],{"type":41,"tag":70,"props":4024,"children":4025},{},[4026,4031],{"type":41,"tag":97,"props":4027,"children":4028},{},[4029],{"type":46,"value":4030},"Spring Boot",{"type":41,"tag":97,"props":4032,"children":4033},{},[4034,4040,4042,4048,4049],{"type":41,"tag":101,"props":4035,"children":4037},{"className":4036},[],[4038],{"type":46,"value":4039},"ENV JAVA_OPTS=\"-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0\"",{"type":46,"value":4041},", copy fat JAR from ",{"type":41,"tag":101,"props":4043,"children":4045},{"className":4044},[],[4046],{"type":46,"value":4047},"target\u002F*.jar",{"type":46,"value":238},{"type":41,"tag":101,"props":4050,"children":4052},{"className":4051},[],[4053],{"type":46,"value":4054},"ENTRYPOINT [\"java\",\"-jar\",\"\u002Fapp\u002Fapp.jar\"]",{"type":41,"tag":70,"props":4056,"children":4057},{},[4058,4063],{"type":41,"tag":97,"props":4059,"children":4060},{},[4061],{"type":46,"value":4062},"Next.js",{"type":41,"tag":97,"props":4064,"children":4065},{},[4066,4068,4073,4075,4081,4082,4088,4089,4095,4097],{"type":46,"value":4067},"Build with ",{"type":41,"tag":101,"props":4069,"children":4071},{"className":4070},[],[4072],{"type":46,"value":2365},{"type":46,"value":4074},"; copy ",{"type":41,"tag":101,"props":4076,"children":4078},{"className":4077},[],[4079],{"type":46,"value":4080},".next\u002Fstandalone",{"type":46,"value":238},{"type":41,"tag":101,"props":4083,"children":4085},{"className":4084},[],[4086],{"type":46,"value":4087},".next\u002Fstatic",{"type":46,"value":238},{"type":41,"tag":101,"props":4090,"children":4092},{"className":4091},[],[4093],{"type":46,"value":4094},"public",{"type":46,"value":4096},"; ",{"type":41,"tag":101,"props":4098,"children":4100},{"className":4099},[],[4101],{"type":46,"value":4102},"CMD [\"node\",\"server.js\"]",{"type":41,"tag":70,"props":4104,"children":4105},{},[4106,4111],{"type":41,"tag":97,"props":4107,"children":4108},{},[4109],{"type":46,"value":4110},"Django",{"type":41,"tag":97,"props":4112,"children":4113},{},[4114,4120,4122],{"type":41,"tag":101,"props":4115,"children":4117},{"className":4116},[],[4118],{"type":46,"value":4119},"RUN python manage.py collectstatic --noinput",{"type":46,"value":4121},"; run with ",{"type":41,"tag":101,"props":4123,"children":4125},{"className":4124},[],[4126],{"type":46,"value":4127},"gunicorn",{"type":41,"tag":70,"props":4129,"children":4130},{},[4131,4136],{"type":41,"tag":97,"props":4132,"children":4133},{},[4134],{"type":46,"value":4135},"FastAPI",{"type":41,"tag":97,"props":4137,"children":4138},{},[4139],{"type":41,"tag":101,"props":4140,"children":4142},{"className":4141},[],[4143],{"type":46,"value":4144},"CMD [\"uvicorn\",\"app.main:app\",\"--host\",\"0.0.0.0\",\"--port\",\"8000\"]",{"type":41,"tag":70,"props":4146,"children":4147},{},[4148,4153],{"type":41,"tag":97,"props":4149,"children":4150},{},[4151],{"type":46,"value":4152},"ASP.NET Core",{"type":41,"tag":97,"props":4154,"children":4155},{},[4156,4162,4164],{"type":41,"tag":101,"props":4157,"children":4159},{"className":4158},[],[4160],{"type":46,"value":4161},"dotnet publish -c Release -o \u002Fout",{"type":46,"value":4163},"; runtime stage runs ",{"type":41,"tag":101,"props":4165,"children":4167},{"className":4166},[],[4168],{"type":46,"value":4169},"dotnet \u003CApp>.dll",{"type":41,"tag":70,"props":4171,"children":4172},{},[4173,4178],{"type":41,"tag":97,"props":4174,"children":4175},{},[4176],{"type":46,"value":4177},"Go",{"type":41,"tag":97,"props":4179,"children":4180},{},[4181,4187],{"type":41,"tag":101,"props":4182,"children":4184},{"className":4183},[],[4185],{"type":46,"value":4186},"CGO_ENABLED=0 go build -ldflags=\"-s -w\" -o \u002Fout\u002Fapp",{"type":46,"value":4188},"; copy single binary into distroless",{"type":41,"tag":70,"props":4190,"children":4191},{},[4192,4197],{"type":41,"tag":97,"props":4193,"children":4194},{},[4195],{"type":46,"value":4196},"Rust",{"type":41,"tag":97,"props":4198,"children":4199},{},[4200,4206,4207,4213],{"type":41,"tag":101,"props":4201,"children":4203},{"className":4202},[],[4204],{"type":46,"value":4205},"cargo build --release",{"type":46,"value":4074},{"type":41,"tag":101,"props":4208,"children":4210},{"className":4209},[],[4211],{"type":46,"value":4212},"target\u002Frelease\u002F\u003Cbin>",{"type":46,"value":4214}," into distroless",{"type":41,"tag":650,"props":4216,"children":4218},{"id":4217},"g4-validate-the-result-against-this-self-check",[4219],{"type":46,"value":4220},"G4 — Validate the result against this self-check",{"type":41,"tag":49,"props":4222,"children":4223},{},[4224],{"type":46,"value":4225},"Before emitting, confirm:",{"type":41,"tag":669,"props":4227,"children":4230},{"className":4228},[4229],"contains-task-list",[4231,4264,4307,4387,4472,4488,4502,4523,4549,4558,4574],{"type":41,"tag":599,"props":4232,"children":4235},{"className":4233},[4234],"task-list-item",[4236,4242,4243,4248,4250,4255,4257,4262],{"type":41,"tag":4237,"props":4238,"children":4241},"input",{"disabled":4239,"type":4240},true,"checkbox",[],{"type":46,"value":1699},{"type":41,"tag":509,"props":4244,"children":4245},{},[4246],{"type":46,"value":4247},"Required label present.",{"type":46,"value":4249}," The runtime stage contains ",{"type":41,"tag":101,"props":4251,"children":4253},{"className":4252},[],[4254],{"type":46,"value":2249},{"type":46,"value":4256}," immediately after its ",{"type":41,"tag":101,"props":4258,"children":4260},{"className":4259},[],[4261],{"type":46,"value":805},{"type":46,"value":4263}," line. (If missing, add it now — do not skip.)",{"type":41,"tag":599,"props":4265,"children":4267},{"className":4266},[4234],[4268,4271,4272,4277,4279,4284,4286,4291,4293,4298,4300,4305],{"type":41,"tag":4237,"props":4269,"children":4270},{"disabled":4239,"type":4240},[],{"type":46,"value":1699},{"type":41,"tag":509,"props":4273,"children":4274},{},[4275],{"type":46,"value":4276},"Azure base.",{"type":46,"value":4278}," Every ",{"type":41,"tag":101,"props":4280,"children":4282},{"className":4281},[],[4283],{"type":46,"value":805},{"type":46,"value":4285}," line either starts with ",{"type":41,"tag":101,"props":4287,"children":4289},{"className":4288},[],[4290],{"type":46,"value":813},{"type":46,"value":4292}," (using a tag from the G2.1 catalog) ",{"type":41,"tag":509,"props":4294,"children":4295},{},[4296],{"type":46,"value":4297},"or",{"type":46,"value":4299}," matches a row in the G2.3 fallback list with a ",{"type":41,"tag":101,"props":4301,"children":4303},{"className":4302},[],[4304],{"type":46,"value":1553},{"type":46,"value":4306}," comment above it. No invented MCR tags.",{"type":41,"tag":599,"props":4308,"children":4310},{"className":4309},[4234],[4311,4314,4315,4320,4322,4327,4329,4334,4336,4341,4342,4347,4348,4353,4354,4359,4360,4366,4368,4373,4374,4379,4381,4385],{"type":41,"tag":4237,"props":4312,"children":4313},{"disabled":4239,"type":4240},[],{"type":46,"value":1699},{"type":41,"tag":509,"props":4316,"children":4317},{},[4318],{"type":46,"value":4319},"No builder as runtime.",{"type":46,"value":4321}," If any ",{"type":41,"tag":101,"props":4323,"children":4325},{"className":4324},[],[4326],{"type":46,"value":805},{"type":46,"value":4328}," uses a G2.3 ",{"type":41,"tag":4330,"props":4331,"children":4332},"em",{},[4333],{"type":46,"value":1725},{"type":46,"value":4335}," image (",{"type":41,"tag":101,"props":4337,"children":4339},{"className":4338},[],[4340],{"type":46,"value":761},{"type":46,"value":462},{"type":41,"tag":101,"props":4343,"children":4345},{"className":4344},[],[4346],{"type":46,"value":768},{"type":46,"value":462},{"type":41,"tag":101,"props":4349,"children":4351},{"className":4350},[],[4352],{"type":46,"value":853},{"type":46,"value":462},{"type":41,"tag":101,"props":4355,"children":4357},{"className":4356},[],[4358],{"type":46,"value":192},{"type":46,"value":462},{"type":41,"tag":101,"props":4361,"children":4363},{"className":4362},[],[4364],{"type":46,"value":4365},"composer",{"type":46,"value":4367},"), the Dockerfile is multi-stage and its ",{"type":41,"tag":509,"props":4369,"children":4370},{},[4371],{"type":46,"value":4372},"final",{"type":46,"value":1699},{"type":41,"tag":101,"props":4375,"children":4377},{"className":4376},[],[4378],{"type":46,"value":805},{"type":46,"value":4380}," is the matching G2.3 ",{"type":41,"tag":4330,"props":4382,"children":4383},{},[4384],{"type":46,"value":1650},{"type":46,"value":4386}," image (or an MCR G2.1 image) — never the builder itself.",{"type":41,"tag":599,"props":4388,"children":4390},{"className":4389},[4234],[4391,4394,4395,4400,4401,4406,4408,4413,4414,4420,4421,4426,4427,4433,4434,4439,4440,4445,4446,4451,4452,4457,4458,4463,4465,4470],{"type":41,"tag":4237,"props":4392,"children":4393},{"disabled":4239,"type":4240},[],{"type":46,"value":1699},{"type":41,"tag":509,"props":4396,"children":4397},{},[4398],{"type":46,"value":4399},"Source copied before build.",{"type":46,"value":4278},{"type":41,"tag":101,"props":4402,"children":4404},{"className":4403},[],[4405],{"type":46,"value":2309},{"type":46,"value":4407}," that invokes a build tool (",{"type":41,"tag":101,"props":4409,"children":4411},{"className":4410},[],[4412],{"type":46,"value":2338},{"type":46,"value":462},{"type":41,"tag":101,"props":4415,"children":4417},{"className":4416},[],[4418],{"type":46,"value":4419},"mvnw",{"type":46,"value":238},{"type":41,"tag":101,"props":4422,"children":4424},{"className":4423},[],[4425],{"type":46,"value":768},{"type":46,"value":462},{"type":41,"tag":101,"props":4428,"children":4430},{"className":4429},[],[4431],{"type":46,"value":4432},"gradlew",{"type":46,"value":238},{"type":41,"tag":101,"props":4435,"children":4437},{"className":4436},[],[4438],{"type":46,"value":2365},{"type":46,"value":238},{"type":41,"tag":101,"props":4441,"children":4443},{"className":4442},[],[4444],{"type":46,"value":729},{"type":46,"value":238},{"type":41,"tag":101,"props":4447,"children":4449},{"className":4448},[],[4450],{"type":46,"value":2379},{"type":46,"value":238},{"type":41,"tag":101,"props":4453,"children":4455},{"className":4454},[],[4456],{"type":46,"value":2386},{"type":46,"value":238},{"type":41,"tag":101,"props":4459,"children":4461},{"className":4460},[],[4462],{"type":46,"value":2393},{"type":46,"value":4464},") is preceded by a ",{"type":41,"tag":101,"props":4466,"children":4468},{"className":4467},[],[4469],{"type":46,"value":2496},{"type":46,"value":4471}," of the source tree.",{"type":41,"tag":599,"props":4473,"children":4475},{"className":4474},[4234],[4476,4479,4481,4486],{"type":41,"tag":4237,"props":4477,"children":4478},{"disabled":4239,"type":4240},[],{"type":46,"value":4480}," Single non-root ",{"type":41,"tag":101,"props":4482,"children":4484},{"className":4483},[],[4485],{"type":46,"value":2794},{"type":46,"value":4487}," in the final stage",{"type":41,"tag":599,"props":4489,"children":4491},{"className":4490},[4234],[4492,4495,4497],{"type":41,"tag":4237,"props":4493,"children":4494},{"disabled":4239,"type":4240},[],{"type":46,"value":4496}," No hardcoded secrets in any ",{"type":41,"tag":101,"props":4498,"children":4500},{"className":4499},[],[4501],{"type":46,"value":452},{"type":41,"tag":599,"props":4503,"children":4505},{"className":4504},[4234],[4506,4509,4511,4516,4518],{"type":41,"tag":4237,"props":4507,"children":4508},{"disabled":4239,"type":4240},[],{"type":46,"value":4510}," No ",{"type":41,"tag":101,"props":4512,"children":4514},{"className":4513},[],[4515],{"type":46,"value":3678},{"type":46,"value":4517}," tag, no ",{"type":41,"tag":101,"props":4519,"children":4521},{"className":4520},[],[4522],{"type":46,"value":2995},{"type":41,"tag":599,"props":4524,"children":4526},{"className":4525},[4234],[4527,4530,4531,4536,4538,4543,4544],{"type":41,"tag":4237,"props":4528,"children":4529},{"disabled":4239,"type":4240},[],{"type":46,"value":1699},{"type":41,"tag":101,"props":4532,"children":4534},{"className":4533},[],[4535],{"type":46,"value":2285},{"type":46,"value":4537}," set, no ",{"type":41,"tag":101,"props":4539,"children":4541},{"className":4540},[],[4542],{"type":46,"value":2301},{"type":46,"value":2303},{"type":41,"tag":101,"props":4545,"children":4547},{"className":4546},[],[4548],{"type":46,"value":2309},{"type":41,"tag":599,"props":4550,"children":4552},{"className":4551},[4234],[4553,4556],{"type":41,"tag":4237,"props":4554,"children":4555},{"disabled":4239,"type":4240},[],{"type":46,"value":4557}," Multi-stage chosen per rule G1",{"type":41,"tag":599,"props":4559,"children":4561},{"className":4560},[4234],[4562,4565,4566,4572],{"type":41,"tag":4237,"props":4563,"children":4564},{"disabled":4239,"type":4240},[],{"type":46,"value":1699},{"type":41,"tag":101,"props":4567,"children":4569},{"className":4568},[],[4570],{"type":46,"value":4571},"EXPOSE",{"type":46,"value":4573}," matches detected listener port",{"type":41,"tag":599,"props":4575,"children":4577},{"className":4576},[4234],[4578,4581,4582,4587,4588,4594],{"type":41,"tag":4237,"props":4579,"children":4580},{"disabled":4239,"type":4240},[],{"type":46,"value":1699},{"type":41,"tag":101,"props":4583,"children":4585},{"className":4584},[],[4586],{"type":46,"value":3774},{"type":46,"value":462},{"type":41,"tag":101,"props":4589,"children":4591},{"className":4590},[],[4592],{"type":46,"value":4593},"ENTRYPOINT",{"type":46,"value":4595}," in exec form",{"type":41,"tag":49,"props":4597,"children":4598},{},[4599,4601,4606],{"type":46,"value":4600},"If any item fails, fix the Dockerfile ",{"type":41,"tag":509,"props":4602,"children":4603},{},[4604],{"type":46,"value":4605},"before",{"type":46,"value":4607}," showing it to the user.",{"type":41,"tag":641,"props":4609,"children":4610},{},[],{"type":41,"tag":55,"props":4612,"children":4614},{"id":4613},"enhancement-path",[4615],{"type":46,"value":513},{"type":41,"tag":650,"props":4617,"children":4619},{"id":4618},"e1-analyze-the-existing-dockerfile",[4620],{"type":46,"value":4621},"E1 — Analyze the existing Dockerfile",{"type":41,"tag":49,"props":4623,"children":4624},{},[4625],{"type":46,"value":4626},"Read the file. Compute:",{"type":41,"tag":669,"props":4628,"children":4629},{},[4630,4656,4674,4693,4724,4742,4796],{"type":41,"tag":599,"props":4631,"children":4632},{},[4633,4639,4641,4647,4649,4654],{"type":41,"tag":101,"props":4634,"children":4636},{"className":4635},[],[4637],{"type":46,"value":4638},"baseImages",{"type":46,"value":4640}," = every line starting with ",{"type":41,"tag":101,"props":4642,"children":4644},{"className":4643},[],[4645],{"type":46,"value":4646},"FROM ",{"type":46,"value":4648}," (after ",{"type":41,"tag":101,"props":4650,"children":4652},{"className":4651},[],[4653],{"type":46,"value":4646},{"type":46,"value":4655},", take the\nfirst whitespace-delimited token).",{"type":41,"tag":599,"props":4657,"children":4658},{},[4659,4665,4667,4673],{"type":41,"tag":101,"props":4660,"children":4662},{"className":4661},[],[4663],{"type":46,"value":4664},"isMultistage",{"type":46,"value":4666}," = ",{"type":41,"tag":101,"props":4668,"children":4670},{"className":4669},[],[4671],{"type":46,"value":4672},"baseImages.length > 1",{"type":46,"value":208},{"type":41,"tag":599,"props":4675,"children":4676},{},[4677,4683,4685,4691],{"type":41,"tag":101,"props":4678,"children":4680},{"className":4679},[],[4681],{"type":46,"value":4682},"hasHealthCheck",{"type":46,"value":4684}," = any line starts with ",{"type":41,"tag":101,"props":4686,"children":4688},{"className":4687},[],[4689],{"type":46,"value":4690},"HEALTHCHECK ",{"type":46,"value":4692}," (case-insensitive).",{"type":41,"tag":599,"props":4694,"children":4695},{},[4696,4702,4704,4709,4711,4716,4717,4723],{"type":41,"tag":101,"props":4697,"children":4699},{"className":4698},[],[4700],{"type":46,"value":4701},"hasNonRootUser",{"type":46,"value":4703}," = any ",{"type":41,"tag":101,"props":4705,"children":4707},{"className":4706},[],[4708],{"type":46,"value":2794},{"type":46,"value":4710}," line whose argument is not ",{"type":41,"tag":101,"props":4712,"children":4714},{"className":4713},[],[4715],{"type":46,"value":38},{"type":46,"value":1973},{"type":41,"tag":101,"props":4718,"children":4720},{"className":4719},[],[4721],{"type":46,"value":4722},"0",{"type":46,"value":208},{"type":41,"tag":599,"props":4725,"children":4726},{},[4727,4733,4735,4741],{"type":41,"tag":101,"props":4728,"children":4730},{"className":4729},[],[4731],{"type":46,"value":4732},"instructionCount",{"type":46,"value":4734}," = number of lines whose first token is one of:\n",{"type":41,"tag":101,"props":4736,"children":4738},{"className":4737},[],[4739],{"type":46,"value":4740},"FROM, RUN, CMD, LABEL, EXPOSE, ENV, ADD, COPY, ENTRYPOINT, VOLUME, USER, WORKDIR, ARG, ONBUILD, STOPSIGNAL, HEALTHCHECK, SHELL",{"type":46,"value":208},{"type":41,"tag":599,"props":4743,"children":4744},{},[4745,4751,4752,4758,4760,4766,4767,4772,4774,4780,4781,4787,4789,4795],{"type":41,"tag":101,"props":4746,"children":4748},{"className":4747},[],[4749],{"type":46,"value":4750},"complexity",{"type":46,"value":4666},{"type":41,"tag":101,"props":4753,"children":4755},{"className":4754},[],[4756],{"type":46,"value":4757},"complex",{"type":46,"value":4759}," if ",{"type":41,"tag":101,"props":4761,"children":4763},{"className":4762},[],[4764],{"type":46,"value":4765},"instructionCount > 20",{"type":46,"value":1973},{"type":41,"tag":101,"props":4768,"children":4770},{"className":4769},[],[4771],{"type":46,"value":4664},{"type":46,"value":4773},";\nelse ",{"type":41,"tag":101,"props":4775,"children":4777},{"className":4776},[],[4778],{"type":46,"value":4779},"moderate",{"type":46,"value":4759},{"type":41,"tag":101,"props":4782,"children":4784},{"className":4783},[],[4785],{"type":46,"value":4786},"> 10",{"type":46,"value":4788},"; else ",{"type":41,"tag":101,"props":4790,"children":4792},{"className":4791},[],[4793],{"type":46,"value":4794},"simple",{"type":46,"value":208},{"type":41,"tag":599,"props":4797,"children":4798},{},[4799,4805,4806,4812,4813,4819,4820,4826,4828,4834,4835,4841],{"type":41,"tag":101,"props":4800,"children":4802},{"className":4801},[],[4803],{"type":46,"value":4804},"securityPosture",{"type":46,"value":4666},{"type":41,"tag":101,"props":4807,"children":4809},{"className":4808},[],[4810],{"type":46,"value":4811},"good",{"type":46,"value":4759},{"type":41,"tag":101,"props":4814,"children":4816},{"className":4815},[],[4817],{"type":46,"value":4818},"hasNonRootUser && hasHealthCheck",{"type":46,"value":4096},{"type":41,"tag":101,"props":4821,"children":4823},{"className":4822},[],[4824],{"type":46,"value":4825},"poor",{"type":46,"value":4827},"\nif ",{"type":41,"tag":101,"props":4829,"children":4831},{"className":4830},[],[4832],{"type":46,"value":4833},"!hasNonRootUser && !hasHealthCheck",{"type":46,"value":4788},{"type":41,"tag":101,"props":4836,"children":4838},{"className":4837},[],[4839],{"type":46,"value":4840},"needs-improvement",{"type":46,"value":208},{"type":41,"tag":650,"props":4843,"children":4845},{"id":4844},"e2-compute-the-diff-plan",[4846],{"type":46,"value":4847},"E2 — Compute the diff plan",{"type":41,"tag":669,"props":4849,"children":4850},{},[4851,4868,4905],{"type":41,"tag":599,"props":4852,"children":4853},{},[4854,4859,4861,4866],{"type":41,"tag":509,"props":4855,"children":4856},{},[4857],{"type":46,"value":4858},"Preserve",{"type":46,"value":4860}," (always keep): multi-stage structure if present, existing\nHEALTHCHECK if present, non-root USER if present, existing base image\nunless it's ",{"type":41,"tag":101,"props":4862,"children":4864},{"className":4863},[],[4865],{"type":46,"value":3678},{"type":46,"value":4867}," or unsupported.",{"type":41,"tag":599,"props":4869,"children":4870},{},[4871,4876,4878,4883,4885,4890,4891,4896,4898,4903],{"type":41,"tag":509,"props":4872,"children":4873},{},[4874],{"type":46,"value":4875},"Improve",{"type":46,"value":4877}," (rewrite in place): any rule from G3 that the current file\nviolates (root user, hardcoded secrets, ",{"type":41,"tag":101,"props":4879,"children":4881},{"className":4880},[],[4882],{"type":46,"value":2995},{"type":46,"value":4884},", missing\ncleanup, ",{"type":41,"tag":101,"props":4886,"children":4888},{"className":4887},[],[4889],{"type":46,"value":2301},{"type":46,"value":2303},{"type":41,"tag":101,"props":4892,"children":4894},{"className":4893},[],[4895],{"type":46,"value":2309},{"type":46,"value":4897},", floating tags, > 6 ",{"type":41,"tag":101,"props":4899,"children":4901},{"className":4900},[],[4902],{"type":46,"value":2309},{"type":46,"value":4904}," instructions when\ncombinable, missing labels).",{"type":41,"tag":599,"props":4906,"children":4907},{},[4908,4913,4915,4920,4922,4927],{"type":41,"tag":509,"props":4909,"children":4910},{},[4911],{"type":46,"value":4912},"Add missing",{"type":46,"value":4914},": non-root USER if absent, HEALTHCHECK if absent and the\nimage has a shell, required ",{"type":41,"tag":101,"props":4916,"children":4918},{"className":4917},[],[4919],{"type":46,"value":3885},{"type":46,"value":4921},"s if absent, ",{"type":41,"tag":101,"props":4923,"children":4925},{"className":4924},[],[4926],{"type":46,"value":2285},{"type":46,"value":4928}," if absent.",{"type":41,"tag":650,"props":4930,"children":4932},{"id":4931},"e3-pick-the-strategy",[4933],{"type":46,"value":4934},"E3 — Pick the strategy",{"type":41,"tag":62,"props":4936,"children":4937},{},[4938,4954],{"type":41,"tag":66,"props":4939,"children":4940},{},[4941],{"type":41,"tag":70,"props":4942,"children":4943},{},[4944,4949],{"type":41,"tag":74,"props":4945,"children":4946},{},[4947],{"type":46,"value":4948},"Conditions",{"type":41,"tag":74,"props":4950,"children":4951},{},[4952],{"type":46,"value":4953},"Strategy",{"type":41,"tag":90,"props":4955,"children":4956},{},[4957,4988,5017],{"type":41,"tag":70,"props":4958,"children":4959},{},[4960,4979],{"type":41,"tag":97,"props":4961,"children":4962},{},[4963,4969,4971,4977],{"type":41,"tag":101,"props":4964,"children":4966},{"className":4965},[],[4967],{"type":46,"value":4968},"securityPosture == \"poor\"",{"type":46,"value":4970}," OR (",{"type":41,"tag":101,"props":4972,"children":4974},{"className":4973},[],[4975],{"type":46,"value":4976},"improve.length + addMissing.length > 5",{"type":46,"value":4978},")",{"type":41,"tag":97,"props":4980,"children":4981},{},[4982],{"type":41,"tag":101,"props":4983,"children":4985},{"className":4984},[],[4986],{"type":46,"value":4987},"major-overhaul",{"type":41,"tag":70,"props":4989,"children":4990},{},[4991,5008],{"type":41,"tag":97,"props":4992,"children":4993},{},[4994,5000,5001,5007],{"type":41,"tag":101,"props":4995,"children":4997},{"className":4996},[],[4998],{"type":46,"value":4999},"securityPosture == \"needs-improvement\"",{"type":46,"value":4970},{"type":41,"tag":101,"props":5002,"children":5004},{"className":5003},[],[5005],{"type":46,"value":5006},"improve.length + addMissing.length > 2",{"type":46,"value":4978},{"type":41,"tag":97,"props":5009,"children":5010},{},[5011],{"type":41,"tag":101,"props":5012,"children":5014},{"className":5013},[],[5015],{"type":46,"value":5016},"moderate-refactor",{"type":41,"tag":70,"props":5018,"children":5019},{},[5020,5025],{"type":41,"tag":97,"props":5021,"children":5022},{},[5023],{"type":46,"value":5024},"Otherwise",{"type":41,"tag":97,"props":5026,"children":5027},{},[5028],{"type":41,"tag":101,"props":5029,"children":5031},{"className":5030},[],[5032],{"type":46,"value":5033},"minor-tweaks",{"type":41,"tag":650,"props":5035,"children":5037},{"id":5036},"e4-produce-the-enhanced-dockerfile",[5038],{"type":46,"value":5039},"E4 — Produce the enhanced Dockerfile",{"type":41,"tag":49,"props":5041,"children":5042},{},[5043,5045,5050],{"type":46,"value":5044},"Compose the ",{"type":41,"tag":509,"props":5046,"children":5047},{},[5048],{"type":46,"value":5049},"full",{"type":46,"value":5051}," updated Dockerfile (do not show a diff). Apply every\nrelevant item from G3 to bring it to baseline. Preserve the listed items\nverbatim. Re-run the G4 self-check before writing.",{"type":41,"tag":641,"props":5053,"children":5054},{},[],{"type":41,"tag":55,"props":5056,"children":5058},{"id":5057},"writing-the-file-mandatory",[5059],{"type":46,"value":5060},"Writing the file (mandatory)",{"type":41,"tag":49,"props":5062,"children":5063},{},[5064,5066,5076],{"type":46,"value":5065},"As soon as the Dockerfile passes the G4 self-check, ",{"type":41,"tag":509,"props":5067,"children":5068},{},[5069,5071],{"type":46,"value":5070},"write it to\n",{"type":41,"tag":101,"props":5072,"children":5074},{"className":5073},[],[5075],{"type":46,"value":505},{"type":46,"value":5077},". Do not ask the user for confirmation first;\ndo not stage it in the response. If a Dockerfile already exists, overwrite\nit (the Enhancement path already incorporates anything worth preserving).",{"type":41,"tag":49,"props":5079,"children":5080},{},[5081,5083,5087],{"type":46,"value":5082},"Do ",{"type":41,"tag":509,"props":5084,"children":5085},{},[5086],{"type":46,"value":3503},{"type":46,"value":5088}," print the full Dockerfile content in the chat response. The\nuser can open the file on disk. Only include excerpts when:",{"type":41,"tag":669,"props":5090,"children":5091},{},[5092,5097,5102],{"type":41,"tag":599,"props":5093,"children":5094},{},[5095],{"type":46,"value":5096},"the user explicitly asks to see it (\"show me the Dockerfile\", \"print it\"),",{"type":41,"tag":599,"props":5098,"children":5099},{},[5100],{"type":46,"value":5101},"you need to highlight a specific change (≤ 10 lines of context), or",{"type":41,"tag":599,"props":5103,"children":5104},{},[5105],{"type":46,"value":5106},"the write failed and you need to surface the content for manual recovery.",{"type":41,"tag":55,"props":5108,"children":5110},{"id":5109},"output-format",[5111],{"type":46,"value":5112},"Output format",{"type":41,"tag":49,"props":5114,"children":5115},{},[5116],{"type":46,"value":5117},"Use exactly these sections, in order. Keep the response short — the file\non disk is the artifact.",{"type":41,"tag":2851,"props":5119,"children":5123},{"className":5120,"code":5121,"language":5122,"meta":2859,"style":2859},"language-md shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","**Dockerfile \u003Cgeneration|enhancement>** — written to `\u003CmodulePath>\u002FDockerfile`\n\n### Plan\n- **Strategy:** \u003Cmulti-stage build | single-stage build | minor-tweaks | moderate-refactor | major-overhaul>\n- **Base image (build):** `\u003Cimage>` \u003Conly if multi-stage>\n- **Base image (runtime):** `\u003Cimage>`\n- **User:** `appuser` (UID 10001) \u003Cor \"preserved from existing\">\n- **Healthcheck:** \u003Cyes\u002Fno — reason if no>\n\n### Env vars\n- `\u003CNAME>` *\u003Cconfig|database>* → emitted as `ENV`\n- `\u003CNAME>` *secret* → **runtime injection only** (Kubernetes Secret)\n- ...\n\n### Next steps\n1. Build locally: `docker buildx build --platform=\u003CtargetPlatform> -t \u003Cmodule>:dev \u003CmodulePath>`\n2. Run **fix-dockerfile** to lint and remediate the file against the built-in security and best-practice rules.\n3. Once validated, scan the built image and proceed to `generate-k8s-manifests`.\n","md",[5124],{"type":41,"tag":101,"props":5125,"children":5126},{"__ignoreMap":2859},[5127,5182,5191,5206,5291,5349,5382,5448,5501,5509,5522,5577,5634,5647,5655,5668,5694,5726],{"type":41,"tag":5128,"props":5129,"children":5132},"span",{"class":5130,"line":5131},"line",1,[5133,5139,5145,5150,5155,5160,5166,5172,5177],{"type":41,"tag":5128,"props":5134,"children":5136},{"style":5135},"--shiki-light:#39ADB5;--shiki-light-font-weight:bold;--shiki-default:#89DDFF;--shiki-default-font-weight:bold;--shiki-dark:#89DDFF;--shiki-dark-font-weight:bold",[5137],{"type":46,"value":5138},"**",{"type":41,"tag":5128,"props":5140,"children":5142},{"style":5141},"--shiki-light:#E53935;--shiki-light-font-weight:bold;--shiki-default:#F07178;--shiki-default-font-weight:bold;--shiki-dark:#F07178;--shiki-dark-font-weight:bold",[5143],{"type":46,"value":5144},"Dockerfile ",{"type":41,"tag":5128,"props":5146,"children":5147},{"style":5135},[5148],{"type":46,"value":5149},"\u003C",{"type":41,"tag":5128,"props":5151,"children":5152},{"style":5141},[5153],{"type":46,"value":5154},"generation|enhancement",{"type":41,"tag":5128,"props":5156,"children":5157},{"style":5135},[5158],{"type":46,"value":5159},">**",{"type":41,"tag":5128,"props":5161,"children":5163},{"style":5162},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[5164],{"type":46,"value":5165}," — written to ",{"type":41,"tag":5128,"props":5167,"children":5169},{"style":5168},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[5170],{"type":46,"value":5171},"`",{"type":41,"tag":5128,"props":5173,"children":5175},{"style":5174},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[5176],{"type":46,"value":505},{"type":41,"tag":5128,"props":5178,"children":5179},{"style":5168},[5180],{"type":46,"value":5181},"`\n",{"type":41,"tag":5128,"props":5183,"children":5185},{"class":5130,"line":5184},2,[5186],{"type":41,"tag":5128,"props":5187,"children":5188},{"emptyLinePlaceholder":4239},[5189],{"type":46,"value":5190},"\n",{"type":41,"tag":5128,"props":5192,"children":5194},{"class":5130,"line":5193},3,[5195,5200],{"type":41,"tag":5128,"props":5196,"children":5197},{"style":5168},[5198],{"type":46,"value":5199},"### ",{"type":41,"tag":5128,"props":5201,"children":5203},{"style":5202},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[5204],{"type":46,"value":5205},"Plan\n",{"type":41,"tag":5128,"props":5207,"children":5209},{"class":5130,"line":5208},4,[5210,5215,5220,5225,5229,5234,5239,5245,5250,5255,5259,5263,5268,5272,5277,5281,5286],{"type":41,"tag":5128,"props":5211,"children":5212},{"style":5168},[5213],{"type":46,"value":5214},"-",{"type":41,"tag":5128,"props":5216,"children":5217},{"style":5135},[5218],{"type":46,"value":5219}," **",{"type":41,"tag":5128,"props":5221,"children":5222},{"style":5141},[5223],{"type":46,"value":5224},"Strategy:",{"type":41,"tag":5128,"props":5226,"children":5227},{"style":5135},[5228],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5230,"children":5231},{"style":5168},[5232],{"type":46,"value":5233}," \u003C",{"type":41,"tag":5128,"props":5235,"children":5237},{"style":5236},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[5238],{"type":46,"value":665},{"type":41,"tag":5128,"props":5240,"children":5242},{"style":5241},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[5243],{"type":46,"value":5244}," build",{"type":41,"tag":5128,"props":5246,"children":5247},{"style":5241},[5248],{"type":46,"value":5249}," |",{"type":41,"tag":5128,"props":5251,"children":5252},{"style":5241},[5253],{"type":46,"value":5254}," single-stage",{"type":41,"tag":5128,"props":5256,"children":5257},{"style":5241},[5258],{"type":46,"value":5244},{"type":41,"tag":5128,"props":5260,"children":5261},{"style":5241},[5262],{"type":46,"value":5249},{"type":41,"tag":5128,"props":5264,"children":5265},{"style":5241},[5266],{"type":46,"value":5267}," minor-tweaks",{"type":41,"tag":5128,"props":5269,"children":5270},{"style":5241},[5271],{"type":46,"value":5249},{"type":41,"tag":5128,"props":5273,"children":5274},{"style":5241},[5275],{"type":46,"value":5276}," moderate-refactor",{"type":41,"tag":5128,"props":5278,"children":5279},{"style":5241},[5280],{"type":46,"value":5249},{"type":41,"tag":5128,"props":5282,"children":5283},{"style":5241},[5284],{"type":46,"value":5285}," major-overhaul",{"type":41,"tag":5128,"props":5287,"children":5288},{"style":5168},[5289],{"type":46,"value":5290},">\n",{"type":41,"tag":5128,"props":5292,"children":5294},{"class":5130,"line":5293},5,[5295,5299,5303,5308,5312,5317,5322,5326,5330,5335,5340,5345],{"type":41,"tag":5128,"props":5296,"children":5297},{"style":5168},[5298],{"type":46,"value":5214},{"type":41,"tag":5128,"props":5300,"children":5301},{"style":5135},[5302],{"type":46,"value":5219},{"type":41,"tag":5128,"props":5304,"children":5305},{"style":5141},[5306],{"type":46,"value":5307},"Base image (build):",{"type":41,"tag":5128,"props":5309,"children":5310},{"style":5135},[5311],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5313,"children":5314},{"style":5168},[5315],{"type":46,"value":5316}," `",{"type":41,"tag":5128,"props":5318,"children":5319},{"style":5174},[5320],{"type":46,"value":5321},"\u003Cimage>",{"type":41,"tag":5128,"props":5323,"children":5324},{"style":5168},[5325],{"type":46,"value":5171},{"type":41,"tag":5128,"props":5327,"children":5328},{"style":5168},[5329],{"type":46,"value":5233},{"type":41,"tag":5128,"props":5331,"children":5332},{"style":5236},[5333],{"type":46,"value":5334},"only",{"type":41,"tag":5128,"props":5336,"children":5337},{"style":5241},[5338],{"type":46,"value":5339}," if",{"type":41,"tag":5128,"props":5341,"children":5342},{"style":5241},[5343],{"type":46,"value":5344}," multi-stage",{"type":41,"tag":5128,"props":5346,"children":5347},{"style":5168},[5348],{"type":46,"value":5290},{"type":41,"tag":5128,"props":5350,"children":5352},{"class":5130,"line":5351},6,[5353,5357,5361,5366,5370,5374,5378],{"type":41,"tag":5128,"props":5354,"children":5355},{"style":5168},[5356],{"type":46,"value":5214},{"type":41,"tag":5128,"props":5358,"children":5359},{"style":5135},[5360],{"type":46,"value":5219},{"type":41,"tag":5128,"props":5362,"children":5363},{"style":5141},[5364],{"type":46,"value":5365},"Base image (runtime):",{"type":41,"tag":5128,"props":5367,"children":5368},{"style":5135},[5369],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5371,"children":5372},{"style":5168},[5373],{"type":46,"value":5316},{"type":41,"tag":5128,"props":5375,"children":5376},{"style":5174},[5377],{"type":46,"value":5321},{"type":41,"tag":5128,"props":5379,"children":5380},{"style":5168},[5381],{"type":46,"value":5181},{"type":41,"tag":5128,"props":5383,"children":5385},{"class":5130,"line":5384},7,[5386,5390,5394,5399,5403,5407,5411,5415,5420,5424,5428,5433,5438,5443],{"type":41,"tag":5128,"props":5387,"children":5388},{"style":5168},[5389],{"type":46,"value":5214},{"type":41,"tag":5128,"props":5391,"children":5392},{"style":5135},[5393],{"type":46,"value":5219},{"type":41,"tag":5128,"props":5395,"children":5396},{"style":5141},[5397],{"type":46,"value":5398},"User:",{"type":41,"tag":5128,"props":5400,"children":5401},{"style":5135},[5402],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5404,"children":5405},{"style":5168},[5406],{"type":46,"value":5316},{"type":41,"tag":5128,"props":5408,"children":5409},{"style":5174},[5410],{"type":46,"value":2817},{"type":41,"tag":5128,"props":5412,"children":5413},{"style":5168},[5414],{"type":46,"value":5171},{"type":41,"tag":5128,"props":5416,"children":5417},{"style":5162},[5418],{"type":46,"value":5419}," (UID 10001) ",{"type":41,"tag":5128,"props":5421,"children":5422},{"style":5168},[5423],{"type":46,"value":5149},{"type":41,"tag":5128,"props":5425,"children":5426},{"style":5236},[5427],{"type":46,"value":4297},{"type":41,"tag":5128,"props":5429,"children":5430},{"style":5168},[5431],{"type":46,"value":5432}," \"preserved ",{"type":41,"tag":5128,"props":5434,"children":5435},{"style":5241},[5436],{"type":46,"value":5437},"from",{"type":41,"tag":5128,"props":5439,"children":5440},{"style":5241},[5441],{"type":46,"value":5442}," existing",{"type":41,"tag":5128,"props":5444,"children":5445},{"style":5168},[5446],{"type":46,"value":5447},"\">\n",{"type":41,"tag":5128,"props":5449,"children":5451},{"class":5130,"line":5450},8,[5452,5456,5460,5465,5469,5473,5478,5483,5488,5492,5497],{"type":41,"tag":5128,"props":5453,"children":5454},{"style":5168},[5455],{"type":46,"value":5214},{"type":41,"tag":5128,"props":5457,"children":5458},{"style":5135},[5459],{"type":46,"value":5219},{"type":41,"tag":5128,"props":5461,"children":5462},{"style":5141},[5463],{"type":46,"value":5464},"Healthcheck:",{"type":41,"tag":5128,"props":5466,"children":5467},{"style":5135},[5468],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5470,"children":5471},{"style":5168},[5472],{"type":46,"value":5233},{"type":41,"tag":5128,"props":5474,"children":5475},{"style":5236},[5476],{"type":46,"value":5477},"yes\u002Fno",{"type":41,"tag":5128,"props":5479,"children":5480},{"style":5241},[5481],{"type":46,"value":5482}," —",{"type":41,"tag":5128,"props":5484,"children":5485},{"style":5241},[5486],{"type":46,"value":5487}," reason",{"type":41,"tag":5128,"props":5489,"children":5490},{"style":5241},[5491],{"type":46,"value":5339},{"type":41,"tag":5128,"props":5493,"children":5494},{"style":5241},[5495],{"type":46,"value":5496}," no",{"type":41,"tag":5128,"props":5498,"children":5499},{"style":5168},[5500],{"type":46,"value":5290},{"type":41,"tag":5128,"props":5502,"children":5504},{"class":5130,"line":5503},9,[5505],{"type":41,"tag":5128,"props":5506,"children":5507},{"emptyLinePlaceholder":4239},[5508],{"type":46,"value":5190},{"type":41,"tag":5128,"props":5510,"children":5512},{"class":5130,"line":5511},10,[5513,5517],{"type":41,"tag":5128,"props":5514,"children":5515},{"style":5168},[5516],{"type":46,"value":5199},{"type":41,"tag":5128,"props":5518,"children":5519},{"style":5202},[5520],{"type":46,"value":5521},"Env vars\n",{"type":41,"tag":5128,"props":5523,"children":5525},{"class":5130,"line":5524},11,[5526,5530,5534,5539,5543,5549,5555,5560,5565,5569,5573],{"type":41,"tag":5128,"props":5527,"children":5528},{"style":5168},[5529],{"type":46,"value":5214},{"type":41,"tag":5128,"props":5531,"children":5532},{"style":5168},[5533],{"type":46,"value":5316},{"type":41,"tag":5128,"props":5535,"children":5536},{"style":5174},[5537],{"type":46,"value":5538},"\u003CNAME>",{"type":41,"tag":5128,"props":5540,"children":5541},{"style":5168},[5542],{"type":46,"value":5171},{"type":41,"tag":5128,"props":5544,"children":5546},{"style":5545},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[5547],{"type":46,"value":5548}," *\u003C",{"type":41,"tag":5128,"props":5550,"children":5552},{"style":5551},"--shiki-light:#E53935;--shiki-light-font-style:italic;--shiki-default:#F07178;--shiki-default-font-style:italic;--shiki-dark:#F07178;--shiki-dark-font-style:italic",[5553],{"type":46,"value":5554},"config|database",{"type":41,"tag":5128,"props":5556,"children":5557},{"style":5545},[5558],{"type":46,"value":5559},">*",{"type":41,"tag":5128,"props":5561,"children":5562},{"style":5162},[5563],{"type":46,"value":5564}," → emitted as ",{"type":41,"tag":5128,"props":5566,"children":5567},{"style":5168},[5568],{"type":46,"value":5171},{"type":41,"tag":5128,"props":5570,"children":5571},{"style":5174},[5572],{"type":46,"value":452},{"type":41,"tag":5128,"props":5574,"children":5575},{"style":5168},[5576],{"type":46,"value":5181},{"type":41,"tag":5128,"props":5578,"children":5580},{"class":5130,"line":5579},12,[5581,5585,5589,5593,5597,5602,5606,5611,5616,5620,5625,5629],{"type":41,"tag":5128,"props":5582,"children":5583},{"style":5168},[5584],{"type":46,"value":5214},{"type":41,"tag":5128,"props":5586,"children":5587},{"style":5168},[5588],{"type":46,"value":5316},{"type":41,"tag":5128,"props":5590,"children":5591},{"style":5174},[5592],{"type":46,"value":5538},{"type":41,"tag":5128,"props":5594,"children":5595},{"style":5168},[5596],{"type":46,"value":5171},{"type":41,"tag":5128,"props":5598,"children":5599},{"style":5545},[5600],{"type":46,"value":5601}," *",{"type":41,"tag":5128,"props":5603,"children":5604},{"style":5551},[5605],{"type":46,"value":476},{"type":41,"tag":5128,"props":5607,"children":5608},{"style":5545},[5609],{"type":46,"value":5610},"*",{"type":41,"tag":5128,"props":5612,"children":5613},{"style":5162},[5614],{"type":46,"value":5615}," → ",{"type":41,"tag":5128,"props":5617,"children":5618},{"style":5135},[5619],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5621,"children":5622},{"style":5141},[5623],{"type":46,"value":5624},"runtime injection only",{"type":41,"tag":5128,"props":5626,"children":5627},{"style":5135},[5628],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5630,"children":5631},{"style":5162},[5632],{"type":46,"value":5633}," (Kubernetes Secret)\n",{"type":41,"tag":5128,"props":5635,"children":5637},{"class":5130,"line":5636},13,[5638,5642],{"type":41,"tag":5128,"props":5639,"children":5640},{"style":5168},[5641],{"type":46,"value":5214},{"type":41,"tag":5128,"props":5643,"children":5644},{"style":5162},[5645],{"type":46,"value":5646}," ...\n",{"type":41,"tag":5128,"props":5648,"children":5650},{"class":5130,"line":5649},14,[5651],{"type":41,"tag":5128,"props":5652,"children":5653},{"emptyLinePlaceholder":4239},[5654],{"type":46,"value":5190},{"type":41,"tag":5128,"props":5656,"children":5658},{"class":5130,"line":5657},15,[5659,5663],{"type":41,"tag":5128,"props":5660,"children":5661},{"style":5168},[5662],{"type":46,"value":5199},{"type":41,"tag":5128,"props":5664,"children":5665},{"style":5202},[5666],{"type":46,"value":5667},"Next steps\n",{"type":41,"tag":5128,"props":5669,"children":5670},{"class":5130,"line":28},[5671,5676,5681,5685,5690],{"type":41,"tag":5128,"props":5672,"children":5673},{"style":5168},[5674],{"type":46,"value":5675},"1.",{"type":41,"tag":5128,"props":5677,"children":5678},{"style":5162},[5679],{"type":46,"value":5680}," Build locally: ",{"type":41,"tag":5128,"props":5682,"children":5683},{"style":5168},[5684],{"type":46,"value":5171},{"type":41,"tag":5128,"props":5686,"children":5687},{"style":5174},[5688],{"type":46,"value":5689},"docker buildx build --platform=\u003CtargetPlatform> -t \u003Cmodule>:dev \u003CmodulePath>",{"type":41,"tag":5128,"props":5691,"children":5692},{"style":5168},[5693],{"type":46,"value":5181},{"type":41,"tag":5128,"props":5695,"children":5697},{"class":5130,"line":5696},17,[5698,5703,5708,5712,5717,5721],{"type":41,"tag":5128,"props":5699,"children":5700},{"style":5168},[5701],{"type":46,"value":5702},"2.",{"type":41,"tag":5128,"props":5704,"children":5705},{"style":5162},[5706],{"type":46,"value":5707}," Run ",{"type":41,"tag":5128,"props":5709,"children":5710},{"style":5135},[5711],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5713,"children":5714},{"style":5141},[5715],{"type":46,"value":5716},"fix-dockerfile",{"type":41,"tag":5128,"props":5718,"children":5719},{"style":5135},[5720],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5722,"children":5723},{"style":5162},[5724],{"type":46,"value":5725}," to lint and remediate the file against the built-in security and best-practice rules.\n",{"type":41,"tag":5128,"props":5727,"children":5729},{"class":5130,"line":5728},18,[5730,5735,5740,5744,5749,5753],{"type":41,"tag":5128,"props":5731,"children":5732},{"style":5168},[5733],{"type":46,"value":5734},"3.",{"type":41,"tag":5128,"props":5736,"children":5737},{"style":5162},[5738],{"type":46,"value":5739}," Once validated, scan the built image and proceed to ",{"type":41,"tag":5128,"props":5741,"children":5742},{"style":5168},[5743],{"type":46,"value":5171},{"type":41,"tag":5128,"props":5745,"children":5746},{"style":5174},[5747],{"type":46,"value":5748},"generate-k8s-manifests",{"type":41,"tag":5128,"props":5750,"children":5751},{"style":5168},[5752],{"type":46,"value":5171},{"type":41,"tag":5128,"props":5754,"children":5755},{"style":5162},[5756],{"type":46,"value":5757},".\n",{"type":41,"tag":49,"props":5759,"children":5760},{},[5761,5763,5768,5770,5775,5777,5782],{"type":46,"value":5762},"If the result was an ",{"type":41,"tag":509,"props":5764,"children":5765},{},[5766],{"type":46,"value":5767},"enhancement",{"type":46,"value":5769},", also include this section between\n",{"type":41,"tag":509,"props":5771,"children":5772},{},[5773],{"type":46,"value":5774},"Plan",{"type":46,"value":5776}," and ",{"type":41,"tag":509,"props":5778,"children":5779},{},[5780],{"type":46,"value":5781},"Env vars",{"type":46,"value":3041},{"type":41,"tag":2851,"props":5784,"children":5786},{"className":5120,"code":5785,"language":5122,"meta":2859,"style":2859},"### Changes from existing\n- **Preserve:** \u003Cbullet list>\n- **Improve:** \u003Cbullet list>\n- **Add:** \u003Cbullet list>\n",[5787],{"type":41,"tag":101,"props":5788,"children":5789},{"__ignoreMap":2859},[5790,5802,5840,5876],{"type":41,"tag":5128,"props":5791,"children":5792},{"class":5130,"line":5131},[5793,5797],{"type":41,"tag":5128,"props":5794,"children":5795},{"style":5168},[5796],{"type":46,"value":5199},{"type":41,"tag":5128,"props":5798,"children":5799},{"style":5202},[5800],{"type":46,"value":5801},"Changes from existing\n",{"type":41,"tag":5128,"props":5803,"children":5804},{"class":5130,"line":5184},[5805,5809,5813,5818,5822,5826,5831,5836],{"type":41,"tag":5128,"props":5806,"children":5807},{"style":5168},[5808],{"type":46,"value":5214},{"type":41,"tag":5128,"props":5810,"children":5811},{"style":5135},[5812],{"type":46,"value":5219},{"type":41,"tag":5128,"props":5814,"children":5815},{"style":5141},[5816],{"type":46,"value":5817},"Preserve:",{"type":41,"tag":5128,"props":5819,"children":5820},{"style":5135},[5821],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5823,"children":5824},{"style":5168},[5825],{"type":46,"value":5233},{"type":41,"tag":5128,"props":5827,"children":5828},{"style":5236},[5829],{"type":46,"value":5830},"bullet",{"type":41,"tag":5128,"props":5832,"children":5833},{"style":5241},[5834],{"type":46,"value":5835}," list",{"type":41,"tag":5128,"props":5837,"children":5838},{"style":5168},[5839],{"type":46,"value":5290},{"type":41,"tag":5128,"props":5841,"children":5842},{"class":5130,"line":5193},[5843,5847,5851,5856,5860,5864,5868,5872],{"type":41,"tag":5128,"props":5844,"children":5845},{"style":5168},[5846],{"type":46,"value":5214},{"type":41,"tag":5128,"props":5848,"children":5849},{"style":5135},[5850],{"type":46,"value":5219},{"type":41,"tag":5128,"props":5852,"children":5853},{"style":5141},[5854],{"type":46,"value":5855},"Improve:",{"type":41,"tag":5128,"props":5857,"children":5858},{"style":5135},[5859],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5861,"children":5862},{"style":5168},[5863],{"type":46,"value":5233},{"type":41,"tag":5128,"props":5865,"children":5866},{"style":5236},[5867],{"type":46,"value":5830},{"type":41,"tag":5128,"props":5869,"children":5870},{"style":5241},[5871],{"type":46,"value":5835},{"type":41,"tag":5128,"props":5873,"children":5874},{"style":5168},[5875],{"type":46,"value":5290},{"type":41,"tag":5128,"props":5877,"children":5878},{"class":5130,"line":5208},[5879,5883,5887,5892,5896,5900,5904,5908],{"type":41,"tag":5128,"props":5880,"children":5881},{"style":5168},[5882],{"type":46,"value":5214},{"type":41,"tag":5128,"props":5884,"children":5885},{"style":5135},[5886],{"type":46,"value":5219},{"type":41,"tag":5128,"props":5888,"children":5889},{"style":5141},[5890],{"type":46,"value":5891},"Add:",{"type":41,"tag":5128,"props":5893,"children":5894},{"style":5135},[5895],{"type":46,"value":5138},{"type":41,"tag":5128,"props":5897,"children":5898},{"style":5168},[5899],{"type":46,"value":5233},{"type":41,"tag":5128,"props":5901,"children":5902},{"style":5236},[5903],{"type":46,"value":5830},{"type":41,"tag":5128,"props":5905,"children":5906},{"style":5241},[5907],{"type":46,"value":5835},{"type":41,"tag":5128,"props":5909,"children":5910},{"style":5168},[5911],{"type":46,"value":5290},{"type":41,"tag":55,"props":5913,"children":5915},{"id":5914},"constraints",[5916],{"type":46,"value":5917},"Constraints",{"type":41,"tag":669,"props":5919,"children":5920},{},[5921,5941,5953,5958,5975,5986,6005,6010],{"type":41,"tag":599,"props":5922,"children":5923},{},[5924,5926,5931,5933,5939],{"type":46,"value":5925},"The Dockerfile written to disk must be ",{"type":41,"tag":509,"props":5927,"children":5928},{},[5929],{"type":46,"value":5930},"complete and runnable as-is",{"type":46,"value":5932},"\n(no placeholders, no ",{"type":41,"tag":101,"props":5934,"children":5936},{"className":5935},[],[5937],{"type":46,"value":5938},"\u003CTODO>",{"type":46,"value":5940}," markers, no truncation).",{"type":41,"tag":599,"props":5942,"children":5943},{},[5944,5946,5952],{"type":46,"value":5945},"NEVER use ",{"type":41,"tag":101,"props":5947,"children":5949},{"className":5948},[],[5950],{"type":46,"value":5951},"FROM \u003Cimage>:latest",{"type":46,"value":208},{"type":41,"tag":599,"props":5954,"children":5955},{},[5956],{"type":46,"value":5957},"NEVER set any of the secret-pattern env vars in the file. If the user\ninsists, refuse and explain why.",{"type":41,"tag":599,"props":5959,"children":5960},{},[5961,5963,5968,5969,5974],{"type":46,"value":5962},"NEVER include ",{"type":41,"tag":101,"props":5964,"children":5966},{"className":5965},[],[5967],{"type":46,"value":2995},{"type":46,"value":1973},{"type":41,"tag":101,"props":5970,"children":5972},{"className":5971},[],[5973],{"type":46,"value":3002},{"type":46,"value":208},{"type":41,"tag":599,"props":5976,"children":5977},{},[5978,5980,5985],{"type":46,"value":5979},"NEVER end the final stage as ",{"type":41,"tag":101,"props":5981,"children":5983},{"className":5982},[],[5984],{"type":46,"value":38},{"type":46,"value":208},{"type":41,"tag":599,"props":5987,"children":5988},{},[5989,5991,5997,5999,6004],{"type":46,"value":5990},"NEVER omit the ",{"type":41,"tag":101,"props":5992,"children":5994},{"className":5993},[],[5995],{"type":46,"value":5996},"com.azure.containerizationassist.createdby",{"type":46,"value":5998}," label, and NEVER replace either attribution label key with ",{"type":41,"tag":101,"props":6000,"children":6002},{"className":6001},[],[6003],{"type":46,"value":3986},{"type":46,"value":208},{"type":41,"tag":599,"props":6006,"children":6007},{},[6008],{"type":46,"value":6009},"NEVER print the full Dockerfile in the chat response by default — write\nit to disk and reference the path. Print only when the user asks or to\nshow a short excerpt.",{"type":41,"tag":599,"props":6011,"children":6012},{},[6013],{"type":46,"value":6014},"The Dockerfile must pass the G4 self-check before being written. If a\nconstraint conflicts with a user instruction, surface the conflict\nexplicitly and ask before proceeding.",{"type":41,"tag":55,"props":6016,"children":6018},{"id":6017},"failure-modes",[6019],{"type":46,"value":6020},"Failure modes",{"type":41,"tag":62,"props":6022,"children":6023},{},[6024,6040],{"type":41,"tag":66,"props":6025,"children":6026},{},[6027],{"type":41,"tag":70,"props":6028,"children":6029},{},[6030,6035],{"type":41,"tag":74,"props":6031,"children":6032},{},[6033],{"type":46,"value":6034},"Symptom",{"type":41,"tag":74,"props":6036,"children":6037},{},[6038],{"type":46,"value":6039},"Action",{"type":41,"tag":90,"props":6041,"children":6042},{},[6043,6061,6092,6110,6130,6150],{"type":41,"tag":70,"props":6044,"children":6045},{},[6046,6056],{"type":41,"tag":97,"props":6047,"children":6048},{},[6049,6054],{"type":41,"tag":101,"props":6050,"children":6052},{"className":6051},[],[6053],{"type":46,"value":106},{"type":46,"value":6055}," doesn't exist",{"type":41,"tag":97,"props":6057,"children":6058},{},[6059],{"type":46,"value":6060},"Echo the path, ask user to provide a valid one. STOP.",{"type":41,"tag":70,"props":6062,"children":6063},{},[6064,6080],{"type":41,"tag":97,"props":6065,"children":6066},{},[6067,6068,6073,6075],{"type":46,"value":3390},{"type":41,"tag":101,"props":6069,"children":6071},{"className":6070},[],[6072],{"type":46,"value":136},{"type":46,"value":6074}," provided and no manifest file at ",{"type":41,"tag":101,"props":6076,"children":6078},{"className":6077},[],[6079],{"type":46,"value":106},{"type":41,"tag":97,"props":6081,"children":6082},{},[6083,6085,6090],{"type":46,"value":6084},"Ask the user for the language, OR suggest running ",{"type":41,"tag":101,"props":6086,"children":6088},{"className":6087},[],[6089],{"type":46,"value":122},{"type":46,"value":6091}," first. STOP.",{"type":41,"tag":70,"props":6093,"children":6094},{},[6095,6100],{"type":41,"tag":97,"props":6096,"children":6097},{},[6098],{"type":46,"value":6099},"Existing Dockerfile is empty or unreadable",{"type":41,"tag":97,"props":6101,"children":6102},{},[6103,6105,6109],{"type":46,"value":6104},"Treat as Generation path, note this in ",{"type":41,"tag":509,"props":6106,"children":6107},{},[6108],{"type":46,"value":5774},{"type":46,"value":208},{"type":41,"tag":70,"props":6111,"children":6112},{},[6113,6118],{"type":41,"tag":97,"props":6114,"children":6115},{},[6116],{"type":46,"value":6117},"Existing Dockerfile already passes the G4 self-check",{"type":41,"tag":97,"props":6119,"children":6120},{},[6121,6123,6128],{"type":46,"value":6122},"Strategy = ",{"type":41,"tag":101,"props":6124,"children":6126},{"className":6125},[],[6127],{"type":46,"value":5033},{"type":46,"value":6129},"; report \"no changes required\"; leave the file untouched.",{"type":41,"tag":70,"props":6131,"children":6132},{},[6133,6145],{"type":41,"tag":97,"props":6134,"children":6135},{},[6136,6138,6143],{"type":46,"value":6137},"Write to ",{"type":41,"tag":101,"props":6139,"children":6141},{"className":6140},[],[6142],{"type":46,"value":505},{"type":46,"value":6144}," fails (permissions, read-only FS)",{"type":41,"tag":97,"props":6146,"children":6147},{},[6148],{"type":46,"value":6149},"Surface the error and the Dockerfile content for manual save.",{"type":41,"tag":70,"props":6151,"children":6152},{},[6153,6158],{"type":41,"tag":97,"props":6154,"children":6155},{},[6156],{"type":46,"value":6157},"User has a custom registry \u002F non-standard base image preference",{"type":41,"tag":97,"props":6159,"children":6160},{},[6161],{"type":46,"value":6162},"Use the user's choice as base image, still apply all G3 baseline rules.",{"type":41,"tag":6164,"props":6165,"children":6166},"style",{},[6167],{"type":46,"value":6168},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":6170,"total":5193},[6171,6188,6195],{"slug":5716,"name":5716,"fn":6172,"description":6173,"org":6174,"tags":6175,"stars":24,"repoUrl":25,"updatedAt":6187},"validate and remediate Dockerfiles","Validate and remediate an existing Dockerfile against security, performance, and best-practice rules. Use AFTER a Dockerfile exists (either user-authored or produced by generate-dockerfile) and BEFORE building or pushing the image. Triggers include \"fix my Dockerfile\", \"is this Dockerfile secure\", \"validate Dockerfile\", \"check Dockerfile for issues\", \"audit Dockerfile\", or any container build flow that needs a sanity check.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6176,6179,6180,6183,6186],{"name":6177,"slug":6178,"type":16},"Deployment","deployment",{"name":22,"slug":23,"type":16},{"name":6181,"slug":6182,"type":16},"Engineering","engineering",{"name":6184,"slug":6185,"type":16},"Performance","performance",{"name":14,"slug":15,"type":16},"2026-07-12T08:18:23.567237",{"slug":4,"name":4,"fn":5,"description":6,"org":6189,"tags":6190,"stars":24,"repoUrl":25,"updatedAt":26},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6191,6192,6193,6194],{"name":11,"slug":8,"type":16},{"name":19,"slug":20,"type":16},{"name":22,"slug":23,"type":16},{"name":14,"slug":15,"type":16},{"slug":5748,"name":5748,"fn":6196,"description":6197,"org":6198,"tags":6199,"stars":24,"repoUrl":25,"updatedAt":6206},"generate production Kubernetes manifests","Generate production-ready Kubernetes manifests (Deployment, Service, ConfigMap, Secret, ServiceAccount, optional HPA) for a containerized application. Use AFTER a Dockerfile exists and has been validated by fix-dockerfile. Triggers include \"generate kubernetes manifests\", \"deploy this to k8s\", \"write k8s yaml\", \"create deployment yaml\", or when running aks-loop and image is built. Writes manifests directly to the target directory.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6200,6201,6202,6203],{"name":11,"slug":8,"type":16},{"name":19,"slug":20,"type":16},{"name":6177,"slug":6178,"type":16},{"name":6204,"slug":6205,"type":16},"Kubernetes","kubernetes","2026-07-12T08:18:26.554131",{"items":6208,"total":6382},[6209,6228,6245,6264,6278,6293,6306,6321,6332,6344,6357,6370],{"slug":6210,"name":6210,"fn":6211,"description":6212,"org":6213,"tags":6214,"stars":6225,"repoUrl":6226,"updatedAt":6227},"azure-arg-external-evaluation-policy-author","author and test Azure Resource Graph policies","Use when the user wants to author, design, or test an Azure Policy that queries Azure Resource Graph (ARG) at request-time — i.e. a policy whose deny\u002Faudit decision depends on data from elsewhere in the subscription (sibling\u002Fparent resource state, RG-wide invariants, multi-hop relationships, etc.). Formally called Azure Policy External Evaluation; sometimes referred to colloquially as \"Invoke\". Drives an iterative KQL co-design loop against the user's real subscription via `az graph query`, then emits a policy definition, assignment, `.http` test flow, and an `EXPLANATION.md` companion. Read-only; never provisions anything.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6215,6216,6219,6222],{"name":11,"slug":8,"type":16},{"name":6217,"slug":6218,"type":16},"Compliance","compliance",{"name":6220,"slug":6221,"type":16},"Governance","governance",{"name":6223,"slug":6224,"type":16},"Policy","policy",1686,"https:\u002F\u002Fgithub.com\u002FAzure\u002Fazure-policy","2026-07-12T08:17:48.378432",{"slug":6229,"name":6229,"fn":6230,"description":6231,"org":6232,"tags":6233,"stars":6242,"repoUrl":6243,"updatedAt":6244},"azure-blueprints-migration","migrate Azure Blueprints to Template Specs","Use when a user needs to migrate off Azure Blueprints (definitions and\u002For assignments) to Template Specs and Deployment Stacks before the January 31, 2027 retirement. Covers inventory, export, conversion to Bicep, policy decoupling, Template Spec publishing, Deployment Stack deployment with deny-settings, validation, and cutover.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6234,6235,6236,6239],{"name":11,"slug":8,"type":16},{"name":6177,"slug":6178,"type":16},{"name":6237,"slug":6238,"type":16},"Infrastructure as Code","infrastructure-as-code",{"name":6240,"slug":6241,"type":16},"Migration","migration",260,"https:\u002F\u002Fgithub.com\u002FAzure\u002Fazure-blueprints","2026-07-12T08:17:49.646405",{"slug":6246,"name":6246,"fn":6247,"description":6248,"org":6249,"tags":6250,"stars":6261,"repoUrl":6262,"updatedAt":6263},"apiview-feedback-resolution","resolve APIView feedback on Azure SDKs","Analyze and resolve APIView review feedback on Azure SDK PRs. **UTILITY SKILL**. USE FOR: APIView comments, API review feedback, SDK API surface changes. DO NOT USE FOR: general code review, non-APIView feedback. INVOKES: azure-sdk-mcp:azsdk_apiview_get_comments, azure-sdk-mcp:azsdk_typespec_customized_code_update.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6251,6254,6255,6258],{"name":6252,"slug":6253,"type":16},"API Development","api-development",{"name":11,"slug":8,"type":16},{"name":6256,"slug":6257,"type":16},"Code Review","code-review",{"name":6259,"slug":6260,"type":16},"Documentation","documentation",133,"https:\u002F\u002Fgithub.com\u002FAzure\u002Fazure-sdk-tools","2026-07-12T08:17:43.350876",{"slug":6265,"name":6265,"fn":6266,"description":6267,"org":6268,"tags":6269,"stars":6261,"repoUrl":6262,"updatedAt":6277},"azsdk-common-live-and-recorded-tests","deploy resources and run Azure SDK tests","Deploy test resources and run Azure SDK tests in live, record, or playback mode. WHEN: \"run live tests\", \"run recorded tests\", \"deploy test resources\", \"record tests\", \"run tests in record mode\", \"clean up test resources\", \"run tests against live resources\". DO NOT USE FOR: writing new tests, authoring Bicep templates, playback-only test runs without resource deployment. INVOKES: azure-sdk-mcp:azsdk_package_run_tests.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6270,6271,6272,6274],{"name":11,"slug":8,"type":16},{"name":6177,"slug":6178,"type":16},{"name":1183,"slug":6273,"type":16},"sdk",{"name":6275,"slug":6276,"type":16},"Testing","testing","2026-07-12T08:17:44.718943",{"slug":6279,"name":6279,"fn":6280,"description":6281,"org":6282,"tags":6283,"stars":6261,"repoUrl":6262,"updatedAt":6292},"azsdk-common-prepare-release-plan","manage Azure SDK release plan work items","Create, get, update, abandon, and link SDK PRs to release plan work items for Azure SDK releases. **UTILITY SKILL**. USE FOR: \"create release plan\", \"get release plan\", \"update release plan\", \"update API spec in release plan\", \"update SDK details in release plan\", \"abandon release plan\", \"link SDK PR to plan\", \"namespace approval\", \"check release plan status\". DO NOT USE FOR: SDK code generation, pipeline troubleshooting, API review feedback. INVOKES: azure-sdk-mcp:azsdk_create_release_plan, azure-sdk-mcp:azsdk_get_release_plan, azure-sdk-mcp:azsdk_get_release_plan_for_spec_pr, azure-sdk-mcp:azsdk_update_release_plan, azure-sdk-mcp:azsdk_update_api_spec_pull_request_in_release_plan, azure-sdk-mcp:azsdk_update_sdk_details_in_release_plan, azure-sdk-mcp:azsdk_abandon_release_plan, azure-sdk-mcp:azsdk_link_sdk_pull_request_to_release_plan, azure-sdk-mcp:azsdk_link_namespace_approval_issue.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6284,6285,6288,6291],{"name":11,"slug":8,"type":16},{"name":6286,"slug":6287,"type":16},"GitHub","github",{"name":6289,"slug":6290,"type":16},"Project Management","project-management",{"name":1183,"slug":6273,"type":16},"2026-07-12T08:17:38.345387",{"slug":6294,"name":6294,"fn":6295,"description":6296,"org":6297,"tags":6298,"stars":6261,"repoUrl":6262,"updatedAt":6305},"azsdk-common-sdk-release","release Azure SDK packages","Check release readiness and trigger the release pipeline for Azure SDK packages. **UTILITY SKILL**. USE FOR: \"release SDK\", \"trigger release\", \"check release readiness\", \"release pipeline\", \"publish package\", \"ship SDK\". DO NOT USE FOR: SDK development, code generation, pipeline debugging, release plan creation. INVOKES: azure-sdk-mcp:azsdk_release_sdk.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6299,6300,6303,6304],{"name":11,"slug":8,"type":16},{"name":6301,"slug":6302,"type":16},"CI\u002FCD","ci-cd",{"name":6177,"slug":6178,"type":16},{"name":1183,"slug":6273,"type":16},"2026-07-12T08:17:34.27607",{"slug":6307,"name":6307,"fn":6308,"description":6309,"org":6310,"tags":6311,"stars":6261,"repoUrl":6262,"updatedAt":6320},"azure-typespec-author","author and modify Azure TypeSpec API specifications","Authors and modifies Azure TypeSpec (.tsp) API specifications. USE FOR: any TypeSpec\u002Ftsp change — api versions (add, bump, preview, stable, promote), resources, operations, models, properties, decorators, visibility, constraints, breaking changes, LRO, suppressions, operationId, spread model. Covers ARM resource-manager and data-plane services. DO NOT USE FOR: SDK generation, releasing SDK packages, or single MCP tool calls. INVOKES: azure-sdk-mcp:azsdk_typespec_generate_authoring_plan, azure-sdk-mcp:azsdk_run_typespec_validation.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6312,6313,6314,6317],{"name":6252,"slug":6253,"type":16},{"name":11,"slug":8,"type":16},{"name":6315,"slug":6316,"type":16},"OpenAPI","openapi",{"name":6318,"slug":6319,"type":16},"Technical Writing","technical-writing","2026-07-12T08:17:39.603232",{"slug":6322,"name":6322,"fn":6323,"description":6324,"org":6325,"tags":6326,"stars":6261,"repoUrl":6262,"updatedAt":6331},"generate-sdk-locally","generate and test Azure SDKs locally","Generate, build, and test Azure SDKs locally from TypeSpec with automatic customization. WHEN: \"generate SDK locally\", \"build SDK\", \"run SDK tests\", \"run CI checks\", \"validate package\", \"run checks\", \"update changelog\", \"fix SDK build errors\", \"fix breaking changes\", \"resolve SDK generation errors\", \"customize TypeSpec\", \"rename SDK client\", \"rename SDK model\", \"hide operation from SDK\", \"fix analyzer errors\", \"resolve customization drift\", \"create subclient\", \"update metadata\", \"update version\". DO NOT USE FOR: publishing to package registries, CI pipeline configuration, API design review. INVOKES: azsdk_verify_setup, azsdk_package_generate_code, azsdk_package_build_code, azsdk_package_run_check, azsdk_package_run_tests, azsdk_customized_code_update, azsdk_package_update_changelog_content, azsdk_package_update_metadata, azsdk_package_update_version.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6327,6328,6329,6330],{"name":11,"slug":8,"type":16},{"name":6301,"slug":6302,"type":16},{"name":1183,"slug":6273,"type":16},{"name":6275,"slug":6276,"type":16},"2026-07-12T08:17:37.08523",{"slug":6333,"name":6333,"fn":6334,"description":6335,"org":6336,"tags":6337,"stars":6261,"repoUrl":6262,"updatedAt":6343},"markdown-token-optimizer","optimize markdown files for token efficiency","Analyze markdown files for token efficiency and reduce context-window bloat. **UTILITY SKILL**. DO NOT USE FOR: code optimization, general file editing, non-markdown files. TRIGGERS: optimize markdown, reduce tokens, token count, token bloat, too many tokens, make concise, shrink file, file too large, optimize for AI, token efficiency, verbose markdown, reduce file size. INVOKES: waza CLI.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6338,6341,6342],{"name":6339,"slug":6340,"type":16},"LLM","llm",{"name":6184,"slug":6185,"type":16},{"name":6318,"slug":6319,"type":16},"2026-07-12T08:17:42.080413",{"slug":6345,"name":6345,"fn":6346,"description":6347,"org":6348,"tags":6349,"stars":6261,"repoUrl":6262,"updatedAt":6356},"pipeline-troubleshooting","troubleshoot Azure SDK CI pipelines","Diagnose and resolve failures in Azure SDK CI and generation pipelines. **UTILITY SKILL**. USE FOR: \"pipeline failed\", \"build failure\", \"CI check failing\", \"SDK generation error\", \"reproduce pipeline locally\", \"debug SDK pipeline\". DO NOT USE FOR: local build issues without pipeline context, API design review, SDK publishing. INVOKES: azure-sdk-mcp:azsdk_analyze_pipeline, azure-sdk-mcp:azsdk_package_build_code, azure-sdk-mcp:azsdk_package_run_check.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6350,6351,6352,6355],{"name":11,"slug":8,"type":16},{"name":6301,"slug":6302,"type":16},{"name":6353,"slug":6354,"type":16},"Debugging","debugging",{"name":1183,"slug":6273,"type":16},"2026-07-12T08:17:40.821512",{"slug":6358,"name":6358,"fn":6359,"description":6360,"org":6361,"tags":6362,"stars":6261,"repoUrl":6262,"updatedAt":6369},"sensei","improve skill frontmatter compliance","**WORKFLOW SKILL** — Iteratively improve skill frontmatter compliance using the Ralph loop pattern. WHEN: \"run sensei\", \"sensei help\", \"improve skill\", \"fix frontmatter\", \"skill compliance\", \"frontmatter audit\", \"score skill\", \"check skill tokens\". INVOKES: token counting tools, test runners, git commands. FOR SINGLE OPERATIONS: use token CLI directly for counts\u002Fchecks.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6363,6364,6365,6368],{"name":11,"slug":8,"type":16},{"name":6217,"slug":6218,"type":16},{"name":6366,"slug":6367,"type":16},"Process Optimization","process-optimization",{"name":6318,"slug":6319,"type":16},"2026-07-12T08:17:32.970921",{"slug":6371,"name":6371,"fn":6372,"description":6373,"org":6374,"tags":6375,"stars":6261,"repoUrl":6262,"updatedAt":6381},"skill-authoring","author agent skills for agentskills.io","Write Agent Skills that comply with the agentskills.io specification. WHEN: \"create a skill\", \"new skill\", \"write a skill\", \"skill template\", \"skill structure\", \"review skill\", \"skill PR\", \"skill compliance\", \"SKILL.md format\", \"skill frontmatter\", \"skill best practices\". DO NOT USE FOR: improving existing skills (use sensei), general documentation. INVOKES: waza CLI.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[6376,6377,6380],{"name":6259,"slug":6260,"type":16},{"name":6378,"slug":6379,"type":16},"Plugin Development","plugin-development",{"name":6318,"slug":6319,"type":16},"2026-07-12T08:17:35.873862",109]