Skip to Content

Building an AI Agent for Docker Image Optimization

Building an AI Agent for Docker Image Optimization
Building an AI Agent for Docker Image Optimization

Most container images ship hundreds of megabytes the application never touches. Here is how an AI agent finds the bloat, rewrites the Dockerfile, and proves the fix.

Highlights

  • What an AI agent for Docker image optimization actually does, and why an analyze, rewrite, and verify loop beats a one time manual cleanup.
  • Why image size is a security problem, since the base image alone determines 60 to 80 percent of your CVE count and 87 percent of images carry high or critical vulnerabilities.
  • The optimization moves that matter: multi stage builds, distroless images, cache aware layer ordering, dependency pruning, and a strict .dockerignore.
  • A before and after walkthrough that takes a Node.js service from roughly 1.1 GB to about 140 MB, and a Go service to under 20 MB.
  • The agent loop that makes automation safe: propose a change, rebuild, run the tests, scan, compare, and only keep what verifies.
  • Docker's own Gordon agent went GA in May 2026, and the prompt injection flaw found on the way there is a lesson in why human approval gates exist.
  • A starting list, whether you adopt Gordon, wire up Docker Scout and dive, or build your own agent.

According to Sysdig's cloud native security research, 87 percent of container images in production carry high or critical vulnerabilities, and 66 percent of organizations have had a security issue traced back to an insecure image. Most of that risk was never written by your developers. It arrived in the base image, in packages your application has never called once. The 2026 Verizon DBIR made the stakes plain, with vulnerability exploitation rising to 31 percent of breaches as the most common initial access vector. A bloated image is not just slow to pull. It is attack surface you are paying to ship.

The fix has been documented for a decade: pick a minimal base, use multi stage builds, prune what you do not need. What changed in 2026 is who does the work. Docker's own AI agent, Gordon, went generally available in May and will propose exactly these rewrites when you ask it to optimize a Dockerfile, and the same loop is straightforward to build yourself. This guide covers both paths: what an AI agent for Docker image optimization actually does, the moves it knows, the verification that keeps it honest, and where to start.

What an AI agent for Docker image optimization is

An AI agent for Docker image optimization is a language model wired to container tooling that analyzes an image and its Dockerfile, proposes changes such as multi stage builds or a smaller base image, rebuilds the image, and verifies the result against tests, scans, and size targets before keeping the change. It automates Docker image optimization as a loop rather than a one time cleanup, so images stay small as the application evolves.

The verification half of that definition is what separates an agent from an autocomplete. Anyone can ask a chatbot to rewrite a Dockerfile, and Docker's own team found in early testing that raw model output often contained subtle bugs or missed obvious Dockerfile best practices. An agent closes that gap by building what it proposes and measuring the outcome, which turns a plausible suggestion into a proven one.

Why image size is a security and cost problem

Size and container image security are the same problem wearing two shirts, and the numbers make the case better than any argument.

Your base image decides most of your vulnerability count before you write a single instruction. Analyses of scanner output consistently attribute 60 to 80 percent of reported CVEs to the base image alone, because a full OS base pulls in hundreds of packages your service never uses, each one a patch obligation. Moving from a full distribution base to a minimal or distroless one routinely cuts the scanner reported CVE count by 80 to 95 percent with zero application changes. Chainguard's hardened image research measured a 97.6 percent CVE reduction against popular official images, and that entire delta is packages that were never needed.

Size also taxes you operationally on every single pull. A 1 GB image slows cold starts and autoscaling, multiplies registry storage and transfer costs across every node and every deploy, and stretches CI cycles while runners download layers. When a pod needs to scale up during an incident, the difference between a 100 MB pull and a 1 GB pull is the difference between recovering now and recovering later.

Every extra package is also a gift to an attacker who lands inside the container. A shell, a package manager, curl, and a compiler are exactly the tools post exploitation depends on, and a minimal image simply does not ship them.

What the agent inspects first: image layer analysis

Before an agent can shrink anything, it needs to see where the bytes and the risk actually live, and three tools provide that sight. This image layer analysis step is the evidence base for every rewrite the agent proposes.

# Where did the size come from? Every layer, largest contributors first.
docker history --no-trunc myapp:latest

# Interactive layer exploration: which files each instruction added,
# and an efficiency score for wasted bytes.
dive myapp:latest

# What is the risk? CVE counts and base image recommendations.
docker scout cves myapp:latest
docker scout recommendations myapp:latest

# Scanner view for the pipeline: fail on what matters.
trivy image --severity HIGH,CRITICAL myapp:latest

