Skip to main content

generate-dockerfile

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/framework). 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.

ソース情報

リポジトリ
Azure/containerization-assist
ソースの最終更新活動
2026年7月16日 16:37
検出された SKILL.md の言語
英語
スター
43
フォーク
20

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
generate-dockerfile
description
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/framework). 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.
argument-hint
<modulePath> <language> [framework] [environment=production|development]
# Generate Dockerfile Produce a production-quality, secure Dockerfile (or enhancement plan for an existing one) for a single module. The output is a complete Dockerfile that the user can write to disk — not a description of one. ## Inputs | Field | Required | Description | |---|---|---| | `modulePath` | yes | Absolute path of the module to containerize (one of the modules from `analyze-repo`). | | `language` | yes | `java` \| `dotnet` \| `javascript` \| `typescript` \| `python` \| `go` \| `rust` \| `php` \| `ruby`. | | `languageVersion` | recommended | E.g. `21`, `8.0`, `20`, `3.11`. Substituted into the base image tag. | | `framework` | optional | E.g. `spring-boot`, `express`, `next`, `django`, `flask`, `asp.net-core`, `gin`. | | `environment` | optional | `production` (default) or `development`. | | `targetPlatform` | optional | `linux/amd64` (default) or `linux/arm64`. | | `detectedDependencies` | optional | Used to choose extra apt/apk packages (e.g. native modules). | | `detectedEnvVars` | optional | List from `analyze-repo`. Used to add `ENV` instructions for `config`/`database` vars and to WARN about `secret`-classified ones (never bake secrets in). | | `existingDockerfile` | optional | If a Dockerfile is already at `<modulePath>/Dockerfile`, read its content and follow the **Enhancement path** instead of the **Generation path**. | ## Prerequisite: analyze-repo This skill needs `language`, `framework`, `detectedDependencies`, and `detectedEnvVars` from the `analyze-repo` skill. If you don't already have that output for `<modulePath>` from earlier in this conversation, follow the `analyze-repo` skill against `<modulePath>` first, then come back. ## Decision: generate or enhance? 1. Check if `<modulePath>/Dockerfile` exists. 2. If **no** → Generation path (Step G1–G4 below). 3. If **yes** → read the file, run **Dockerfile analysis** (Step E1), then Enhancement path (Step E2–E4). --- ## Generation path ### G1 — Choose build strategy Use **multi-stage** if any of these: - `language` ∈ {`java`, `go`, `rust`, `dotnet`} - `language` is `typescript` AND build output is required (`tsc`, `next build`, `vite build`, etc.) - `buildSystem.type` ∈ {`maven`, `gradle`} Otherwise use **single-stage**. The reason this matters: multi-stage drops compilers, SDKs, and source code from the final image — typically 70–90% smaller and a smaller attack surface. ### G2 — Choose the base image(s) **Hard rule: every `FROM` line MUST start with `mcr.microsoft.com/` unless the stack appears in the explicit non-MCR list (G2.3) below.** The Dockerfile is the contract for an Azure-hosted image. Public-registry images (`eclipse-temurin`, `tomcat`, `node`, `python`, `golang`, `rust`) are **not** "alternatives" — they are fallbacks for the few stacks where MCR genuinely does not publish a base. Pick from the catalog in G2.1 first; only if no row matches, drop to G2.3. #### G2.1 — MCR catalog (use these tags, do not invent others) Use only the tags listed here. If your `<LV>` is not in the list, see G2.2 (modernize) or G2.3 (documented fallback) — do NOT guess a tag. **Java — `mcr.microsoft.com/openjdk/jdk`** | `<LV>` | Build tag | Runtime tag | |---|---|---| | 8 | `8-azurelinux` | `8-distroless` | | 11 | `11-azurelinux` | `11-distroless` | | 17 | `17-azurelinux` | `17-distroless` | | 21 | `21-azurelinux` | `21-distroless` | | 25 | `25-azurelinux` | `25-distroless` | These are the only Java major versions on MCR (verified against `https://mcr.microsoft.com/v2/openjdk/jdk/tags/list`). The published tag format is a **single digit major** — `8-azurelinux`, never `1.8-azurelinux` or `8u292-jdk-slim` (those do not exist and fail with `image not found`). MCR does **not** publish a separate `openjdk/jre` repository — for the runtime stage of a JRE-only image, use the `-distroless` variant of the same major (`8-distroless`, `17-distroless`, …) which ships only the JRE. **.NET — `mcr.microsoft.com/dotnet/{sdk,aspnet,runtime}`** | `<LV>` | SDK | ASP.NET runtime | Generic runtime | |---|---|---|---| | 8.0 | `sdk:8.0-azurelinux3.0` | `aspnet:8.0-azurelinux3.0` | `runtime:8.0-azurelinux3.0` | | 9.0 | `sdk:9.0-azurelinux3.0` | `aspnet:9.0-azurelinux3.0` | `runtime:9.0-azurelinux3.0` | **Node.js — `mcr.microsoft.com/azurelinux/{base,distroless}/nodejs`** | `<LV>` | Build tag | Runtime tag | |---|---|---| | 18 | `base/nodejs:18` | `distroless/nodejs:18` | | 20 | `base/nodejs:20` | `distroless/nodejs:20` | | 22 | `base/nodejs:22` | `distroless/nodejs:22` | **Python — `mcr.microsoft.com/azurelinux/{base,distroless}/python`** | `<LV>` | Build tag | Runtime tag | |---|---|---| | 3.11 | `base/python:3.11` | `distroless/python:3.11` | | 3.12 | `base/python:3.12` | `distroless/python:3.12` | Defaults if `languageVersion` is missing: `java=21`, `dotnet=8.0`, `node=20`, `python=3.12`. #### G2.2 — Modernize before falling back If the project targets a version not in G2.1 (typically Python 3.9/3.10, Node 16, Java 7): 1. **Preferred:** bump the build target to the nearest LTS in G2.1 (Python → 3.11, Node → 18). Update package metadata, keep MCR images. 2. Only if modernization is genuinely impossible, drop to G2.3 and document the reason in a `# WHY-NOT-MCR:` comment above the offending `FROM` line. #### G2.3 — Allowed non-MCR fallbacks (closed list) The following bases may appear when, and only when, no MCR row in G2.1 applies. Anything not in this list MUST NOT appear in a `FROM` line. **Hard rule — build images are build-only.** The images in the **Build stage** column below (`maven:*`, `gradle:*`, `golang:*`, `rust:*`, `composer:*`) are builders. They MUST NOT be the final / runtime stage. Using a non-MCR build image obligates a **multi-stage** Dockerfile whose final `FROM` is the matching **Runtime stage** image (an MCR `*-distroless` row from G2.1 wherever one exists). A single-stage Dockerfile that ships a `maven` / `gradle` / `golang` / `rust` builder as the runtime image is a policy violation: it defeats the MCR-runtime goal and ships the full build toolchain plus source in the running image — even though a lone `maven`/`gradle` `FROM` looks "allowed" here. | Stack / Reason | Build stage | Runtime stage | |---|---|---| | Maven builder (MCR ships no Maven-with-JDK image) | `maven:3.9-eclipse-temurin-<LV>` (where `<LV>` ∈ {8, 11, 17, 21}) | use the matching MCR `openjdk/jdk:<LV>-distroless` for runtime | | Gradle builder (MCR ships no Gradle image) | `gradle:<ver>-jdk<LV>` | use the matching MCR `openjdk/jdk:<LV>-distroless` for runtime | | Java EE / Jakarta EE app server (EJB, JSF, full profile — MCR ships no app server) | `maven:3.9-eclipse-temurin-<LV>` or MCR `openjdk/jdk:<LV>-azurelinux` | `jboss/wildfly:<ver>` (WildFly), `payara/server-full:<ver>` (Payara), `tomee:<ver>` (TomEE), or `tomcat:<ver>-jdk<LV>` (servlet-only WAR) | | Servlet/JSP WAR with no EJB | MCR `openjdk/jdk:<LV>-azurelinux` | `tomcat:<ver>-jdk<LV>` | | Go (no MCR base) | `golang:<LV>-alpine` | `gcr.io/distroless/static-debian12:nonroot` (CGO off) or `gcr.io/distroless/base-debian12:nonroot` (CGO on) | | Rust (no MCR base) | `rust:<LV>-slim` | `gcr.io/distroless/cc-debian12:nonroot` | | PHP (no MCR base) | `composer:2` | `php:<LV>-fpm-alpine` or `php:<LV>-apache` | | Ruby (no MCR base) | `ruby:<LV>-slim` | `ruby:<LV>-slim` | **Bare JDK/JRE images (`eclipse-temurin`, `openjdk`, `adoptopenjdk`, `amazoncorretto`, `ibmjava`) are NOT on this list.** For Java versions 8, 11, 17, 21, or 25, the MCR `openjdk/jdk:<LV>-{azurelinux,distroless}` row in G2.1 is mandatory — falling back to `eclipse-temurin:8-jre-alpine` or `adoptopenjdk:8-jre-hotspot` when MCR has the same major is a policy violation, even with a `# WHY-NOT-MCR:` comment. **Tag-name precision for Docker Hub `maven` images:** the only published `maven:3.9-eclipse-temurin-*` tags are `8`, `11`, `17`, `21` — there is **no** `…-jdk` suffix on these. Tags such as `maven:3.9-eclipse-temurin-8-jdk` or `maven:3.9-eclipse-temurin-17-jdk` do **not** exist and fail with `not found`. Use `maven:3.9-eclipse-temurin-17`, not `maven:3.9-eclipse-temurin-17-jdk`. When you use any row from G2.3, prepend a `# WHY-NOT-MCR:` comment above the `FROM` line explaining which condition triggered the fallback (e.g. `# WHY-NOT-MCR: Java EE app server, no MCR equivalent`). **Never invent a tag.** If you are tempted to write `mcr.microsoft.com/<anything>:<LV>-<suffix>` and the exact tag is not in G2.1, stop — either modernize per G2.2 or fall back per G2.3. ### G3 — Construct the Dockerfile **Hard rule: every Dockerfile MUST contain `LABEL com.azure.containerizationassist.createdby="containerization-assist"`, emitted on the line immediately after the `FROM` of the runtime / final stage. No exceptions. A Dockerfile without this label is rejected.** Apply every rule in this checklist: **Layer/structure** - One `WORKDIR` early (use `/app`); never use `cd` in `RUN`. - Copy **dependency manifests first**, install deps, then copy source — to preserve layer cache. - **Source MUST be copied before any build/compile command.** Every build stage that runs `mvn` / `./mvnw` / `gradle` / `./gradlew` / `npm run build` / `tsc` / `dotnet publish` / `go build` / `cargo build` MUST be preceded by a `COPY src ./src` (or equivalent — `COPY . .` for languages without a conventional `src/` layout). Skipping the source copy produces an empty build that fails with errors like "Unable to find main class" or "no main module" at runtime. - Use `RUN` chaining with `&&` to keep layers small. Aim for ≤ 6 `RUN` instructions. - For multi-stage, give each stage a name (`AS build`, `AS runtime`). **Build output & dependencies (derive, never assume)** Where a build writes its artifact, and which dependencies it needs to run, are determined by the project's own config — not by framework convention. Two recurring build failures come from guessing instead of reading: - **Derive the build-output directory; never hardcode it.** Before you `COPY` build output into the runtime stage, find where the build tool actually writes it: 1. Read the build tool's config for a configured output path — e.g. `build.outDir` in `vite.config.*`, `compilerOptions.outDir` in `tsconfig.json`, `outputPath` in `angular.json`, `distDir` in `next.config.*`, `output.path` in `webpack.config.*`, `buildDir` in `nuxt.config.*`. 2. If none is set, use that tool's documented default. 3. If still unsure, run the build in the build stage and `COPY` the directory it actually produced. `build/` is only Create React App's default. Vite, Vue CLI, Angular and most bundlers emit to `dist/`; Next.js to `.next/`. Hardcoding `COPY build/ ...` fails with `"/app/build": not found` on any of them. - **Install full dependencies in the build stage; prune only for runtime.** Compilers and bundlers (`tsc`, `vite`, `webpack`, `rollup`, `esbuild`) almost always live in `devDependencies`. In the build stage run a full install (`npm ci` / `npm install` with **no** `--omit=dev` / `--production`). Running `npm ci --omit=dev` before `npm run build` removes the compiler and fails with `tsc: not found` / exit 127. Only the **runtime** stage may drop dev deps — or, better, copy just the built artifact into a clean runtime image and install nothing there. These two rules hold for any compiled or bundled stack — present or future — so they replace per-framework "copy from X" recipes rather than adding to them. **Security baseline (mandatory)** - Final stage MUST end with a `USER` instruction set to a non-root user. - If the base image already provides one (e.g. `nonroot`, `appuser`), use it; otherwise create one with **two separate instructions** (`USER` is a Dockerfile instruction, not a shell command — it cannot be chained after `RUN ... &&`): - Alpine: ``` RUN adduser -D -u 10001 appuser USER appuser ``` - Debian / Azure Linux: ```
GitHubで見る
この SKILL.md は非常に大きいため、SkillsMP では最初のセクションだけを表示しています。 GitHubで見る