Ansible Builder — Build Custom Execution Environments
Introduction
Ansible Builder (ansible-builder) is a command-line tool that creates container images called Execution Environments (EEs). EEs package ansible-core, collections, Python libraries, and system dependencies into a single container — ensuring consistent playbook execution across development, CI/CD, and production.
Install ansible-builder
# Install via pip
pip install ansible-builder
# Verify installation
ansible-builder --version
Execution Environment Definition
The execution-environment.yml file defines what goes into your EE:
---
version: 3
# Base image
images:
base_image:
name: quay.io/ansible/ansible-runner:latest
# Dependencies
dependencies:
galaxy:
collections:
- amazon.aws >= 8.0.0
- community.general >= 9.0.0
- community.vmware >= 5.0.0
- kubernetes.core >= 4.0.0
- ansible.posix >= 1.6.0
python:
- boto3 >= 1.35.0
- botocore >= 1.35.0
- pyVmomi >= 8.0.3
- kubernetes >= 30.0.0
- jmespath >= 1.0.1
- netaddr >= 1.0.0
system:
- openssh-clients [platform:rpm]
- sshpass [platform:rpm]
- openssh-client [platform:dpkg]
- sshpass [platform:dpkg]
# Additional build steps
additional_build_steps:
prepend_galaxy:
- ENV ANSIBLE_GALAXY_CLI_COLLECTION_OPTS="--pre"
prepend_final:
- RUN whoami
- RUN pip3 install --upgrade pip
append_final:
- RUN ansible --version
- LABEL maintainer="your-team@example.com"
# Build options
build_arg_defaults:
ANSIBLE_GALAXY_CLI_COLLECTION_OPTS: "--pre"
Build the EE Image
# Basic build
ansible-builder build -t my-ee:latest
# Build with specific tag
ansible-builder build -t registry.example.com/ansible/my-ee:1.0.0
# Build with verbose output
ansible-builder build -t my-ee:latest -v 3
# Build using a specific container runtime
ansible-builder build -t my-ee:latest --container-runtime docker
ansible-builder build -t my-ee:latest --container-runtime podman
# Build from a specific file
ansible-builder build -t my-ee:latest -f execution-environment.yml
# Create Containerfile without building
ansible-builder create --file execution-environment.yml
EE Definition File Versions
# Version 1 (legacy)
---
version: 1
dependencies:
galaxy: requirements.yml
python: requirements.txt
system: bindep.txt
# Version 3 (current — inline dependencies)
---
version: 3
dependencies:
galaxy:
collections:
- name: amazon.aws
version: ">=8.0.0"
python:
- boto3>=1.35.0
system:
- gcc [compile]
Use Separate Requirements Files
# execution-environment.yml
---
version: 3
dependencies:
galaxy: requirements.yml
python: requirements.txt
system: bindep.txt
# requirements.yml
---
collections:
- name: amazon.aws
version: ">=8.0.0"
- name: community.general
- name: ansible.posix
# requirements.txt
boto3>=1.35.0
pyVmomi>=8.0.3
jmespath>=1.0.1
# bindep.txt
openssh-clients [platform:centos-9 platform:rhel-9]
sshpass [platform:centos-9 platform:rhel-9]
openssh-client [platform:debian platform:ubuntu]
gcc [compile platform:centos-9 platform:rhel-9]
Run Playbooks with Custom EE
# Using ansible-navigator
ansible-navigator run site.yml \
--eei my-ee:latest \
--mode stdout
# Using ansible-runner
ansible-runner run . \
--container-image my-ee:latest \
-p site.yml
# Push to registry
podman push my-ee:latest registry.example.com/ansible/my-ee:latest
docker push my-ee:latest registry.example.com/ansible/my-ee:latest
Multi-Stage Build Example
---
version: 3
images:
base_image:
name: quay.io/ansible/ansible-runner:latest
dependencies:
galaxy:
collections:
- amazon.aws
- community.general
- community.vmware
- kubernetes.core
- ansible.posix
- community.crypto
python:
- boto3
- pyVmomi
- kubernetes
- cryptography
system:
- gcc [compile]
- python3-devel [compile]
- libffi-devel [compile]
additional_build_steps:
append_final:
- RUN pip3 cache purge
- RUN rm -rf /tmp/*
- RUN ansible-galaxy collection list
Inspect an EE
# List installed collections
podman run --rm my-ee:latest ansible-galaxy collection list
# Check ansible version
podman run --rm my-ee:latest ansible --version
# Check Python packages
podman run --rm my-ee:latest pip3 list
# Interactive shell
podman run --rm -it my-ee:latest /bin/bash
CI/CD Pipeline
# .github/workflows/build-ee.yml
name: Build Execution Environment
on:
push:
paths: ['execution-environment.yml', 'requirements.*', 'bindep.txt']
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install ansible-builder
run: pip install ansible-builder
- name: Build EE
run: ansible-builder build -t my-ee:${{ github.sha }}
- name: Push to GHCR
run: |
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
docker tag my-ee:${{ github.sha }} ghcr.io/${{ github.repository }}/my-ee:latest
docker push ghcr.io/${{ github.repository }}/my-ee:latest
Troubleshooting
# Build fails on collection install
ansible-builder build -t my-ee:latest -v 3 2>&1 | grep -i error
# Galaxy timeout — use proxy or mirror
export ANSIBLE_GALAXY_SERVER_LIST=my_galaxy
ansible-builder build -t my-ee:latest
# Check generated Containerfile
ansible-builder create
cat context/Containerfile
# Disk space issues
podman system prune -a
docker system prune -a
Related Articles
- Ansible Execution Environments vs virtualenv vs Docker
- Ansible at Scale — Patterns for Large Fleets
- Ansible Navigator — Modern CLI Interface
- Ansible Automation Platform Architecture
Conclusion
ansible-builder build -t is the core command for creating Execution Environments. Define your dependencies in execution-environment.yml, build with a single command, and push to a container registry. EEs eliminate "works on my machine" problems and ensure every playbook run uses identical dependencies.