An agent runs these, parses the output, and forms hypotheses a human would recognize instantly: the pip cache was committed into a layer, node_modules includes dev dependencies, build tools shipped into the runtime image, the base is a full distribution when a slim variant exists. Each hypothesis maps to a specific rewrite, which is what the next section catalogs.

Want to practice Docker optimization by doing it?

Reading about multi stage builds is one thing. Watching your own image drop from a gigabyte to a hundred megabytes, then proving it still runs, is what makes the pattern stick. The Docker learning path on KodeKloud takes you from fundamentals through production image patterns in hands on labs, and the KodeKloud playgrounds give you a disposable environment with Docker preinstalled, so you can break, rebuild, and measure images without touching your own machine.

The optimization moves the agent knows

Almost every real Dockerfile rewrite draws from the same short catalog. The agent's job is picking the right moves for your image and proving they hold.

MoveWhat it doesTypical impact
Multi stage buildsCompile in a full build image, copy only artifacts into a clean runtime stage.Removes compilers, headers, and build caches, often hundreds of MB.
Minimal base imageSwap a full OS base for slim, alpine, or distroless images.60 to 95 percent fewer scanner CVEs, large size cut.
Cache aware layer orderCopy dependency manifests and install before copying source.Rebuilds reuse cached layers, CI gets dramatically faster.
Dependency pruningProduction only installs, no dev dependencies, clean package caches.Smaller layers and fewer packages to patch.
Strict .dockerignoreKeep .git, tests, docs, and local env files out of the build context.Smaller context, faster builds, no leaked files in layers.
Run as non rootAdd a dedicated user and drop root in the final stage.No size change, large container image security win.

Here is the shape of a rewrite the agent would propose for a typical Node.js service, with the before as the pattern most repositories still carry.

# BEFORE: single stage on a full base. Roughly 1.1 GB with dev
# dependencies, build tools, and the entire source tree inside.
FROM node:20
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"]
# AFTER: multi stage on alpine, dependencies cached, non root runtime.
FROM node:20-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev            # production dependencies only

FROM node:20-alpine AS runtime
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deps /app/node_modules ./node_modules
COPY src ./src
COPY server.js ./
USER node                        # never run as root
EXPOSE 3000
HEALTHCHECK --interval=30s CMD wget -qO- http://localhost:3000/healthz || exit 1
CMD ["node", "server.js"]

The measured difference on a representative service, with sizes rounded and CVE counts from a standard scanner run, looks like this. Your numbers will vary with your dependencies, but the shape will not.

MetricBefore (node:20, single stage)After (multi stage, alpine)
Image size~1.1 GB~140 MB
OS packagesHundredsDozens
High and critical CVEsDozens, base image dominatedA small handful
Cold pull on a fresh nodeTens of secondsA few seconds

Compiled languages go further. A Go service built in golang:1.23 and shipped in a distroless static runtime lands under 20 MB, because the final image contains the binary, certificates, and nothing else. That is the reduce Docker image size ceiling: an image that is only the application.

# Go: build stage plus distroless runtime, final image under 20 MB.
FROM golang:1.23 AS build
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /out/app ./cmd/app

FROM gcr.io/distroless/static-debian12:nonroot
COPY --from=build /out/app /app
USER nonroot
ENTRYPOINT ["/app"]

The agent loop: propose, build, verify, keep

Now the part that makes this an agent rather than a suggestion box. The loop below is the whole design, and every step exists to catch the failure mode of the step before it.

  1. Analyze. Run the layer and scan tools, parse the results, identify the top opportunities.
  2. Propose. Generate a revised Dockerfile applying one or two moves, not everything at once, so failures are attributable.
  3. Build. docker build the proposal. A failed build rejects the proposal immediately.
  4. Verify. Start the container, hit the health check, run the integration tests, confirm the entrypoint behaves.
  5. Measure. Compare size and scanner output against the baseline. A rewrite that saves 400 MB but adds a critical CVE is a regression.
  6. Keep or revert. Only a proposal that builds, passes, and improves the numbers survives. Everything else is discarded with the failure logged for the next attempt.

A compact version of that loop, with the LLM behind any OpenAI compatible endpoint, fits in one file. The allowlist is the security boundary: the model chooses among safe operations and can never run a free form command, a lesson straight from the least privilege playbook.

import json, subprocess

