What is DockerResolve?
DockerResolve is a an extremely lightweight, minimalistic and low-configuration DNS server for Docker containers. Allowing DNS resolution on Host for Docker Containers.
Why?
Because there are often situations where you may require to resolve containers by container name/hostname rather than IP. This can be extremely tedious to do.
Let's use an example:
You have an NGINX container that requires NETWORK_MODE: HOST, or, simply, an NGINX server running as a package on your server. While this NGINX server can freely communicate with the containers utilizing the Docker network/s - the internal Docker DNS does not allow DNS queries from anything that isn't directly attached to the specific network.
In this scenario, that means our NGINX that's host network attached. Which makes it more tedious, because while we CAN contact our internal Docker DNS at 127.0.0.11 you won't get a response.
However, when we use DockerResolve, we can now set up this container which hooks straight into the Docker API and creates it's own DNS microservice. Now, we can simply set resolver {container_ip} valid=30s; and suddenly we have functioning Docker DNS, allowing us to use important configurations such as $upstream_app myapp for our proxy_pass.
How does it work?
DockerResolve works by attaching straight to the Docker API. Due to this, it's a deliberate choice to make it as nitpicky and limited as possible as not to pose other risks.
We grab the information by using a standard series of commands integrated. These can be narrowed down to, essentially:
GET /containers/json: Container overviewGET /containers/{id}/json: Specific container informationGET /networks: Network overiewGET /networks/{id}: Specific networks Inn essence, the workflow is very simple.
Intialization:
- Get all containers
- Filter blacklisted containers
- Cache all IPs
- Deliver
Once initialized:
- Monitor Docker Events for two things: Network changes / Container state changes. This allows two things: Detect when a container is deleted / restarted / started / created, which can all change the ID, IP or name. It's then matched with the network changes; disconnect, connect.
- Upon changes, the Container information is replaced
- When a request for a container name is made to the DNS, it's matched towards the corresponding IP, just as Docker's internal DNS would function
- Return is given It's important to note that:
- The optins you're running with will impact resolvability
- IPv6 and IPv4 is a delibarete choice you'll have to make in your networks
The DNS will often refuse IPv6 requests if the containers are IPv4.
Because of this, amongst other things, it is HIGHLY recommended to use IPv4 only, and for any queries for containers that these requests are made in IPv4 only. As the response will be a failure.
This solution is made with simplicity first. There are therefore a few recommendations:
- Create a specific network for DockerResolve
- Assign a static IP Certain other parts are optional, you'll find all the options for the container below:
services:
dockerresolve:
image: dockerresolvedns:latest
container_name: dockerresolve-dns
environment:
- CACHE_TIME=10m
- LOG_LEVEL=2
- PREFIX=
- POSTFIX=
- OUTPUT_DIR=/DockerResolve
- CUSTOM_HOSTS=
- BLACKLIST_CONTAINERS=dockerresolve-dns
- NAME_INTELLIMATCH=false
- DNS_PORT=53
volumes:
- /var/run/docker.sock:/var/run/docker.sockFor this configuration, you may pick any. The only requirements are:
- An IP (so the DNS can receive contact)
/var/run/docker.sockfor using the Docker API. To see the exact details expand theEnvironment Options:
Environment Options
CACHE_TIMECache time for DNS. Coincidentally, this also allows you to choose resource use as the list of Container items grow, as it also specifies our lifetime of the Docker system events.LOG_LEVELLogging level, where 0 is disabled, 1 is base, 2 is default. For the full amount select 5.PREFIX: Prefix for DNS. For example,dockerwould mean the DNS resolution will bedocker.nginxinstead ofnginxPOSTFIX: Same asPREFIXbut in the opposite style:nginx.dockerOUTPUT_DIR: Hosts file output directoryCUSTOM_HOSTS: Internal hosts, only really used for hosts file. For example, if you're using the hosts file and want to keep the original hosts file items such as127.0.0.1instead of overwriting the existing one.BLACKLIST_CONTAINERS: The blacklist. Items you don't want the DNS to monitor or resolve. For example, ifnginxis runningNETWORK_MODE: HOSTthere's no reason to resolve it or monitor it. addingnginxwould stop this.NAME_INTELLIMATCH: Easier name matching with a bit of leeway. Allows you to not use full name of the container. For example; Trying to resolvenginxwhen the container name isnginx-weballows this to do so.DNS_PORT: The port. Optional, I suppose.- Volumes:
/var/run/docker.sockis required. If you want to use hosts file I also suggest passing the/DockerResolvefolder, where you'll find this file.
For an optimal Docker Compose, assign a network and IP:
services:
dockerresolve:
image: dockerresolvedns:latest
container_name: dockerresolve-dns
environment:
- CACHE_TIME=10m
- LOG_LEVEL=2
- OUTPUT_DIR=/DockerResolve
- BLACKLIST_CONTAINERS=dockerresolve-dns
- NAME_INTELLIMATCH=false
- DNS_PORT=53
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./DockerResolveDNS:/DockerResolve
restart: unless-stopped
networks:
dockerresolvedns:
ipv4_address: 10.99.99.5
networks:
dockerresolvedns:
name: dockerresolvedns
internal: true
driver: bridge
driver_opts:
com.docker.network.bridge.name: dckr_resolvdns
ipam:
config:
- subnet: 10.99.99.0/24The biggest concern is that the DockerResolveDNS will, inherently, only work with the Docker API and internal services (on the same machine, within host) that are able to use localhost. Therefore, you should not for any reason, open any ports, as it does not need it anyway.
There are few other concerns due to the nature of the server.