Chainguard Guardener Dockerfile migration
The Dockerfile migration feature converts your Dockerfiles to use Chainguard Containers. It uses AI to iteratively translate instructions, build images, compare results, and fix issues until the migrated Dockerfile works as expected.
Unlike the Guardener’s Hardened Actions and Commit Verification features, Dockerfile migration does not run through the GitHub App or the .chainguard/ configuration directory. Instead, you drive it locally through chainctl agent dockerfile commands. The AI runs server-side and scans your workspace to perform its analysis, while Docker builds and file access remain local to your machine.
Note: The Guardener is in beta.
Prerequisites
While Dockerfile migration is in beta, your organization needs to join the waitlist. Chainguard will notify you once registration becomes available. You can sign up on The Guardener landing page.
You also need the following:
chainctlinstalled on your local machine. Refer to our installation guide to set this up if you haven’t already done so.- Docker installed and running locally.
- Your Dockerfile and build context (source code and other inputs) present on the same machine where you run the migration.
- A user with permission to accept the Guardener legal terms must accept them for your organization before anyone can run a session. Refer to IAM access below for the roles involved.
If you encounter permission errors, check your available groups and verify role bindings:
chainctl iam organizations list -o table
chainctl iam role-bindings create --parent <group-id> --identity <identity> --role <role-with-repo.create>How it works
The migration agent runs on Chainguard’s servers, but it never touches your machine directly. Every file read, Docker build, and command is requested by the agent and mediated by chainctl on your machine. The local client evaluates each request, and only performs and returns the ones it deems acceptable — so you stay in control of what the agent can do and what data is sent back.
Your machine (client) Chainguard (server)
┌───────────────────────────┐ ┌──────────────────────┐
│ chainctl │◀── request ───│ Migration agent │
│ │ read a file, │ (AI) │
│ Dockerfile │ run a build, │ │
│ build context │ run a command│ │
│ Docker │ │ │
│ ▼ │ │ │
│ evaluate request: │ │ │
│ allowed? │ │ │
│ ▼ │─── result ───▶│ analyzes result, │
│ perform locally, │ (only for │ plans next step │
│ return result │ approved │ │
│ │ requests) │ │
└───────────────────────────┘ └──────────────────────┘Because every action is mediated by the local client, the agent can’t read a file, run a build, or execute a command unless chainctl approves the request first.
Migration steps
During a migration, the agent performs the following steps:
- Parse — reads your original Dockerfile.
- Translate — generates Chainguard equivalents for each instruction.
- Build and compare — builds both the original and migrated images and compares them with
syft, an open source SBOM generator. - Iterate — if differences are found, adjusts and retries.
- Validate — runs functional tests to verify equivalence.
If the agent cannot resolve an issue automatically, it prompts you for guidance with suggested alternatives.
The entire loop takes from five to more than thirty minutes, depending on the complexity of the Dockerfile.
IAM access
Access to Dockerfile migration is governed by Chainguard IAM roles:
| Action | Minimum role |
|---|---|
| Accepting the Guardener legal terms for your organization (required once before anyone can run sessions) | guardener.admin or owner |
| Running Dockerfile migration sessions | guardener.user |
Refer to the Built-in roles and capabilities reference for details.
Commands
chainctl agent dockerfile includes the following subcommands:
| Command | What it does |
|---|---|
build | Migrate a Dockerfile to a Chainguard equivalent image |
optimize | Optimize an already-migrated Dockerfile |
upgrade | Upgrade package versions in a Dockerfile |
validate | Validate a migrated Dockerfile |
Usage examples
To run a basic migration, provide the path to your Dockerfile and a target image tag:
chainctl agent dockerfile build -f Dockerfile \
-t myapp:chainguardIf your image requires build arguments, pass them with --build-arg:
chainctl agent dockerfile build -f Dockerfile \
-t myapp:chainguard \
--build-arg VERSION=1.0For CI environments or automated workflows, use the --non-interactive flag to skip prompts and automatically select the first suggestion:
chainctl agent dockerfile build -f Dockerfile \
--non-interactiveTo resume a migration from a previously saved local state, use --resume:
chainctl agent dockerfile build -f Dockerfile \
--resumeTo optimize an already-migrated Dockerfile:
chainctl agent dockerfile optimize -f DockerfileTo run only specific optimizers, pass a comma-separated list with --optimizers:
chainctl agent dockerfile optimize -f Dockerfile \
--optimizers=cache,securityTo upgrade outdated packages in a Dockerfile:
chainctl agent dockerfile upgrade -f DockerfileTo preview what an upgrade would change without modifying any files, use the --dry-run flag:
chainctl agent dockerfile upgrade -f Dockerfile \
--dry-runTo validate a migrated Dockerfile:
chainctl agent dockerfile validate -f DockerfileAvailable optimizers
When running the optimize subcommand, you can specify one or more of the following optimizers:
cache— Reorders instructions for better layer caching. The order of instructions determines where the build cache is invalidated. Reordering to take better advantage of layer caching leads to faster builds and reduced CI consumption.cleanup— Removes duplicate and redundant instructions. For example, copying one file vsCOPY ..layers— CombinesRUNcommands and merges package installs. Reducing the number of layers results in a smaller image, faster pull times, and lower CI minute consumption.security— Adds--no-cachetoapk, flags secrets, and suggests a non-rootUSER. Skipping theapkcache layer reduces image size, and using a non-root user limits root access to the host and removes the ability to install new packages at runtime.multi-stage— Transforms the Dockerfile into a multi-stage build using Chainguard runtime images. Chainguard containers come in a-devvariant with a package manager and shell, and a distroless runtime variant. Splitting into multiple stages produces a smaller runtime image with a reduced attack surface.native-packages— Replacescurl/bashinstalls with nativeapkpackages, ensuring full provenance of packages rather than just the resulting binary.
Agent access
The migration agent runs server-side, but its access to your environment is scoped to what it needs to analyze and migrate a single Dockerfile:
- Workspace analysis. The agent scans your workspace to understand your Dockerfile and build context.
- Analysis tools. During a migration, the agent has access to tools for:
- Searching the Wolfi
APKINDEX. - Finding which package provides a given binary or library.
- Comparing installed packages and filesystem layers between the original and migrated images.
- Running commands in built images.
- Reading build context files such as
requirements.txt,package.json, and similar.
- Searching the Wolfi
- Interactive guidance. If the agent cannot resolve an issue automatically, it prompts you for guidance with suggested alternatives. In
--non-interactivemode it skips these prompts and automatically selects the first suggestion.
Before and after example
Dockerfile migration has been tested with Python, Go, Node.js, Java, Spring Boot (UBI-based), and multi-stage Argo CD builds. The following example shows a simple Ubuntu-based Dockerfile converted to use cgr.dev/chainguard/wolfi-base:latest.
Before
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y curl git python3
WORKDIR /app
COPY . .
CMD ["python3", "app.py"]After
FROM cgr.dev/chainguard/wolfi-base:latest
RUN apk add --no-cache curl git python3
WORKDIR /app
COPY . .
CMD ["python3", "app.py"]FAQ
What do I need to get started?
You need Docker installed and running locally, chainctl installed and authenticated, and a Chainguard organization that has joined the beta program.
Can I run this in CI?
Yes. Use --non-interactive to skip all prompts, and ensure your CI environment has Docker and a chainctl authentication token.
How long does it take?
The chainctl agent dockerfile commands can take anywhere from five to more than thirty minutes depending on the size and complexity of the Dockerfile. For example, the optimize subcommand takes longer than build because it performs a more in-depth analysis.
Why did I get different results on a second run?
Dockerfile migration is AI-based, which means its behavior is inherently non-deterministic. You may see slightly different results across runs, even with the same inputs. This is expected.
The agent makes probabilistic decisions based on patterns in the data rather than following a fixed set of rules. As a result, it can take different but equally valid paths when analyzing a Dockerfile, choosing optimizations, or resolving build issues. The overall outcome should be consistent across runs, but the exact steps, suggestions, or ordering may vary.
My session ended unexpectedly
A network interruption causes the bidirectional gRPC stream to terminate, ending the session immediately.
The --resume flag only resumes from locally saved migration state, not from the live session. The server-side agent, its conversation history, and any in-flight work are lost when the connection drops. There is currently no server-side session recovery.
What if I don’t have Docker?
Docker is required, since all builds happen on your local machine. A fully managed headless mode with server-side builds is planned for a future release.
Next steps
- Migrating to Chainguard Containers — Manual migration guidance, compatibility charts, and per-language guides.
- Dockerfile Converter (dfc) — A deterministic, open source alternative for converting Dockerfiles.
- Hardened Actions — Recommend and migrate GitHub Actions to hardened, SHA-pinned equivalents.
- Commit Verification — Require cryptographically signed commits in pull requests.