Ansible Execution Environments

Automation breaks when two machines carry different versions of Ansible, Python, or libraries. A playbook that works on a laptop fails on a build server because a library is missing. An execution environment (EE) solves the problem by packing Ansible, Python, collections, and system tools into a container image. Think of a lunch box that holds the meal, cutlery, and a napkin: it travels anywhere and behaves the same at every table.

Diagram: Same Image, Every Place

        ┌──────────────────────────────────┐
        │   Execution Environment Image    │
        │  ┌────────────────────────────┐  │
        │  │ ansible-core 2.16          │  │
        │  │ Python 3.11 + libraries    │  │
        │  │ Collections: aws, k8s      │  │
        │  │ System tools: git, rsync   │  │
        │  └────────────────────────────┘  │
        └───────┬──────────┬───────────┬───┘
                │          │           │
                ▼          ▼           ▼
          ┌─────────┐ ┌─────────┐ ┌─────────┐
          │ Laptop  │ │ CI/CD   │ │   AWX   │
          └─────────┘ └─────────┘ └─────────┘
          identical behavior everywhere

Tools Involved

ToolPurpose
ansible-builderBuilds an execution environment image from a definition file
ansible-navigatorRuns playbooks inside an image with a text interface
ansible-runnerRuns Ansible in an isolated process or container, used by AWX
Podman or DockerContainer engine that builds and starts the image

Install the Tools

python3 -m pip install ansible-builder ansible-navigator
podman --version

Write the Definition File

The file execution-environment.yml lists everything the image needs.

---
version: 3

images:
  base_image:
    name: quay.io/centos/centos:stream9

dependencies:
  ansible_core:
    package_pip: ansible-core==2.16.4
  ansible_runner:
    package_pip: ansible-runner
  galaxy: requirements.yml
  python: requirements.txt
  system: bindep.txt
# requirements.yml
collections:
  - name: amazon.aws
  - name: community.general

# requirements.txt
boto3
botocore

# bindep.txt
git [platform:rpm]
rsync [platform:rpm]

Build the Image

ansible-builder build --tag shop-ee:1.0
podman images

The builder installs each dependency in layers. A build can take several minutes on the first run.

Run a Playbook Inside the Image

ansible-navigator run site.yml \
  --execution-environment-image shop-ee:1.0 \
  --mode stdout

Navigator mounts the project folder into the container, runs the playbook, and prints results. Add --mode interactive for a text user interface that lets you browse plays and task details.

Set Defaults for the Project

# ansible-navigator.yml
ansible-navigator:
  execution-environment:
    image: shop-ee:1.0
    pull:
      policy: missing
  mode: stdout

Inspect an Image

ansible-navigator images
ansible-navigator collections
ansible-navigator doc ansible.builtin.copy

Share the Image

Push the image to a container registry so CI systems and AWX can pull it.

podman tag shop-ee:1.0 registry.example.com/automation/shop-ee:1.0
podman push registry.example.com/automation/shop-ee:1.0

Tag images with version numbers. A fixed tag guarantees the same toolset on every run, and a new tag rolls out upgrades on a schedule.

Benefits

  • Identical tool versions across laptops, pipelines, and AWX
  • No Python package clashes on the host system
  • Faster onboarding, since new teammates pull one image
  • Simple rollback by switching to an earlier tag

Try This

Write a definition file that includes the community.general collection. Build the image with a tag of your choice. Run ansible-navigator collections --execution-environment-image with that tag and confirm the collection appears in the list.

Summary

An execution environment is a container image that bundles Ansible, Python, collections, and system tools. The ansible-builder tool creates the image from a definition file, and ansible-navigator runs playbooks inside it. A shared, versioned image removes the "works on my machine" problem and gives every pipeline and teammate the same trusted toolset.