Skip to content
Snippets Groups Projects
Select Git revision
  • d9f35e03457bfe2b6226c60a2342dfb4c6843a53
  • master default protected
  • feature/ipv6
  • systemd-resolved-docker-1.0.0-1
  • systemd-resolved-docker-0.4.0-1
  • systemd-resolved-docker-0.1.1-1
  • python-systemd-resolved-docker-0.1.0-1
7 results

systemd-resolved-docker

  • Clone with SSH
  • Clone with HTTPS
  • user avatar
    Zsombor Welker authored
    Created by command:
    
    /usr/bin/tito tag --use-version 0.5.0 --offline
    d9f35e03
    History

    systemd-resolved-docker

    Provides systemd-resolved and docker DNS integration.

    1. A DNS server is configured to listen on the docker interface's IP address. This is used to expose the systemd-resolved DNS service (127.0.0.53) to docker containers by proxying DNS requests, which doesn't work by default due to the differing network namespaces.

    2. Allows containers to be referenced by hostname by adding a DNS servers to a dummy interface using the systemd-resolved D-Bus API.

    Features

    Container domain addresses

    Based on the container's properties multiple domain names may be generated. For this the default_domain (DEFAULT_DOMAIN) and allowed domains (ALLOWED_DOMAINS) options are used. The list of allowed domains specifies which domains may be handled. An entry starting with . (example: .docker) allows all matching subdomains, otherwise an exact match is required. If a generated domain address doesn't match the list of allowed domains, then the default_domain is appended.

    1. <container_id>.<default_domain>

      All containers will be reachable by their container_id:

      docker run --rm -it alpine                                        #  d6d51528ac46.docker
      docker ps
      CONTAINER ID        IMAGE                     COMMAND                  CREATED             STATUS              PORTS                    NAMES
      d6d51528ac46        alpine                    "/bin/sh"                8 seconds ago       Up 6 seconds                                 relaxed_cartwright
    2. <container_hostname>.<default_domain>, <container_hostname>.<container_domain>.<default_domain>, <container_hostname>.<container_domain>

      If an explicit --hostname is provided then that may also be used:

      docker run --rm -it --hostname test      alpine                   # test.docker

      Glob matching is supported in the --hostname, with which wildcard domains are supported:

      docker run --hostname '*.test' --rm -it alpine                    # anything.test

      If an explicit --domainname is provided then that may also be used:

      docker run --rm -it --hostname test --domainname mydomain alpine  # test.mydomain.docker

      When the domain name is in the list of allowed domains (ALLOWED_DOMAINS=.docker,.local), then the default_domain will not be appended:

      docker run --rm -it --hostname test --domainname local    alpine  # test.local
    3. <container_name>.<container_network>.<default_domain>, <container_name>.<container_network>

      If a non-default network is used (not bridge or host) then a name will be generated based on the network's name:

      docker run --rm -it           --network testnet alpine            # zealous_jones.testnet.docker
      docker run --rm -it --name db --network testnet alpine            # db.testnet.docker

      When the network's name is in the list of allowed domains (ALLOWED_DOMAINS=.docker,.somenet), then the default_domain will not be appended:

      docker run --rm -it           --network somenet alpine            # zealous_jones.somenet
      docker run --rm -it --name db --network somenet alpine            # db.somenet.docker
    4. <service>.<project>.<default_domain>, <service>.<project>, <container_number>.<service>.<project>.<default_domain>, <container_number>.<service>.<project>

      If docker-compose is used then names will be generated based on the service and project names. If a service has multiple containers then the reply will contain all instances:

      host   webserver.someproject.docker                        #   webserver.someproject.docker has address 172.16.238.3
                                                                 #   webserver.someproject.docker has address 172.16.238.4
      host 1.webserver.someproject.docker                        # 1.webserver.someproject.docker has address 172.16.238.3

      When the project's name is in the list of allowed domains (ALLOWED_DOMAINS=.docker,.someproject), then the default_domain will not be appended:

    If configured correctly then resolvectl status should show the configured link-specific DNS server:

    $ resolvectl status
    ...
    Link 7 (srd-dummy)
    Current Scopes: DNS LLMNR/IPv4 LLMNR/IPv6
         Protocols: -DefaultRoute +LLMNR -mDNS -DNSOverTLS DNSSEC=no/unsupported
       DNS Servers: 127.0.0.153
        DNS Domain: ~docker
    ... 

    A dummy interface (srd-dummy by default) is created to add the custom DNS server to systemd-resolved. This is required because the lifecycle of the docker0 depends on there being running containers on the default network, even if there are running containers on other networks.

    127.0.0.53 / systemd-resolved within containers

    If docker is configured to use the provided DNS server then the container domain names may also be resolved within containers:

    $ docker run --dns 1.1.1.1 --rm -it alpine
    / # apk add bind
    / # host test.docker
    Host test.docker not found: 3(NXDOMAIN)
    $ docker run --dns 172.17.0.1 --rm -it alpine
    / # apk add bind
    / # host test.docker
    / # host test.docker
    test.docker has address 172.17.0.3
    Host test.docker not found: 3(NXDOMAIN)
    Host test.docker not found: 3(NXDOMAIN)

    If there are link-local, VPN or other DNS servers configured then those will also work within containers.

    Configuration

    systemd-resolved-docker may be configured using environment variables. When installed using the RPM /etc/sysconfig/systemd-resolved-docker may also be modified to update the environment variables.

    Name Description Default Value Example
    DNS_SERVER DNS server to use when resolving queries from docker containers. 127.0.0.53 - systemd-resolved DNS server 127.0.0.53
    SYSTEMD_RESOLVED_INTERFACE Dummy interface name which will be created to interface with systemd-resolved srd-dummy srd-dummy
    SYSTEMD_RESOLVED_LISTEN_ADDRESS IPs (+port) to listen on for queries from systemd-resolved. 127.0.0.153 127.0.0.153:1053
    DOCKER_LISTEN_ADDRESS IPs (+port) to listen on for queries from docker containers in the default network. ip of the default docker bridge, often 172.17.0.1 172.17.0.1 or 172.17.0.1:53
    ALLOWED_DOMAINS Domain which will be handled by the DNS server. If a domain starts with . then all subdomains will also be allowed. .docker .docker,.local
    DEFAULT_DOMAIN Domain to append to hostnames which are not allowed by ALLOWED_DOMAINS. docker docker
    DEFAULT_HOST_IP IP address to use for containers on the host network if the container doesn't contain one. 127.0.0.1 127.0.0.1
    --------------------------------- ----------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------- ---------------------------------

    Install

    Fedora / COPR

    For Fedora and RPM based systems COPR contains pre-built packages.

    1. Enabled the COPR repository

      dnf copr enable flaktack/systemd-resolved-docker
    2. Install the package

      dnf install systemd-resolved-docker
    3. Start and optionally enable the service

      systemctl start  systemd-resolved-docker
      systemctl enable systemd-resolved-docker
    4. Docker should be updated to use the DNS server provided by systemd-docker-resolved. This may be done globally by editing the docker daemon's configuration (daemon.json) or per-container using the --dns flag.

      "dns": [
        "172.17.0.1" // docker0 interface's IP address
      ]
    5. NetworkManager may reset the docker interface's configuration for systemd-resolved. If that happens than the interface needs to be unmanaged. This may be done by creating a /etc/NetworkManager/conf.d/99-docker.conf:

      [main]
      plugins=keyfile
      
      [keyfile]
      unmanaged-devices=interface-name:docker0

    Build

    setup.py may be used to create a python package.

    tito may be used to create RPMs.

    Links

    Portions are based on docker-auto-dnsmasq and dnslib.