Ansible Docker: Complete Guide to Container Automation (2026)
By Luca Berton · Published 2026-04-03 · Category: installation
Complete guide to automating Docker with Ansible. Manage containers, images, networks, volumes, and docker-compose with community.docker collection.
Ansible's community.docker collection provides modules to manage Docker containers, images, networks, and Docker Compose deployments — all from your playbooks.
Prerequisites
# Install the collection
ansible-galaxy collection install community.docker
# Python requirements on managed hosts
pip install docker
See also: Ansible docker_container Module: Manage Docker Containers (Guide)
Manage Containers
Start a container
- name: Run nginx container
community.docker.docker_container:
name: webserver
image: nginx:latest
state: started
ports:
- "80:80"
- "443:443"
volumes:
- /opt/nginx/html:/usr/share/nginx/html:ro
- /opt/nginx/conf:/etc/nginx/conf.d:ro
restart_policy: unless-stopped
Container with environment variables
- name: Run PostgreSQL
community.docker.docker_container:
name: postgres
image: postgres:16
state: started
ports:
- "5432:5432"
env:
POSTGRES_PASSWORD: "{{ vault_db_password }}"
POSTGRES_DB: myapp
POSTGRES_USER: appuser
volumes:
- pgdata:/var/lib/postgresql/data
Stop and remove containers
- name: Stop container
community.docker.docker_container:
name: webserver
state: stopped
- name: Remove container
community.docker.docker_container:
name: webserver
state: absent
Manage Images
- name: Pull latest image
community.docker.docker_image:
name: nginx
tag: latest
source: pull
- name: Build image from Dockerfile
community.docker.docker_image:
name: myapp
tag: "{{ app_version }}"
build:
path: /opt/myapp
dockerfile: Dockerfile
source: build
- name: Remove old images
community.docker.docker_image:
name: myapp
tag: old-version
state: absent
See also: community.docker 5.1.0 — New Feature for Docker Compose Pull
Docker Networks
- name: Create app network
community.docker.docker_network:
name: app_network
driver: bridge
ipam_config:
- subnet: 172.20.0.0/16
- name: Run container on custom network
community.docker.docker_container:
name: myapp
image: myapp:latest
networks:
- name: app_network
ipv4_address: 172.20.0.10
Docker Volumes
- name: Create named volume
community.docker.docker_volume:
name: app_data
driver: local
- name: Use volume in container
community.docker.docker_container:
name: myapp
image: myapp:latest
volumes:
- app_data:/data
See also: Ansible Execution Environments: Build Custom EEs for Enterprise Automation
Docker Compose
- name: Deploy with Docker Compose
community.docker.docker_compose_v2:
project_src: /opt/myapp
state: present
pull: always
- name: Stop compose project
community.docker.docker_compose_v2:
project_src: /opt/myapp
state: absent
Generate docker-compose.yml with Ansible
- name: Create docker-compose.yml
ansible.builtin.copy:
content: |
version: '3.8'
services:
web:
image: nginx:latest
ports:
- "{{ http_port }}:80"
volumes:
- ./html:/usr/share/nginx/html
restart: unless-stopped
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: {{ vault_db_pass }}
volumes:
- pgdata:/var/lib/postgresql/data
restart: unless-stopped
volumes:
pgdata:
dest: /opt/myapp/docker-compose.yml
notify: restart compose
handlers:
- name: restart compose
community.docker.docker_compose_v2:
project_src: /opt/myapp
state: present
recreate: always
Install Docker with Ansible
- name: Install Docker on Ubuntu
hosts: all
become: true
tasks:
- name: Install prerequisites
ansible.builtin.apt:
name:
- ca-certificates
- curl
- gnupg
state: present
update_cache: true
- name: Add Docker GPG key
ansible.builtin.apt_key:
url: https://download.docker.com/linux/ubuntu/gpg
state: present
- name: Add Docker repository
ansible.builtin.apt_repository:
repo: "deb https://download.docker.com/linux/ubuntu {{ ansible_distribution_release }} stable"
state: present
- name: Install Docker
ansible.builtin.apt:
name:
- docker-ce
- docker-ce-cli
- containerd.io
- docker-compose-plugin
state: present
- name: Start Docker service
ansible.builtin.service:
name: docker
state: started
enabled: true
Container Health Checks
- name: Run container with health check
community.docker.docker_container:
name: myapp
image: myapp:latest
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
FAQ
Can I manage remote Docker hosts?
Yes. Set docker_host: "tcp://remote:2376" or use DOCKER_HOST environment variable. For TLS, configure tls, tls_verify, and certificate paths.
How do I update a running container?
Pull the new image, then recreate: set recreate: true or image: myapp:{{ new_version }}. The module handles stop → remove → start.
Docker Compose v1 vs v2 in Ansible?
Use community.docker.docker_compose_v2 for Docker Compose v2 (plugin). The older docker_compose module targets Compose v1 (standalone binary, deprecated).
Install Docker with Ansible
- name: Install Docker on Ubuntu
hosts: all
become: true
tasks:
- ansible.builtin.apt:
name: [docker.io, docker-compose-v2, python3-docker]
state: present
update_cache: true
- ansible.builtin.service:
name: docker
state: started
enabled: true
- ansible.builtin.user:
name: "{{ ansible_user }}"
groups: docker
append: true
Run Containers
- name: Run nginx container
community.docker.docker_container:
name: web
image: nginx:latest
state: started
ports:
- "80:80"
- "443:443"
volumes:
- /opt/website:/usr/share/nginx/html:ro
- /opt/nginx.conf:/etc/nginx/nginx.conf:ro
restart_policy: unless-stopped
env:
NGINX_HOST: example.com
Docker Compose
- name: Deploy with Docker Compose
community.docker.docker_compose_v2:
project_src: /opt/myapp
state: present
pull: always
- name: Tear down
community.docker.docker_compose_v2:
project_src: /opt/myapp
state: absent
Manage Images
# Pull image
- community.docker.docker_image:
name: python
tag: "3.12-slim"
source: pull
# Build from Dockerfile
- community.docker.docker_image:
name: myapp
tag: latest
source: build
build:
path: /opt/myapp
dockerfile: Dockerfile
# Remove old images
- community.docker.docker_prune:
images: true
images_filters:
dangling: true
Networks
- community.docker.docker_network:
name: app-network
driver: bridge
ipam_config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
- community.docker.docker_container:
name: app
image: myapp:latest
networks:
- name: app-network
ipv4_address: 172.20.0.10
Volumes
- community.docker.docker_volume:
name: db-data
driver: local
- community.docker.docker_container:
name: postgres
image: postgres:16
volumes:
- db-data:/var/lib/postgresql/data
env:
POSTGRES_PASSWORD: "{{ vault_db_pass }}"
Full Stack Example
---
- name: Deploy app stack
hosts: docker_hosts
become: true
tasks:
- community.docker.docker_network:
name: appnet
- community.docker.docker_container:
name: db
image: postgres:16
networks: [{ name: appnet }]
volumes: ["dbdata:/var/lib/postgresql/data"]
env:
POSTGRES_DB: myapp
POSTGRES_PASSWORD: "{{ vault_db_pass }}"
- community.docker.docker_container:
name: redis
image: redis:7-alpine
networks: [{ name: appnet }]
- community.docker.docker_container:
name: app
image: "myapp:{{ app_version }}"
networks: [{ name: appnet }]
ports: ["8080:8080"]
env:
DATABASE_URL: "postgresql://postgres:{{ vault_db_pass }}@db:5432/myapp"
REDIS_URL: "redis://redis:6379"
restart_policy: unless-stopped
Key Modules
| Module | Purpose |
|--------|---------|
| docker_container | Run/manage containers |
| docker_image | Pull/build images |
| docker_compose_v2 | Docker Compose |
| docker_network | Networks |
| docker_volume | Volumes |
| docker_prune | Cleanup |
| docker_login | Registry auth |
FAQ
Do I need Python Docker SDK?
Yes — install python3-docker on managed hosts. Or: pip install docker
How do I update a running container?
Set pull: true and recreate: true (or use comparisons for smart recreation):
- community.docker.docker_container:
name: app
image: myapp:latest
pull: true
recreate: true
Ansible vs Docker Compose directly?
Ansible adds inventory management, secrets (Vault), multi-host orchestration, and integration with non-Docker infrastructure. Use Ansible when Docker is part of a larger automation workflow.
Install Collection
ansible-galaxy collection install community.docker
Run a Container
- community.docker.docker_container:
name: nginx
image: nginx:latest
state: started
ports:
- "80:80"
- "443:443"
volumes:
- /opt/nginx/html:/usr/share/nginx/html:ro
- /opt/nginx/conf:/etc/nginx/conf.d:ro
become: true
Container with Environment Variables
- docker_container:
name: myapp
image: myorg/myapp:{{ version }}
state: started
env:
DB_HOST: "db.internal"
DB_PORT: "5432"
REDIS_URL: "redis://cache:6379"
APP_ENV: "production"
restart_policy: unless-stopped
Docker Compose
- community.docker.docker_compose_v2:
project_src: /opt/myapp
state: present
register: output
# Or pull and recreate
- docker_compose_v2:
project_src: /opt/myapp
state: present
pull: always
recreate: smart
Manage Images
# Pull image
- community.docker.docker_image:
name: nginx
tag: "1.25"
source: pull
# Build image
- docker_image:
name: myorg/myapp
tag: "{{ version }}"
source: build
build:
path: /opt/myapp
dockerfile: Dockerfile
Manage Networks
- community.docker.docker_network:
name: myapp_network
driver: bridge
ipam_config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1
- docker_container:
name: myapp
image: myorg/myapp
networks:
- name: myapp_network
ipv4_address: 172.20.0.10
Manage Volumes
- community.docker.docker_volume:
name: myapp_data
- docker_container:
name: postgres
image: postgres:16
volumes:
- myapp_data:/var/lib/postgresql/data
env:
POSTGRES_PASSWORD: "{{ vault_db_password }}"
Container Health Check
- docker_container:
name: myapp
image: myorg/myapp
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 30s
Full Stack Example
- name: Deploy application stack
hosts: docker_hosts
become: true
vars:
app_version: "2.5.0"
tasks:
- docker_network:
name: app_net
- docker_container:
name: postgres
image: postgres:16
networks: [{ name: app_net }]
volumes: [pgdata:/var/lib/postgresql/data]
env:
POSTGRES_PASSWORD: "{{ vault_db_pass }}"
- docker_container:
name: redis
image: redis:7-alpine
networks: [{ name: app_net }]
- docker_container:
name: webapp
image: "myorg/webapp:{{ app_version }}"
networks: [{ name: app_net }]
ports: ["80:8080"]
env:
DATABASE_URL: "postgresql://postgres:{{ vault_db_pass }}@postgres/app"
REDIS_URL: "redis://redis:6379"
restart_policy: unless-stopped
Cleanup
# Remove stopped containers
- docker_container:
name: old-app
state: absent
# Prune unused images
- community.docker.docker_prune:
images: true
containers: true
volumes: false # Be careful with data volumes
FAQ
docker_container vs docker_compose?
docker_container manages individual containers. docker_compose_v2 manages multi-container stacks from docker-compose.yml. Use compose for complex stacks.
Do I need Docker installed first?
Yes — install Docker on the target host first. Use geerlingguy.docker role or install manually.
How to handle secrets?
Use Ansible Vault for environment variables. Never put secrets in Dockerfiles or images.
Install Collection
ansible-galaxy collection install community.docker
pip install docker # Python SDK required
Run a Container
- community.docker.docker_container:
name: nginx
image: nginx:latest
state: started
ports:
- "80:80"
- "443:443"
restart_policy: unless-stopped
Container with Volumes
- docker_container:
name: myapp
image: myorg/myapp:v2
volumes:
- /opt/data:/app/data
- /opt/config:/app/config:ro
env:
DATABASE_URL: "postgresql://db:5432/myapp"
APP_SECRET: "{{ vault_app_secret }}"
Pull Image
- community.docker.docker_image:
name: myorg/myapp
tag: "{{ app_version }}"
source: pull
Build Image
- docker_image:
name: myorg/myapp
tag: "{{ app_version }}"
source: build
build:
path: /opt/myapp
dockerfile: Dockerfile
Docker Network
- community.docker.docker_network:
name: app_network
driver: bridge
- docker_container:
name: myapp
image: myorg/myapp:latest
networks:
- name: app_network
Docker Volume
- community.docker.docker_volume:
name: db_data
state: present
- docker_container:
name: postgres
image: postgres:16
volumes:
- db_data:/var/lib/postgresql/data
env:
POSTGRES_PASSWORD: "{{ vault_db_pass }}"
Docker Compose
- community.docker.docker_compose_v2:
project_src: /opt/myapp
state: present
register: output
Cleanup
# Remove stopped containers
- docker_container:
name: old-app
state: absent
# Prune unused images
- community.docker.docker_prune:
images: true
images_filters:
dangling: true
Full Stack Deployment
- hosts: docker_hosts
become: true
tasks:
- docker_network:
name: mystack
- docker_container:
name: db
image: postgres:16
networks: [{ name: mystack }]
volumes: [db_data:/var/lib/postgresql/data]
env: { POSTGRES_PASSWORD: "{{ vault_db_pass }}" }
- docker_container:
name: app
image: "myorg/myapp:{{ app_version }}"
networks: [{ name: mystack }]
ports: ["8080:8080"]
env: { DATABASE_URL: "postgresql://db:5432/myapp" }
FAQ
community.docker vs docker module?
community.docker is the current maintained collection. The old docker_container short name resolves to it via ansible.legacy.
How to install Docker itself?
Use geerlingguy.docker role: ansible-galaxy install geerlingguy.docker.
Docker vs Podman?
Use containers.podman collection for Podman. API is similar but modules differ.
Related Articles
• using Ansible Galaxy for collections • task-scoped environment variables in Ansible • idempotent restarts via Ansible handlers • Ansible Vault CLI reference • Ansible become methods comparedCategory: installation