agentleFS
Microsoft AzureKnown publisherAzure/containerization-assist/skills/fix-dockerfile/SKILL.md

fix-dockerfile

Skill43 starsChanged 5 months agoMITView on GitHub

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.

  • Deletes or force-pushes
  • Installs packages

The file

Show its rules and text

We split this skill into the rules it gives an agent

16 rules. About 0 are common, 6 are distinctive, and 10 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈6

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 10

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    If neither is provided → ask the user for the Dockerfile path.

    line 21
  2. Very specific:

    If path is given, read the file content.

    line 27
  3. Very specific:

    When a rule says "scan lines", split the file on \n, trim each line, ignore empty lines and lines starting with #.

    line 38
  4. Distinctive:

    Start at 100. Subtract 10 per issue (any severity).

    line 75
  5. Very specific:

    After applying all fixes, run Step 2 again as a self-check on the new content.

    line 123
  6. Very specific:

    If path was provided and the file scored below A (any issues found):

    line 129
  7. Very specific:

    If path was provided and the file already scored A with 0 issues: do nothing — the file is fine as-is.

    line 133
  8. Very specific:

    If only inline dockerfile content was provided (no path): you cannot write to disk — say so and include the fixed content inline.

    line 135
  9. Distinctive:

    If the user explicitly asks to see the fixed content (“show me the file”, “print the Dockerfile”, etc.), include it under an extra Fixed …

    line 137
  10. Distinctive:

    Use these exact sections in order:

    line 144
  11. Distinctive:

    If the input scores A with 0 issues, the output collapses to: the

    line 197
  12. Very specific:

    NEVER write a Dockerfile that still has any error-severity issue.

    line 206
  13. Very specific:

    NEVER print the full Dockerfile in chat unless (a) no path was given, or (b) the user explicitly asks to see it.

    line 207
  14. Distinctive:

    NEVER keep a value next to any secret-pattern env var name.

    line 209
  15. Very specific:

    NEVER replace :latest with another floating tag.

    line 211
  16. Very specific:

    NEVER add a HEALTHCHECK that uses tools not present in the base image (e.g.

    line 213

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Fix Dockerfile

Validate an existing Dockerfile against a fixed rule set, score it, and produce a fully remediated version. Deterministic — every rule below is a regex or a structural check, not a judgment call.

Inputs

FieldRequiredDescription
dockerfile or pathyesEither the file contents OR an absolute path. If path is given, read it.
environmentoptionalproduction (default) or development. Some rules downgrade to suggestions in dev.
targetPlatformoptionallinux/amd64 (default) or linux/arm64. Used only in the Next steps section.

If neither is provided → ask the user for the Dockerfile path. STOP.

Procedure

Step 1 — Read the file

If path is given, read the file content. Reject if it doesn't contain at least one FROM line (case-insensitive) — that's not a Dockerfile.

Step 2 — Run every rule

Apply each rule below in order. For each match, record an issue with { ruleId, category, severity, line, message }.

severity ∈ error (must fix) | warning (should fix) | info (nice to fix). category ∈ security | performance | bestPractices.

When a rule says "scan lines", split the file on \n, trim each line, ignore empty lines and lines starting with #.

Security rules (highest priority)

ruleIdPatternSeverityMessage
block-root-userAny line matches ^USER\s+(root|0)\s*$ (case-insensitive multiline)errorRunning as root is forbidden. Replace with a non-root user.
no-root-userNo USER line at all, OR final USER line argument is root/0errorContainer must declare a non-root USER instruction.
block-secrets-in-envAny ENV or ARG line matches (?i)(PASSWORD|PASSWD|SECRET|TOKEN|API[_-]?KEY|PRIVATE[_-]?KEY|ACCESS[_-]?KEY|CREDENTIAL|DATABASE_URL|CONNECTION_STRING|REDIS_URL|MONGODB?_URI|_DSN)\b.*=\s*\S+ with a non-empty, non-placeholder valueerrorHardcoded secret in ENV/ARG. Inject via runtime (Kubernetes Secret).
no-secretsSame as above but covers RUN export FOO=… and RUN echo "FOO=…" shapeserrorHardcoded secret in RUN.
avoid-sudoAny line matches (?i)\bsudo\bwarningDrop sudo; run the entire stage as the required user instead.
avoid-apt-upgradeAny line matches (?i)apt-get\s+(upgrade|dist-upgrade)warningAvoid apt-get upgrade; pin package versions.

Performance / optimization rules

ruleIdPatternSeverityMessage
optimize-package-installRUN line with apt-get install but NO rm -rf /var/lib/apt/lists/* in the same RUNwarningCombine update + install + cleanup in one RUN.
apk-no-cacheapk add without --no-cacheinfoAdd --no-cache to apk add.
recommend-npm-cinpm install without -ginfoUse npm ci for reproducible builds.
excessive-run-commandsCount of RUN lines ≥ 6infoCombine RUN instructions with && to reduce layers.
dependency-orderCOPY . . (or COPY . /<dir>) appears before any COPY package*.json / COPY pom.xml / COPY go.mod / COPY requirements*.txt / COPY Cargo.tomlinfoCopy dependency manifests before source for better layer caching.
recommend-multistageSingle FROM AND any of mvn, gradle, npm run build, go build, cargo build, dotnet publish appears in a RUN lineinfoUse multi-stage build to drop build tools from the final image.

Best-practice / quality rules

ruleIdPatternSeverityMessage
specific-base-imageAny FROM whose tag is latest or missing (no :)warningPin a specific major version tag, never :latest.
require-healthcheckNo line starts with HEALTHCHECK infoAdd HEALTHCHECK (or note why if image is distroless / shell-less).
require-workdirNo WORKDIR line, OR any RUN cd / patterninfoUse WORKDIR instead of cd.
recommend-exposeApplication code references a port (PORT=, LISTEN, :8080, :3000, :5000) but no EXPOSE lineinfoAdd EXPOSE <port> to document the listener.
missing-attribution-labelsNo LABEL com.azure.containerizationassist.createdbyinfoAdd the attribution createdby label (and version if a version is available) for traceability.

Step 3 — Score

Start at 100. Subtract 10 per issue (any severity). Floor at 0.

Grade band:

ScoreGrade
90–100A
75–89B
60–74C
40–59D
0–39F

Step 4 — Compute overall priority

  • high if any security issue has severity error, OR ≥ 3 security issues total.
  • medium if any security/performance/best-practice issue exists.
  • low if no issues found.

Step 5 — Decide remediation strategy

ConditionsStrategy
Grade = F OR ≥ 1 error severity issuerewrite — emit a fully restructured Dockerfile.
Grade ∈ {C, D}refactor — emit the file with targeted edits per issue.
Grade ∈ {A, B}tweak — emit the file with minimal edits; if no issues, return unchanged.

Step 6 — Produce and apply the fixed Dockerfile

Walk every recorded issue and apply the corresponding fix. The fix table:

ruleIdFix
block-root-user / no-root-userAppend (or replace existing) before final CMD/ENTRYPOINT: RUN adduser -D -u 10001 appuser (Alpine) or RUN useradd -m -u 10001 appuser (Debian/Azure Linux), then USER appuser. Choose flavor from base image.
block-secrets-in-env / no-secretsDelete the offending ENV/ARG/RUN line. Add a comment # SECRET: <NAME> — inject via Kubernetes Secret at runtime.
avoid-sudoDrop sudo prefix. If the action requires root, move it before the final USER directive.
avoid-apt-upgradeReplace with apt-get install -y --no-install-recommends <explicit packages>.
optimize-package-installCombine into: RUN apt-get update && apt-get install -y --no-install-recommends <pkgs> && rm -rf /var/lib/apt/lists/*.
apk-no-cacheAdd --no-cache flag.
recommend-npm-ciReplace npm install with npm ci.
excessive-run-commandsChain consecutive RUN lines with &&.
dependency-orderMove the manifest COPY lines above COPY . . and add the dependency install step between them.
recommend-multistageRestructure into two stages: FROM <build-image> AS build … FROM <runtime-image> … COPY --from=build ….
specific-base-imageReplace :latest (or no tag) with a pinned major version from the curated table in generate-dockerfile skill, matching detected language.
require-healthcheckAdd a HEALTHCHECK matching the base image's available tools: curl -fsS http://localhost:<port>/health || exit 1 if curl is present; wget --spider -q http://localhost:<port>/health || exit 1 on Alpine/busybox; for distroless add a comment # HEALTHCHECK: skipped — distroless image has no shell. Use Kubernetes liveness/readiness probe.
require-workdirAdd WORKDIR /app after FROM. Replace any RUN cd /<dir> with WORKDIR /<dir>.
recommend-exposeAdd EXPOSE <port> near the bottom. Infer port from the code reference.
missing-attribution-labelsAdd LABEL com.azure.containerizationassist.createdby="containerization-assist". If you can read the current containerization-assist package version from the environment, also add LABEL com.azure.containerizationassist.version="<version>"; otherwise omit the version label — never hard-code a stale version string. Do NOT use org.opencontainers.image.* keys.

After applying all fixes, run Step 2 again as a self-check on the new content. If any rule still triggers, fix it before writing. Never write a Dockerfile that still violates a security error rule.

Step 7 — Apply the change

  • If path was provided and the file scored below A (any issues found): write the remediated content to that file immediately, using whatever file-editing capability the environment exposes. Do NOT ask the user to copy-paste. Do NOT defer this to a “Next steps” list.
  • If path was provided and the file already scored A with 0 issues: do nothing — the file is fine as-is.
  • If only inline dockerfile content was provided (no path): you cannot write to disk — say so and include the fixed content inline.
  • If the user explicitly asks to see the fixed content (“show me the file”, “print the Dockerfile”, etc.), include it under an extra Fixed Dockerfile section. Otherwise omit it — the file on disk is the artifact, not the chat output.

Output format

Use these exact sections in order:

**Dockerfile validation** — `<path or "(inline)">`

### Score
- **Grade:** <A|B|C|D|F> (<score>/100)
- **Priority:** <high|medium|low>
- **Strategy:** <rewrite|refactor|tweak>

### Issues (<N>)

#### Security (<count>)
- *<severity>* `<ruleId>` (line <line>) — <message>
- ...

#### Performance (<count>)
- *<severity>* `<ruleId>` (line <line>) — <message>
- ...

#### Best practices (<count>)
- *<severity>* `<ruleId>` (line <line>) — <message>
- ...

> If a category has 0 issues, write `- none`.

### Result
✅ Wrote remediated Dockerfile to `<path>`. <N> issue(s) fixed.

> Replace this with `✅ Dockerfile already meets the baseline. No changes
> required.` if the input scored A with 0 issues, OR with `⚠️ Inline
> content — no path provided. Fixed content below.` when only inline
> content was supplied.

### Diff summary
- **Added:** <bullet list of new instructions>
- **Removed:** <bullet list of dropped/replaced instructions>
- **Modified:** <bullet list of in-place edits>

> Omit this section entirely if no changes were applied.

### Fixed Dockerfile *(only when no path was given, or when the user asked to see it)*

```dockerfile
<full remediated Dockerfile content>
```

### Next steps
1. Rebuild: `docker buildx build --platform=<targetPlatform> -t <name>:dev <build-context>`.
2. Re-run **fix-dockerfile** to confirm score is **A** (90+).
3. Once clean, proceed to `generate-k8s-manifests`.

If the input scores A with 0 issues, the output collapses to: the Score section, the Issues section (all “none”), and the Result block — nothing else.

Constraints

  • The artifact is the file on disk, not the chat output. Always write the remediated content to path immediately after Step 6 when changes are needed.
  • NEVER write a Dockerfile that still has any error-severity issue.
  • NEVER print the full Dockerfile in chat unless (a) no path was given, or (b) the user explicitly asks to see it.
  • NEVER keep a value next to any secret-pattern env var name. Even if the user wrote it themselves, surface the violation and remove it.
  • NEVER replace :latest with another floating tag; always a specific major version.
  • NEVER add a HEALTHCHECK that uses tools not present in the base image (e.g. curl on distroless). Use the distroless fallback comment.
  • Preserve the user's choice of base image family (don't switch node:20-alpine → mcr.microsoft.com/... unless :latest forced a retag).
  • Line numbers in the issue list must reference the original file.

Failure modes

SymptomAction
Neither dockerfile nor path providedAsk for one. STOP.
path doesn't exist or isn't readableEcho path, ask user to verify. STOP. Do NOT generate a new Dockerfile — if the user wants one created, point them at the generate-dockerfile skill.
File has no FROM lineReject: "This doesn't look like a Dockerfile." STOP. Do NOT generate one from scratch — use generate-dockerfile for that.
Parse failure (unbalanced quotes, etc.)Surface a single parse-error issue (severity error), skip remaining rules, set Grade = F, Strategy = rewrite.
User insists on keeping a secret in ENVRefuse. Explain that K8s Secrets are the only acceptable path.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.