ALLOWED = {
    "build":   ["docker", "build", "-q", "-f", "Dockerfile.proposed", "-t", "opt:candidate", "."],
    "size":    ["docker", "image", "inspect", "opt:candidate", "--format", "{{.Size}}"],
    "scan":    ["trivy", "image", "--quiet", "--severity", "HIGH,CRITICAL",
                "--format", "json", "opt:candidate"],
    "test":    ["docker", "run", "--rm", "opt:candidate", "npm", "test"],
}

def run(step: str) -> str:
    """Execute one allowlisted step. The model never supplies raw commands."""
    out = subprocess.run(ALLOWED[step], capture_output=True, text=True, timeout=600)
    return out.stdout if out.returncode == 0 else f"FAILED: {out.stderr[-1500:]}"

def optimize(dockerfile: str, baseline: dict, llm) -> str | None:
    prompt = (
        "Rewrite this Dockerfile to shrink the image. Apply at most two changes "
        "(multi stage build, smaller base, cache aware ordering, pruning). "
        f"Baseline: {baseline}. Return only the Dockerfile.\n\n{dockerfile}"
    )
    proposal = llm(prompt)
    open("Dockerfile.proposed", "w").write(proposal)

    if run("build").startswith("FAILED"):   return None      # gate 1: it builds
    if run("test").startswith("FAILED"):    return None      # gate 2: it works
    size  = int(run("size"))
    vulns = sum(len(r.get("Vulnerabilities") or [])
                for r in json.loads(run("scan")).get("Results", []))
    if size >= baseline["size"] or vulns > baseline["vulns"]:
        return None                                          # gate 3: it improves
    return proposal        # verified better: hand to a human for the final diff

Notice what the code does not do. It never pushes to a registry, never edits the real Dockerfile in place, and never treats the model's confidence as evidence. The output of a successful run is a verified proposal a human diffs and approves, which is Docker build automation with a person still holding the merge button.

Gordon's own history is the argument for that last gate. A prompt injection flaw disclosed in February 2026 showed that a malicious metadata label inside a Docker image could hijack the agent's instructions and route arbitrary operations through its tooling. Docker's fix made human approval mandatory, and the GA release surfaces every command and file write for sign off before anything runs. When the vendor that builds the agent concludes it must not act autonomously, your homegrown agent should reach the same conclusion.

The tools you can use today

You do not have to start from zero, and the honest comparison is which layer of the work each tool takes off your plate.

ToolWhat it isWhere it fits
GordonDocker's AI agent, GA since May 2026 in Docker Desktop 4.61+ and the docker ai CLI, free with a Docker account.Ask it to optimize a Dockerfile, debug a container, or generate a Compose file. Human approval on every action.
Docker ScoutCVE analysis and base image recommendations tied to your registry.The measurement half of the loop: what is at risk and which base fixes it.
diveInteractive layer explorer with an efficiency score.Image layer analysis when you want to see exactly which instruction added the bytes.
Slim (SlimToolkit)Automated image minification by observing what the app actually uses.Aggressive size reduction on images you cannot easily rewrite.
Trivy and GrypeOpen source container image scanning in CI.The verification gate that keeps a smaller image from being a riskier one.
Your own agentThe loop above, pointed at your private base images and policies.When rewrites must respect internal conventions no public tool knows.

Where to start

The path is incremental, and the first two steps cost you an hour.

  1. Measure the baseline. Run docker scout cves or Trivy plus dive on your three most deployed images and record size, package count, and high or critical CVEs.
  2. Ask Gordon, or your own agent, to optimize the worst offender, and read the proposed diff instead of accepting it blind.
  3. Apply the two biggest moves by hand if you prefer: a multi stage build and a slim or distroless base cover most of the win.
  4. Add a .dockerignore and reorder layers so dependency installs cache, then watch your CI times drop.
  5. Wire container image scanning into the pipeline with a severity gate, so the optimized image cannot regress quietly.
  6. Automate the loop for new services, with every agent proposal landing as a pull request a human reviews.

Conclusion

Image bloat is the rare problem that is simultaneously a security exposure, a cost line, and a performance tax, and it persists mostly because cleaning it up is tedious rather than hard. That is exactly the shape of work agents are good at. The catalog of moves is small and stable, the verification is mechanical, and the difference between a safe automation and a reckless one is nothing more than gates: build it, test it, scan it, measure it, and put a human in front of the merge.

Start by measuring your three biggest images this week. If the base image is a full distribution and the Dockerfile is single stage, there is a strong chance an afternoon of agent assisted rewriting removes most of your image size and most of your CVE count in one motion.

Ready to Master Docker for Real?

