← Back to posts

Testing Ansible Roles Locally with Molecule and Docker

A quick start guide to initialize and use Molecule with the Docker driver to test your Ansible roles before deploying.

Case Snapshot

Situation

During enterprise Linux and virtualization operations across multi-team environments, this case came from work related to "Testing Ansible Roles Locally with Molecule and Docker."

Issue

Needed a repeatable way to initialize and use Molecule with the Docker driver to test your Ansible roles before deploying.

Solution

Implemented a practical runbook/automation pattern with clear safety checks, execution steps, and verification points.

Used In

Used in Linux platform engineering, middleware operations, and datacenter modernization projects in regulated environments.

Impact

Improved repeatability, reduced incident risk, and made operational handoffs clearer across teams.

Situation

Pushing Ansible role changes directly to a development environment can be slow and risky. Molecule provides a framework for testing Ansible roles locally, spinning up temporary instances (like Docker containers), running your role, and verifying the state.

Task 1 – Installation and Initialization

First, ensure you have Ansible and Molecule installed in your Python virtual environment.

# Set up a virtual environment
python3 -m venv .venv
source .venv/bin/activate

# Install requirements
pip install ansible-core molecule molecule-docker

Navigate to your role’s directory and initialize a new Molecule scenario using the Docker driver:

cd my_custom_role/
molecule init scenario --driver-name docker

This creates a molecule/default/ directory containing molecule.yml and converge.yml.

Task 2 – Configuring the Scenario

Edit molecule/default/molecule.yml to define your testing platforms. For example, testing against a RHEL 9 container:

---
dependency:
  name: galaxy
driver:
  name: docker
platforms:
  - name: rhel9-test
    image: registry.access.redhat.com/ubi9/ubi-init
    command: /sbin/init
    tmpfs:
      - /run
      - /tmp
    volumes:
      - /sys/fs/cgroup:/sys/fs/cgroup:rw
    cgroupns_mode: host
    privileged: true
    pre_build_image: true
provisioner:
  name: ansible
verifier:
  name: ansible

(Note: Using ubi-init with cgroups and privileged mode allows systemd services to run inside the container, which is often necessary for Ansible role testing).

Task 3 – The Molecule Workflow

Molecule provides several commands to manage the lifecycle of your test instances:

1. Create the instance: Spins up the Docker container based on your molecule.yml.

molecule create

2. List running instances: Check the status of your test environments.

molecule list

3. Run the role (Converge): Executes converge.yml against the running container, applying your Ansible role.

molecule converge

4. Debugging: If something fails, you can drop into a shell inside the test container.

molecule login --host rhel9-test

5. Clean up: Destroys the Docker container and cleans up temporary files.

molecule destroy

Alternatively, you can run the entire test suite (linting, creating, converging, verifying, destroying) with a single command:

molecule test

Architecture Diagram

Testing Ansible Roles Locally with Molecule and Docker execution diagram

This diagram supports Testing Ansible Roles Locally with Molecule and Docker and highlights where controls, validation, and ownership boundaries sit in the workflow.

Post-Specific Engineering Lens

For this post, the primary objective is: Increase automation reliability and reduce human variance.

Implementation decisions for this case

  • Chose a staged approach centered on ansible to avoid high-blast-radius rollouts.
  • Used molecule checkpoints to make regressions observable before full rollout.
  • Treated testing documentation as part of delivery, not a post-task artifact.

Practical command path

These are representative execution checkpoints relevant to this post:

ansible-playbook site.yml --limit target --check --diff
ansible-playbook site.yml --limit target
ansible all -m ping -o

Validation Matrix

Validation goalWhat to baselineWhat confirms success
Functional stabilityservice availability, package state, SELinux/firewall posturesystemctl --failed stays empty
Operational safetyrollback ownership + change windowjournalctl -p err -b has no new regressions
Production readinessmonitoring visibility and handoff notescritical endpoint checks pass from at least two network zones

Failure Modes and Mitigations

Failure modeWhy it appears in this type of workMitigation used in this post pattern
Inventory scope errorWrong hosts receive a valid but unintended changeUse explicit host limits and pre-flight host list confirmation
Role variable driftDifferent environments behave inconsistentlyPin defaults and validate required vars in CI
Undocumented manual stepAutomation appears successful but remains incompleteMove manual steps into pre/post tasks with assertions

Recruiter-Readable Impact Summary

  • Scope: deliver Linux platform changes with controlled blast radius.
  • Execution quality: guarded by staged checks and explicit rollback triggers.
  • Outcome signal: repeatable implementation that can be handed over without hidden steps.