能否将PowerDNS服务器配置为Docker的后端DNS并实现容器IP信息自动同步?
Absolutely, you can automate syncing Docker container IPs to PowerDNS—here are a few practical, battle-tested approaches that fit your setup:
Docker emits real-time events whenever containers start, stop, or have their network settings updated. You can build a simple script to listen for these events, pull container IPs and service names, then push updates to PowerDNS via its API.
步骤:
编写监听脚本(以Python为例,利用Docker SDK和requests):
This script tracks container events for youroffice-netnetwork, extracts service names/labels and IPs, then creates/updates/deletes A records in PowerDNS.import docker import requests import time # Configure your PowerDNS details PDNS_API_URL = "http://your-pdns-server:8081/api/v1/servers/localhost/zones/domain." PDNS_API_KEY = "your-pdns-api-key-here" TARGET_NETWORK = "office-net" DOMAIN_SUFFIX = "domain" # Initialize Docker client client = docker.from_env() def update_pdns_record(hostname, ip): headers = {"X-API-Key": PDNS_API_KEY} record_name = f"{hostname}.{DOMAIN_SUFFIX}." # Check if record already exists check_url = f"{PDNS_API_URL}records/{hostname}.{DOMAIN_SUFFIX}/A" response = requests.get(check_url, headers=headers) if response.status_code == 200: # Update existing record payload = { "rrsets": [{ "name": record_name, "type": "A", "ttl": 300, "records": [{"content": ip, "disabled": False}] }] } requests.patch(PDNS_API_URL, json=payload, headers=headers) else: # Create new record payload = { "rrsets": [{ "name": record_name, "type": "A", "ttl": 300, "changetype": "REPLACE", "records": [{"content": ip, "disabled": False}] }] } requests.post(PDNS_API_URL, json=payload, headers=headers) def delete_pdns_record(hostname): headers = {"X-API-Key": PDNS_API_KEY} record_name = f"{hostname}.{DOMAIN_SUFFIX}." payload = { "rrsets": [{ "name": record_name, "type": "A", "changetype": "DELETE" }] } requests.patch(PDNS_API_URL, json=payload, headers=headers) if __name__ == "__main__": print("Listening for Docker container events...") for event in client.events(decode=True): if event["Type"] == "container": try: container = client.containers.get(event["Actor"]["ID"]) # Skip if container isn't in your target network if TARGET_NETWORK not in container.attrs["NetworkSettings"]["Networks"]: continue # Get service name (prioritize Compose service label first) service_name = container.labels.get("com.docker.compose.service") or container.name container_ip = container.attrs["NetworkSettings"]["Networks"][TARGET_NETWORK]["IPAddress"] if event["Action"] in ["start", "update"]: print(f"Updating DNS: {service_name}.{DOMAIN_SUFFIX} -> {container_ip}") update_pdns_record(service_name, container_ip) elif event["Action"] == "stop": print(f"Removing DNS record: {service_name}.{DOMAIN_SUFFIX}") delete_pdns_record(service_name) except Exception as e: print(f"Error processing event: {str(e)}") time.sleep(0.5)运行脚本:
- Install dependencies:
pip install docker requests - Run it as a systemd service or wrap it in a Docker container to ensure it runs continuously.
- Install dependencies:
External-DNS is a mature tool that automates DNS record management for containerized services. It supports PowerDNS as a backend and can listen directly to Docker events to sync records automatically.
步骤:
Deploy External-DNS as a Docker container:
Use this command to start External-DNS, configured to watch your Docker containers and sync to PowerDNS:docker run -d \ --name external-dns \ --restart=always \ --volume /var/run/docker.sock:/var/run/docker.sock \ k8s.gcr.io/external-dns/external-dns:v0.13.4 \ --provider=powerdns \ --pdns-server=http://your-pdns-server:8081 \ --pdns-api-key=your-pdns-api-key-here \ --source=docker \ --domain-filter=domain \ --policy=sync \ --log-level=infoTag your Docker Compose services:
Add labels to each service in yourdocker-compose.ymlto specify the hostname you want in PowerDNS:services: gitlab: image: gitlab/gitlab-ce networks: - office-net labels: - "external-dns.alpha.kubernetes.io/hostname=gitlab.domain" - "external-dns.alpha.kubernetes.io/ttl=300" mail: image: your-mail-image networks: - office-net labels: - "external-dns.alpha.kubernetes.io/hostname=mail.domain" - "external-dns.alpha.kubernetes.io/ttl=300"When you start these services, External-DNS will automatically create/update A records for
gitlab.domainandmail.domainwith their respective container IPs.
- PowerDNS API Setup: Make sure your PowerDNS server has its API enabled (check
api=yesinpdns.conf) and that you've set a secure API key. - TTL Configuration: Use a short TTL (like 300 seconds) so DNS caches update quickly when container IPs change.
- Network Filtering: Both approaches let you target specific networks (like
office-net) to avoid syncing containers from other networks accidentally. - Testing: After setting up, start a test container, check PowerDNS for the new A record, then stop the container to verify the record is removed or marked for deletion.
内容的提问来源于stack exchange,提问作者Eugen Konkov

