Skip to content

0xnoid/DockerResolve

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DockerResolve: Minimalistic DNS for Docker


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 overview
  • GET /containers/{id}/json: Specific container information
  • GET /networks: Network overiew
  • GET /networks/{id}: Specific networks Inn essence, the workflow is very simple.
    Intialization:
  1. Get all containers
  2. Filter blacklisted containers
  3. Cache all IPs
  4. Deliver

Once initialized:

  1. 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.
  2. Upon changes, the Container information is replaced
  3. 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
  4. Return is given It's important to note that:
  5. The optins you're running with will impact resolvability
  6. 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.

Configuration

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.sock

For this configuration, you may pick any. The only requirements are:

  • An IP (so the DNS can receive contact)
  • /var/run/docker.sock for using the Docker API. To see the exact details expand the Environment Options:
Environment Options
  • CACHE_TIME Cache 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_LEVEL Logging level, where 0 is disabled, 1 is base, 2 is default. For the full amount select 5.
  • PREFIX: Prefix for DNS. For example, docker would mean the DNS resolution will be docker.nginx instead of nginx
  • POSTFIX: Same as PREFIX but in the opposite style: nginx.docker
  • OUTPUT_DIR: Hosts file output directory
  • CUSTOM_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 as 127.0.0.1 instead of overwriting the existing one.
  • BLACKLIST_CONTAINERS: The blacklist. Items you don't want the DNS to monitor or resolve. For example, if nginx is running NETWORK_MODE: HOST there's no reason to resolve it or monitor it. adding nginx would 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 resolve nginx when the container name is nginx-web allows this to do so.
  • DNS_PORT: The port. Optional, I suppose.
  • Volumes: /var/run/docker.sock is required. If you want to use hosts file I also suggest passing the /DockerResolve folder, 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/24

Other

Security

The 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.

About

Resolve container IPs on host/host-mode networks

Topics

Resources

License

Stars

Watchers

Forks