We created experimental Docker image which tries to ensure high availability for your web service by dynamically refreshing Cloudflare DNS with healthy endpoints.

How it works?

Current implementation is really simple:

  • Worker process periodically checks your web service endpoints. It checks health for every IP address provided in input variable IPAddresses (see below for docker compose example).
  • Terraform file is created with DNS entries for all healthy IP endpoints (your service is considered healthy if it returns HTTP status code 2xx)
  • Terraform file is applied with
    • terraform apply --auto-approve if ApplyAndAutoApprove variable is set to true
    • or terraform plan otherwise (doesn’t change your Cloudflare configuration - can be used for testing)
  • Worker process then pauses for some time (controlled by input variable Frequency) and entire process repeats again.

Used technology

All source code is freely available on GitHub: AppBeat/AppBeat.DnsUtil.

Docker Compose example

Below is example for example.com where A records for test-subdomain are pointing to YOUR_WEB_SERVER_IP_1 and YOUR_WEB_SERVER_IP_2 (you would of course replace this with your actual domain and IP addresses).

As you can see, all configuration is provided via environment variables. You must also provide Cloudflare API Token with Zone.DNS edit permission and Zone ID.

version: "3.9"
services:
  healthy-dns-util:
    image: appbeat/healthy-dns-util:latest
    container_name: appbeat-healthy-dns-util
    restart: "no" #should be checked if something goes wrong

    environment:
      - DnsUtil_RunAsService="true" #periodic or one time job
      - DnsUtil_Frequency="1m" #how frequently do we run Terraform. Unit examples: 30s, 1m, 1h

      - DnsUtil_Terraform__ApplyAndAutoApprove="true" #if not set then defaults to false which will run plan only

      - DnsUtil_Cloudflare__ApiToken="YOUR_API_TOKEN" #Cloudlare specific global setting

      - DnsUtil_DNS[0]__Provider="Cloudflare" #currently only Cloudflare is supported
      - DnsUtil_DNS[0]__Domain="example.com"
      - DnsUtil_DNS[0]__Subdomain="test-subdomain"
      - DnsUtil_DNS[0]__IPAddresses="YOUR_WEB_SERVER_IP_1, YOUR_WEB_SERVER_IP_2" #A or AAAA destination addresses
      - DnsUtil_DNS[0]__HealthCheckServiceProtocol="https" #when checking destination addresses for HTTP status 2xx, should we use https or http
      - DnsUtil_DNS[0]__HealthCheckTimeoutSeconds="15" #how much do we wait for check
      - DnsUtil_DNS[0]__HealthCheckRetriesOnFailure="2" #if destination check fails with unhandled exception, should we retry it?
      - DnsUtil_DNS[0]__HealthCheckIgnoreSslIssues="true" #should we ignore SSL issues when checking destinations?
      - DnsUtil_DNS[0]__DnsProxied="true" #Cloudlare specific DNS setting
      - DnsUtil_DNS[0]__ZoneId="YOUR_ZONE_ID" #Cloudlare specific DNS setting

Hopefully this will be useful to you.