unit 9 · Workplace ecosystem
Execution environments & navigator
Docker eats the control node
you may want to read 3 · ansible-core vs the community package , 26 · Galaxy, requirements.yml & pinning first — but nothing is locked
tl;dr
- An EE is a container image: ansible-core + collections + their Python/system deps, built by ansible-builder.
- ansible-navigator runs playbooks inside an EE by default — the image tag pins your whole runtime.
- Inside an EE, localhost is the container: files "saved locally" vanish when the container is removed.
why it matters AWX/AAP shops run everything inside EE containers — assume collections live on the control node and you’ll install fixes in the wrong place and lose files to a container that no longer exists.
Lesson 3 left you an IOU: in AWX and AAP, neither install model applies — collections are baked into an execution-environment container image. This is where it gets paid. An EE is Docker doing to Ansible what you’ve watched it do to application code.
First, the disease. The model you’ve run since Unit 2 — pip install ansible on a control node, collections pinned through lesson 26’s
requirements.yml — pins collection versions and nothing else. The
control node still has a Python, an ansible-core, a set of system
libraries. No requirements file governs those. Two engineers and a CI
runner can satisfy the same requirements.yml and still be three
different machines. That’s “works on my machine”. A virtualenv shrinks
the blast radius but doesn’t close it.
An execution environment — “EE” in every standup — closes it the way you closed it for apps: put the whole runtime in a container image. One image bundles ansible-core, the collections, and their Python and system dependencies. This is the standard runtime model in AWX/AAP. Jobs there don’t run on the controller’s own Python. They run inside an EE, replacing “install collections on the control node” outright. Unit 2’s setup was for learning. This is its industrialized successor. ansible-builder builds the images: it reads a definition file (base image, collections, Python and system deps) and emits the image.
Running inside the image: ansible-navigator
Meet ansible-navigator , the modern CLI/TUI. Its run
subcommand executes a playbook inside an EE by default — it pulls the
image and runs there, not with your laptop’s Python:
# run in the default EE image — a TUI opens unless you ask for plain output
ansible-navigator run site.yml -i inventories/prod --mode stdout
# pin the exact runtime: the same image tag your AWX/AAP jobs use
ansible-navigator run site.yml --execution-environment-image registry.example.com/company-ee:1.4That second line is the whole point. Local runs and controller runs resolve to the same image, so “works on my machine” stops being a sentence anyone says. The other subcommands interrogate the image, not your machine:
ansible-navigator collections # what does the image actually ship?
ansible-navigator doc ansible.windows.win_service # docs from the EE's collections
ansible-navigator exec # a shell inside the EE — docker exec energyPlain ansible-playbook isn’t deprecated and you’ll keep seeing it daily.
Navigator wraps the same engine. “Run it through navigator” means “run it
in the blessed image”.
The localhost trap
- name: Save an audit report "locally"
hosts: localhost
tasks:
- name: Write the report
ansible.builtin.copy:
content: '{{ audit_summary }}'
dest: /tmp/audit.txt # under navigator: inside the container, gone after the runWhat recognition means here
Nobody expects you to build EEs in week one. Teams keep one or a few
blessed images in a registry. Someone owns the definition file. Adding a
collection means rebuilding the image and bumping the tag — not running
ansible-galaxy on a server. Your day-one bar is smaller:
- “EE” / “the image” in a standup = the execution-environment container, and the tag decides every version in play.
- Know navigator exists and that
runuses an EE by default, so a playbook command that isn’tansible-playbookdoesn’t throw you. - Know the localhost trap, or your first local navigator run will find it for you.
One cert note: the current RHCE exam (EX294) expects you to run playbooks with ansible-navigator and execution environments — lesson 42 picks up the cert story. Nearer to hand is Jenkins, where your new team’s pipelines actually invoke Ansible. A pipeline can install Ansible on the agent or run it through the plugin. Either way you now speak the runtime vocabulary it assumes. That’s next.
at work, this sounds like
- “Which EE does that run in?”
- Which container image and tag supplies the runtime — it fixes the ansible-core, collection and Python versions the playbook gets.
- “Add the collection to the EE and rebuild.”
- Collections aren’t installed on a control node here — ansible-builder bakes them into a new image version, and the tag gets bumped.
self-check — recall, not a test
1 A teammate says “it works in my venv but fails in AWX.” Where do you look first, and why?
2 Your playbook writes a report to /tmp on localhost. Fine under ansible-playbook, but after a navigator run the file is gone. Why?
3 requirements.yml and an EE both “pin versions.” What does each pin, and which pins more?