ansible-builder
ansible-builder automates the creation of execution environment (EE) container images. An execution environment packages ansible-core, ansible-runner, collections, Python dependencies, and system packages into a single container image — providing a consistent, reproducible Ansible control node for development, CI/CD, and production use with Ansible Automation Platform.
Builder takes a declarative YAML definition file and produces a container image through a multi-stage build process, using Podman or Docker as the container runtime.
Installation
Section titled “Installation”# Via the full suite (recommended)pip install ansible-dev-tools
# Standalonepip install ansible-builderVerify installation:
ansible-builder --versionCore concepts
Section titled “Core concepts”Execution environments
Section titled “Execution environments”An execution environment (EE) is a container image that serves as an Ansible control node. It contains everything needed to run Ansible automation:
- Python interpreter
ansible-coreansible-runner- Ansible collections
- Python package dependencies
- System package dependencies
EEs ensure that playbooks run identically across development, CI/CD, and production — eliminating “works on my machine” problems.
The definition file
Section titled “The definition file”An execution-environment.yml file declares what goes into the image. Builder reads this file and generates a Containerfile/Dockerfile, then builds the image.
Four-stage build process
Section titled “Four-stage build process”Builder creates EE images through four internal stages, each optimized for layer caching:
- Base stage — Pulls the base image, installs Python interpreter, pip,
ansible-core, andansible-runner - Galaxy stage — Downloads collections from Galaxy, collects their Python and system dependency metadata
- Builder stage — Merges Python dependencies, downloads and builds Python wheels, downloads system packages
- Final stage — Integrates all stages, installs collections, system packages, and Python packages into the final image
EE definition file (v3)
Section titled “EE definition file (v3)”Version 3 is the current and recommended schema. It has seven top-level sections:
---version: 3
images: base_image: name: docker.io/redhat/ubi9:latest
dependencies: ansible_core: package_pip: ansible-core==2.17.0 ansible_runner: package_pip: ansible-runner galaxy: requirements.yml python: - boto3>=1.26 - requests - psutil system: bindep.txt python_interpreter: package_system: python3.12 python_path: /usr/bin/python3.12 exclude: python: - docker system: - python3-Cython
build_arg_defaults: ANSIBLE_GALAXY_CLI_COLLECTION_OPTS: '--pre' ANSIBLE_GALAXY_CLI_ROLE_OPTS: '' PKGMGR_PRESERVE_CACHE: ''
additional_build_files: - src: files/ansible.cfg dest: configs - src: scripts/ dest: scripts
additional_build_steps: prepend_base: - RUN echo "Base stage prep" append_base: - RUN echo "Base stage done" prepend_galaxy: - COPY _build/configs/ansible.cfg /etc/ansible/ansible.cfg append_galaxy: [] prepend_builder: [] append_builder: [] prepend_final: - RUN whoami append_final: - RUN echo "Build complete"
options: container_init: cmd: ["bash"] entrypoint: ["/opt/builder/bin/entrypoint", "dumb-init"] package_pip: dumb-init==1.2.5 package_manager_path: /usr/bin/dnf skip_ansible_check: false relax_passwd_permissions: true workdir: /runner user: 1000 tags: - my-ee:latest - my-ee:1.0.0version
Section titled “version”Required. Must be 3.
images
Section titled “images”Defines the base container image:
images: base_image: name: docker.io/redhat/ubi9:latest signature_original_name: registry.redhat.io/ubi9:latest # for mirrored imagesUse host/namespace/container:tag format. The signature_original_name field is for verifying signed images that have been mirrored to a different registry (Podman only).
dependencies
Section titled “dependencies”Declares everything the EE needs beyond the base image:
ansible_core and ansible_runner
Section titled “ansible_core and ansible_runner”dependencies: ansible_core: package_pip: ansible-core==2.17.0 ansible_runner: package_pip: ansible-runner>=2.4.0Values are passed directly to pip — can be version pins, URLs, or package names.
galaxy (collections)
Section titled “galaxy (collections)”Three formats supported:
# File referencedependencies: galaxy: requirements.yml
# Inline dictdependencies: galaxy: collections: - name: community.general - name: ansible.utils version: "3.0.0" - name: company.internal source: https://galaxy.internal.company.com/
# Inline stringdependencies: galaxy: | collections: - community.general - ansible.utilspython (Python packages)
Section titled “python (Python packages)”# File referencedependencies: python: requirements.txt
# Inline list (PEP 508 format)dependencies: python: - boto3>=1.26 - requests - jmespath - pywinrm # for Windows hostssystem (system packages)
Section titled “system (system packages)”# File referencedependencies: system: bindep.txt
# Inline list (bindep format)dependencies: system: - gcc [compile] - python3-devel [compile] - libffi-devel [compile] - iputils [platform:rpm] - openssh-clientsBindep format markers:
| Marker | Meaning |
|---|---|
[compile] |
Needed only during build, not in final image |
[platform:rpm] |
Platform selector |
[epel] |
Enables EPEL repos before install |
| (no marker) | Runtime requirement, installed into final image |
python_interpreter
Section titled “python_interpreter”Override the Python interpreter in the base image:
dependencies: python_interpreter: package_system: python3.12 python_path: /usr/bin/python3.12exclude
Section titled “exclude”Exclude specific dependencies discovered from collections:
dependencies: exclude: python: - docker - podman system: - python3-Cython all_from_collections: - community.docker - ~community\..+ # regex: exclude all community.* collection depsThe ~ prefix enables regex matching for collection names.
build_arg_defaults
Section titled “build_arg_defaults”build_arg_defaults: ANSIBLE_GALAXY_CLI_COLLECTION_OPTS: '--pre' ANSIBLE_GALAXY_CLI_ROLE_OPTS: '--force' PKGMGR_PRESERVE_CACHE: alwaysadditional_build_files
Section titled “additional_build_files”Copy files into the build context for use in custom build steps:
additional_build_files: - src: files/ansible.cfg dest: configs - src: scripts/post-install.sh dest: scriptsFiles are placed under _build/<dest>/ in the build context, accessible in build steps as COPY _build/<dest>/<filename> /target/path.
additional_build_steps
Section titled “additional_build_steps”Inject custom commands at eight hook points in the build process:
| Hook | When it runs |
|---|---|
prepend_base |
Before base stage operations |
append_base |
After base stage operations |
prepend_galaxy |
Before collection download |
append_galaxy |
After collection download |
prepend_builder |
Before dependency builds |
append_builder |
After dependency builds |
prepend_final |
Before final assembly |
append_final |
After final assembly |
Do NOT use USER directives in build steps — use options.user instead.
options
Section titled “options”options: container_init: cmd: ["bash"] entrypoint: ["/opt/builder/bin/entrypoint", "dumb-init"] package_pip: dumb-init==1.2.5 package_manager_path: /usr/bin/dnf skip_ansible_check: false skip_pip_install: false relax_passwd_permissions: true workdir: /runner user: 1000 tags: - my-ee:latest| Option | Default | Description |
|---|---|---|
package_manager_path |
/usr/bin/dnf |
System package manager (also supports microdnf) |
skip_ansible_check |
false |
Skip validation of ansible/runner installation |
skip_pip_install |
false |
Skip pip installation into base image |
relax_passwd_permissions |
true |
Grant GID 0 write to /etc/passwd |
workdir |
/runner |
Working directory in the image |
user |
1000 |
User ID for the image |
tags |
["ansible-execution-env:latest"] |
Image tags |
CLI reference
Section titled “CLI reference”ansible-builder build
Section titled “ansible-builder build”Build the container image (generates context + builds):
# Basic buildansible-builder build
# Custom tagansible-builder build --tag my-org/my-ee:latest
# Multiple tagsansible-builder build --tag my-ee:latest --tag my-ee:1.0.0
# Custom definition fileansible-builder build --file custom-ee.yml
# Use Docker instead of Podmanansible-builder build --container-runtime docker
# Pass build argumentsansible-builder build --build-arg HTTP_PROXY=http://proxy:8080
# Prune dangling images after buildansible-builder build --prune-images
# Verbose outputansible-builder build -v 3Options:
| Flag | Description | Default |
|---|---|---|
--tag, -t |
Image name/tag (repeatable) | ansible-execution-env:latest |
--file, -f |
EE definition file path | execution-environment.yml |
--context, -c |
Build context output directory | context |
--container-runtime |
podman or docker |
podman |
--build-arg |
Build-time variables (repeatable) | — |
--prune-images |
Remove dangling images after build | false |
--squash |
Layer squash: new, all, off (Podman only) |
off |
--galaxy-keyring |
GPG keyring for collection signature verification | — |
--container-policy |
Image validation: ignore_all, system, signature_required |
— |
--container-keyring |
GPG keyring for container image validation | — |
-v, --verbosity |
Verbosity level (0-3) | 2 |
ansible-builder create
Section titled “ansible-builder create”Generate the build context and Containerfile without building:
# Generate onlyansible-builder create
# Inspect the generated Containerfilecat context/ContainerfileUseful for:
- Reviewing what Builder will do before building
- Generating artifacts to build on a different platform (CI/CD)
- Customizing the Containerfile manually before building
ansible-builder introspect
Section titled “ansible-builder introspect”Inspect installed collections and report their dependencies:
# Introspect default collections pathansible-builder introspect /usr/share/ansible/collections
# Clean and deduplicate outputansible-builder introspect --sanitize /path/to/collections
# Write combined requirements to filesansible-builder introspect --sanitize \ --write-pip requirements.txt \ --write-bindep bindep.txt \ /path/to/collections
# Merge with user requirementsansible-builder introspect --sanitize \ --user-pip my-requirements.txt \ --user-bindep my-bindep.txt \ /path/to/collectionsThis is primarily useful for collection authors to verify their declared dependencies.
Collection-level dependencies
Section titled “Collection-level dependencies”Collections declare their dependencies in meta/execution-environment.yml:
dependencies: python: requirements.txt system: bindep.txtOr directly via files in the collection root:
requirements.txt— Python dependenciesbindep.txt— System dependencies
Builder automatically discovers and merges these during the Galaxy and Builder stages.
Container runtime integration
Section titled “Container runtime integration”| Feature | Podman | Docker |
|---|---|---|
| Default runtime | Yes | No (use --container-runtime docker) |
| Build file name | Containerfile |
Dockerfile |
| Image signature verification | Yes (--container-policy) |
Not supported |
| Layer squashing | Yes (new, all, off) |
Not supported |
| Build args | Yes | Yes |
| Multi-tag support | Yes | Yes |
Image signature verification (Podman only)
Section titled “Image signature verification (Podman only)”ansible-builder build \ --container-policy signature_required \ --container-keyring /path/to/keyring.gpgPolicies:
ignore_all— No signature checkssystem— Use system-levelpolicy.jsonsignature_required— All referenced images must have valid signatures
Using the community-ansible-dev-tools image as a base
Section titled “Using the community-ansible-dev-tools image as a base”The ADT container image works as an EE base with all tools pre-installed:
---version: 3images: base_image: name: ghcr.io/ansible/community-ansible-dev-tools:latestdependencies: galaxy: requirements.yml python: requirements.txtoptions: package_manager_path: /usr/bin/dnf5Editor integration
Section titled “Editor integration”The VS Code extension integrates with ansible-builder through:
- ansible-creator scaffolding of EE projects (generating
execution-environment.ymlwith CI/CD workflows) - ansible-navigator’s
:buildersubcommand for building EEs from within the navigator TUI - Image introspection to display EE contents (collections, packages, versions) in the extension’s views
Migrating from v1/v2
Section titled “Migrating from v1/v2”Versions 1 and 2 of the definition schema are deprecated (as of ansible-builder 3.2) and will be removed in 3.3. Key migration steps:
- Set
version: 3 - Move
build_arg_defaults.EE_BASE_IMAGEtoimages.base_image.name - Remove
build_arg_defaults.EE_BUILDER_IMAGE(no longer needed) - Update
additional_build_stepskeys fromprepend/appendto stage-specific hooks
Next steps
Section titled “Next steps”Your execution environment is built. Secure it for production:
- Run playbooks in your new EE with ansible-navigator — use the image you just built
- Sign your project with ansible-sign — protect the content from tampering before deploying to Automation Platform
- CLI Reference — complete v3 schema specification, CLI flags, and bindep format
- PyPI: ansible-builder
- GitHub: ansible/ansible-builder