There’s a point in most DevOps pipelines where things start to feel repetitive—building Docker images, tagging them, pushing to DockerHub, and deploying them somewhere. It works, but it’s manual or glued together with scripts that nobody wants to touch.
This is exactly where Ansible fits surprisingly well. While it’s often associated with server provisioning, it can orchestrate container workflows just as effectively—including interactions with DockerHub.
Why combine Ansible and DockerHub?
DockerHub is your image registry. Ansible is your automation engine. When you connect the two, you get:
- Consistent image builds across environments
- Automated tagging and versioning
- Secure credential handling
- Repeatable deployments without brittle scripts
Instead of stitching together shell scripts, you define everything declaratively.
A quick example: building and pushing an image
Let’s start with a minimal playbook that builds a Docker image and pushes it to DockerHub.
1- name: Build and push Docker image
2 hosts: localhost
3 vars:
4 image_name: myapp
5 image_tag: latest
6 dockerhub_username: "{{ lookup('env', 'DOCKER_USERNAME') }}"
7 dockerhub_password: "{{ lookup('env', 'DOCKER_PASSWORD') }}"
8
9 tasks:
10 - name: Log in to DockerHub
11 community.docker.docker_login:
12 username: "{{ dockerhub_username }}"
13 password: "{{ dockerhub_password }}"
14
15 - name: Build Docker image
16 community.docker.docker_image:
17 name: "{{ dockerhub_username }}/{{ image_name }}"
18 tag: "{{ image_tag }}"
19 build:
20 path: ./app
21
22 - name: Push image to DockerHub
23 community.docker.docker_image:
24 name: "{{ dockerhub_username }}/{{ image_name }}"
25 tag: "{{ image_tag }}"
26 push: yes
27That’s already cleaner than most bash scripts—and easier to maintain.
Handling versioning without chaos
A common mistake developers make is hardcoding latest everywhere. That works until it doesn’t.
With Ansible, you can generate dynamic tags:
1vars:
2 image_tag: "{{ lookup('pipe', 'git rev-parse --short HEAD') }}"
3Now every build is tied to a commit. You can still optionally tag latest in a separate step.
Tagging multiple versions
1- name: Tag image as latest
2 community.docker.docker_image:
3 name: "{{ dockerhub_username }}/{{ image_name }}"
4 tag: latest
5 source: local
6This keeps your pipeline predictable and traceable.
Where credentials usually go wrong
Hardcoding DockerHub credentials in playbooks is a bad idea. Instead:
- Use environment variables
- Or Ansible Vault for encrypted storage
Example with Vault:
1ansible-vault encrypt_string 'mypassword' --name 'dockerhub_password'Then reference it safely in your playbook.
Deploying containers after push
Here’s where things get interesting. You can extend the same playbook to deploy the freshly pushed image to a server.
1- name: Deploy container
2 hosts: web_servers
3 tasks:
4 - name: Pull latest image
5 community.docker.docker_container:
6 name: myapp
7 image: "{{ dockerhub_username }}/{{ image_name }}:{{ image_tag }}"
8 state: started
9 restart_policy: always
10 ports:
11 - "80:3000"
12No separate deployment tool required. Ansible handles the full lifecycle.
Using Ansible in CI/CD pipelines
Most teams don’t run Ansible manually—they integrate it into CI/CD tools like GitHub Actions, GitLab CI, or Jenkins.
A simple GitHub Actions step might look like:
1- name: Run Ansible playbook
2 run: ansible-playbook deploy.yml
3 env:
4 DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
5 DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
6This turns your Ansible playbook into a reusable deployment engine.
Performance and practical considerations
While Ansible is powerful, it’s not always the fastest tool for heavy image builds. A few practical tips:
- Use Docker layer caching when possible
- Keep build contexts small
- Avoid rebuilding unchanged images
- Consider delegating builds to CI runners
Ansible shines most in orchestration—not raw build speed.
When this approach works best
This setup is especially useful when:
- You already use Ansible for infrastructure
- You want fewer tools in your pipeline
- You need consistent workflows across environments
It might not be ideal if you're deeply invested in specialized container tools like Kubernetes-native pipelines or advanced CI build systems.
A small but important detail
The community.docker collection is required for these modules:
1ansible-galaxy collection install community.dockerWithout it, your playbooks won’t run.
Wrapping it up
Ansible and DockerHub together create a clean, declarative workflow for building, tagging, and deploying container images. Instead of juggling scripts and tools, you define everything in one place and run it consistently across environments.
It’s not about replacing your entire CI/CD stack—but simplifying the parts that tend to become messy over time.