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 dockerSee 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-stoppedContainer 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/dataStop and remove containers
- name: Stop container
community.docker.docker_container:
name: webserver
state: stopped
- name: Remove container
community.docker.docker_container:
name: webserver
state: absentManage 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: absentSee 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.10Docker 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:/dataSee 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: absentGenerate 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: alwaysInstall 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: trueContainer 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: 40sFAQ
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: trueRun 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.comDocker 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: absentManage 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: trueNetworks
- 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.10Volumes
- 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-stoppedKey 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: trueAnsible 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.dockerRun 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: trueContainer 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-stoppedDocker 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: smartManage 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: DockerfileManage 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.10Manage 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: 30sFull 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-stoppedCleanup
# 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 volumesFAQ
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 requiredRun a Container
- community.docker.docker_container:
name: nginx
image: nginx:latest
state: started
ports:
- "80:80"
- "443:443"
restart_policy: unless-stoppedContainer 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: pullBuild Image
- docker_image:
name: myorg/myapp
tag: "{{ app_version }}"
source: build
build:
path: /opt/myapp
dockerfile: DockerfileDocker Network
- community.docker.docker_network:
name: app_network
driver: bridge
- docker_container:
name: myapp
image: myorg/myapp:latest
networks:
- name: app_networkDocker 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: outputCleanup
# Remove stopped containers
- docker_container:
name: old-app
state: absent
# Prune unused images
- community.docker.docker_prune:
images: true
images_filters:
dangling: trueFull 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
Category: installation