Reading about image optimization is one thing. Rebuilding an image five different ways, measuring each one, and breaking your own build to understand the cache are the skills that stay with you. The Docker learning path on KodeKloud covers containers from fundamentals to production patterns with hands on labs, and the KodeKloud playgrounds give you throwaway Docker environments where every experiment is free. Spin one up and shrink your first image today.

FAQs

Q1: How much can an AI agent actually reduce Docker image size?

The realistic range for a typical single stage image on a full OS base is a 70 to 95 percent reduction, though the exact number depends on the language and how much bloat the original carried. A Node.js or Python service on a full base image commonly starts near 1 GB and lands between 100 and 200 MB after a multi stage rewrite onto a slim or alpine base with production only dependencies. Compiled languages go much further, since a Go or Rust binary in a distroless runtime image regularly lands under 20 MB. The CVE reduction usually tracks the size reduction, because the base image accounts for 60 to 80 percent of scanner findings and a minimal base simply does not ship those packages. Images that are already multi stage and minimal see much smaller gains, which is why the agent's first step is measuring rather than rewriting.

Q2: Is it safe to let an AI agent rewrite my Dockerfile automatically?

It is safe only when the agent's output is gated by verification and a human review, and unsafe as unattended automation. A rewritten Dockerfile can build successfully and still break the application, drop a needed system library, or introduce a base image with worse vulnerabilities, so the loop must build the proposal, run the container and its tests, scan the result, and compare size and CVE counts against the baseline before keeping anything. The February 2026 prompt injection disclosure against Docker's own Gordon agent, where a malicious image metadata label could hijack the agent's instructions, is the concrete reason the shipped product now requires human approval for every command. Follow the same design: the agent proposes, the pipeline verifies, and a person approves the diff. Never grant an optimization agent push access to your registry or write access to the production Dockerfile.

Q3: Should I use Docker's Gordon or build my own optimization agent?

Start with Gordon, and build your own only when you hit its edges. Gordon is free with a Docker account, ships inside Docker Desktop 4.61 and later plus the docker ai CLI, already knows your local containers and files, and went GA in May 2026 with persistent memory and a mandatory approval gate on every action, so the integration work is already done. Building your own agent makes sense when you need things a general tool cannot know: enforcing your organization's approved base images, respecting internal registry and proxy conventions, running your specific integration test suite as the verification gate, or operating inside CI where a desktop assistant does not fit. The two are not exclusive, and a common pattern is Gordon for interactive developer use with a custom pipeline agent enforcing policy on every pull request.

Q4: What do I need to know before automating Docker image optimization?

You need solid Docker fundamentals rather than any machine learning background. That means understanding how layers and build cache work, what multi stage builds do, why base image choice drives both size and CVE count, and how to read the output of tools like dive, Docker Scout, and Trivy, because the agent's proposals are only reviewable if you can judge them. Comfort with your CI system matters for wiring the verification gates, and basic container security awareness, non root users, minimal packages, and no secrets in layers, keeps an optimization from becoming a regression. If you want structured practice, the Docker learning path on KodeKloud builds exactly these fundamentals in hands on labs, and the KodeKloud playgrounds let you experiment with builds and scanners in a disposable environment before touching your real pipeline.

Q5: Do distroless images make debugging harder?

Yes, by design, and the trade is worth it in production with two escape hatches. Distroless images ship no shell and no package manager, which is precisely why their attack surface and CVE counts are so low, but it also means docker exec into a shell does not work. The first escape hatch is debug variants: distroless publishes :debug tags that include busybox, so you can run the debug tag in a development environment while shipping the plain tag to production. The second is Kubernetes ephemeral debug containers, where kubectl debug attaches a fully tooled sidecar to a running pod without changing the image at all. Teams that adopt these two patterns keep the security benefit without losing the ability to investigate, and the agent can encode the policy directly: distroless for the runtime stage, debug tooling only ever attached from outside.

Q6: How does image optimization relate to container image scanning and security?

They are two halves of one control, and each is weaker alone. Container image scanning tells you which vulnerabilities are present, but on a bloated image most findings live in packages your application never uses, which buries the signal and turns patching into an endless chore. Optimization removes those packages entirely, shrinking the finding list to things that actually matter, which is why re basing onto a minimal or distroless image routinely cuts scanner reported CVEs by 80 to 95 percent without touching application code. Scanning then becomes the regression gate that keeps the optimized image honest, failing the build if a new base or dependency reintroduces critical findings. The agent loop uses them together: optimize to reduce the attack surface, scan to prove the reduction, and block any change that improves size while worsening security.

Pramodh Kumar M Pramodh Kumar M

Subscribe to Newsletter

Join me on this exciting journey as we explore the boundless world of web design together.