Deploy BIND DNS server using Docker containers orchestrated by Ansible. This guide provides playbooks for automated deployment of production-ready BIND instances with proper security hardening.
ansible-galaxy collection install community.docker community.general
| Item | Details |
|---|---|
| Official Image | internetsystemsconsortium/bind9 |
| Current Stable | 9.20 tag (BIND 9.20.20) |
| ESV/LTS | 9.18 tag (BIND 9.18.46) |
| Base OS | Alpine Linux |
| User | UID 53 (bind user) |
| Ports | 53/UDP, 53/TCP (DNS), 953/TCP (RNDC) |
Always use specific version tags instead of latest for production deployments.
Create bind-docker-install.yml:
---
- name: Deploy BIND with Docker
hosts: bind_servers
become: true
gather_facts: true
vars:
bind_version: "9.20.20"
bind_image: "internetsystemsconsortium/bind9:{{ bind_version }}"
bind_container_name: "bind9"
bind_config_dir: "/opt/bind/config"
bind_data_dir: "/opt/bind/data"
bind_logs_dir: "/opt/bind/logs"
bind_network_name: "bind-net"
tasks:
- name: Install Docker dependencies
package:
name:
- docker
- docker-compose-plugin
state: present
- name: Ensure Docker service is running
systemd:
name: docker
state: started
enabled: true
- name: Create BIND directories
file:
path: "{{ item }}"
state: directory
mode: '0755'
loop:
- "{{ bind_config_dir }}"
- "{{ bind_data_dir }}"
- "{{ bind_logs_dir }}"
- name: Create Docker network
community.docker.docker_network:
name: "{{ bind_network_name }}"
driver: bridge
- name: Deploy Docker Compose file
copy:
dest: "{{ bind_config_dir }}/docker-compose.yml"
mode: '0644'
content: |
version: '3.8'
services:
bind:
image: {{ bind_image }}
container_name: {{ bind_container_name }}
restart: unless-stopped
ports:
- "53:53/udp"
- "53:53/tcp"
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
read_only: true
tmpfs:
- /tmp
- /var/run
user: "53:53"
security_opt:
- no-new-privileges:true
volumes:
- {{ bind_config_dir }}/named.conf:/etc/bind/named.conf:ro
- {{ bind_data_dir }}:/var/lib/bind
- {{ bind_logs_dir }}:/var/log/named
networks:
- {{ bind_network_name }}
healthcheck:
test: ["CMD", "dig", "@127.0.0.1", "example.com"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
networks:
{{ bind_network_name }}:
external: true
- name: Deploy BIND configuration
template:
src: named.conf.j2
dest: "{{ bind_config_dir }}/named.conf"
mode: '0644'
notify: Restart BIND
- name: Start BIND container
community.docker.docker_compose_v2:
project_src: "{{ bind_config_dir }}"
state: present
- name: Verify BIND is running
command: dig @127.0.0.1 google.com +short
register: dig_result
retries: 5
delay: 3
until: dig_result.rc == 0
changed_when: false
handlers:
- name: Restart BIND
community.docker.docker_compose_v2:
project_src: "{{ bind_config_dir }}"
state: present
restarted: true
# Test run
ansible-playbook -i inventory.ini site.yml --check
# Run the playbook
ansible-playbook -i inventory.ini site.yml
# Verify deployment
docker ps | grep bind9
dig @127.0.0.1 google.com
latestBeyond this playbook, we offer:
Contact our automation team: office@linux-server-admin.com | Contact Page