Most teams reach a point where running docker build and docker run manually just doesn’t scale anymore. That’s usually when Ansible enters the conversation—not just for provisioning servers, but for orchestrating container workflows as well.
Let’s walk through how to build and run a container using Ansible in a way that’s reproducible, readable, and actually useful in real environments.
Why use Ansible for containers?
It might feel like Docker already solves everything, so why add Ansible?
- You want repeatable infrastructure and container deployment
- You need to coordinate across multiple hosts
- You prefer declarative automation over shell scripts
- You want everything version-controlled in playbooks
Here’s where things get interesting: Ansible doesn’t replace Docker—it orchestrates it.
Prerequisites (quick but important)
- Ansible installed on your control node
- Docker installed on target hosts
- Python Docker SDK (docker Python package)
If the Docker SDK is missing, many Ansible Docker modules will fail silently or behave oddly.
Start with a simple Dockerfile
Before Ansible does anything, you need something to build. A minimal example:
FROM node:18-alpine
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "server.js"]
Keep it in your project directory. Ansible will reference this path when building the image.
Building a Docker image with Ansible
Instead of calling docker build, you use the community.docker.docker_image module.
1- name: Build Docker image
2 hosts: app_servers
3 become: true
4 tasks:
5 - name: Build image from Dockerfile
6 community.docker.docker_image:
7 name: my-node-app
8 tag: latest
9 build:
10 path: /opt/my-app
11This does a few important things:
- Ensures idempotency (won’t rebuild unnecessarily)
- Tracks image state declaratively
- Works cleanly across environments
A subtle but important detail
A common mistake developers make is assuming Ansible will automatically detect changes in the Dockerfile. It doesn’t always behave like a local Docker cache.
If you need stricter rebuild behavior, you can add:
1force_source: trueRunning a container with Ansible
Once the image is built, running it is handled by another module:
1- name: Run container
2 community.docker.docker_container:
3 name: my-node-container
4 image: my-node-app:latest
5 state: started
6 ports:
7 - "3000:3000"
8 restart_policy: always
9This replaces your usual docker run command—but with state awareness.
What this gives you
- If the container isn’t running → it starts
- If it’s already running → nothing happens
- If config changes → container is recreated
That last point is where Ansible shines compared to raw Docker CLI usage.
Putting it together: a full playbook
Here’s a minimal but realistic playbook combining both steps:
1- name: Build and run container with Ansible
2 hosts: app_servers
3 become: true
4
5 tasks:
6 - name: Build Docker image
7 community.docker.docker_image:
8 name: my-node-app
9 tag: latest
10 build:
11 path: /opt/my-app
12
13 - name: Run application container
14 community.docker.docker_container:
15 name: my-node-container
16 image: my-node-app:latest
17 state: started
18 ports:
19 - "3000:3000"
20 env:
21 NODE_ENV: production
22 restart_policy: unless-stopped
23This playbook is now your single source of truth for both building and running the container.
Where things can go wrong
Let’s not pretend this is always smooth. A few real-world issues:
- Missing Docker SDK: Causes module failures
- Path issues: Wrong build context breaks image builds
- Port conflicts: Existing containers may block ports
- Image caching confusion: Changes not reflected without forcing rebuild
Debugging tip: run playbooks with -vvv for verbose output—it helps more than most people expect.
When to use this approach
This pattern works especially well when:
- You deploy to VMs or bare metal
- You’re not using Kubernetes
- You want simple, controlled container automation
- You need to manage both infra and app in one tool
If you're deep into Kubernetes already, Ansible might still help—but mostly for cluster setup rather than container lifecycle.
A quick comparison: CLI vs Ansible
| Task | Docker CLI | Ansible |
|---|---|---|
| Build image | docker build | docker_image module |
| Run container | docker run | docker_container module |
| Idempotency | No | Yes |
| Multi-host automation | Manual | Built-in |
Final thoughts
Using Ansible to build and run containers isn’t about replacing Docker—it’s about making your workflows predictable and scalable.
Once you move this logic into playbooks, you stop thinking in terms of commands and start thinking in terms of desired state. That shift alone tends to clean up a lot of operational chaos.
If you're already using Ansible for provisioning, extending it to container management is a natural next step—and usually a worthwhile one.