Home > Software design >  How to set bind9 docker container as dns of other container
How to set bind9 docker container as dns of other container

Time:08-04

I'm trying to set up ssl for my home network and I've set up a bind9 container with a custom domain that points to my unraid server. So far so good. I've also set up a private step-ca certificate authority which needs it's dns set to the bind9 container so that it knows about my private domain. The setup works if I set the dns of the step container to the internal docker ip address of the bind container but since these ip addresses are ephemeral I can't rely on that hence why I'm binding the bind9 ip address to something within 192.168.0.1/24 and accessing it there. This works if I set the dns server of my pc to the bind9 container but I am unable to do so for other docker containers for some reason

in short, step-ca and my proxy traefik need their dns set to bind9 which I want to have set up with a static ip address on the 192.168.0.1/24 subnet. traefik also needs to be able to talk to containers on the bridge network br0 otherwise it won't be able to proxy requests to the containers

CodePudding user response:

The addresses of your containers don't need to be ephemeral. We can set up a custom network using the networks top-level element that defines a static range for the network using the ipam option, and then we can assign our containers static address on this network.

We can use the dns option to configure containers to use the bind9 container for name resolution.

Here's an example docker-compose.yaml that sets up a bind9 container and a couple of additional containers that will use it for DNS:

version: "3"

services:
  bind9:
    image: docker.io/internetsystemsconsortium/bind9:9.19
    volumes:
      - "./bind:/etc/bind"
      - bind9_cache:/var/cache/bind
      - bind9_log:/var/log
      - bind9_lib:/var/lib/bind
    networks:
      bind9:
        ipv4_address: 192.168.133.10

  web1:
    image: docker.io/alpinelinux/darkhttpd:latest
    networks:
      bind9:
        ipv4_address: 192.168.133.20
    dns: 192.168.133.10

  web2:
    image: docker.io/alpinelinux/darkhttpd:latest
    networks:
      bind9:
        ipv4_address: 192.168.133.21
    dns: 192.168.133.10

networks:
  bind9:
    ipam:
      driver: default
      config:
        - subnet: 192.168.133.0/24
          gateway: 192.168.133.1

volumes:
  bind9_cache:
  bind9_lib:
  bind9_log:

In in the bind directory, I have bind configured to serve the following zonefile:

$TTL    604800
@   IN  SOA docker.example. root.docker.example. (
                  2     ; Serial
             604800     ; Refresh
              86400     ; Retry
            2419200     ; Expire
             604800 )   ; Negative Cache TTL
;
@   IN  NS  ns.docker.example.
ns  IN  A   192.168.133.10
web1    IN  A   192.168.133.20
web2    IN  A   192.168.133.21
web IN  A   192.168.133.20
web IN  A   192.168.133.21

From either the web1 or web2 containers, we can confirm that they are using our bind instance for name resolution:

/ $ wget -O- web1.docker.example:8080
Connecting to web1.docker.example:8080 (192.168.133.20:8080)
writing to stdout
<html>
.
.
.
</html>

Recall that docker-compose is just a fancy wrapper for docker run, so you can accomplish the same thing without using docker-compose (although it will of course make life much easier).


If you need to access the bind9 container, you would of course just publish the appropriate ports on your host by adding the necessary ports section to the compose configuration (or by using the --publish/-p option on the docker run command line):

  bind9:
    image: docker.io/internetsystemsconsortium/bind9:9.19
    ports:
      - "53:53/udp"
      - "53:53/tcp"
    volumes:
      - "./bind:/etc/bind"
      - bind9_cache:/var/cache/bind
      - bind9_log:/var/log
      - bind9_lib:/var/lib/bind
    networks:
      bind9:
        ipv4_address: 192.168.133.10
  • Related