Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to configure docker container DNS

2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Servers >

Share

Shulou(Shulou.com)05/31 Report--

Editor to share with you how to configure docker container DNS, I believe most people do not know much about it, so share this article for your reference, I hope you can learn a lot after reading this article, let's go to know it!

Configure container DNSDNS in default bridge networkOptionsDescription-h HOSTNAME or-- hostname=HOSTNAME sets HOSTNAME to the / etc/hosts, / etc/hostname, / bin/bash prompt within the container when the container starts. -- link=CONTAINER_NAME or ID:ALIAS adds the container IP corresponding to ALIAS and CONTAINER_NAME/ID to / etc/hosts when the container starts. What if CONTAINER_NAME/ID has more than one IP address? -- dns=IP_ADDRESS... When the container starts, add nameserver IP_ADDRESS to / etc/resolv.conf within the container. Multiple can be configured. -- dns-search=DOMAIN... When the container starts, add DOMAIN to the dns search list of / etc/resolv.conf in the container. Multiple can be configured. -- dns-opt=OPTION... When the container starts, you can configure more than one by adding OPTION to the options option in the container / etc/resolv.conf.

Description:

If docker run does not contain-- dns=IP_ADDRESS...,-- dns-search=DOMAIN..., or-- dns-opt=OPTION... Parameter, docker daemon will copy the / etc/resolv.conf of the local host, and then process the copy (discard those nameserver items in the / etc/resolv.conf that do not understand ping), and the part left after processing will be regarded as the internal / etc/resolv.conf of the container. Therefore, if you want to use the nameserver configured in / etc/resolv.conf in the host for domain name resolution, you need to configure an IP in the host that can ping the dns service in the host.

If the / etc/resolv.conf content of the host is changed, a corresponding file change notifier in docker daemon will watch the change, and then take corresponding measures according to the status of the container:

If the container starts with the-- dns,-- dns-search, or-- dns-opt option, it starts with changes to the host's / etc/resolv.conf filtered content, so docker daemon will never update the container's / etc/resolv.conf.

If the container status is stopped, the / etc/resolv.conf in the container is updated immediately according to the / etc/resolv.conf content of the host.

If the container state is running, the / etc/resolv.conf in the container will not change until the container state becomes stopped.

If the / etc/resolv.conf in the container is modified after the container is started, the container will not be processed, otherwise the completed changes may be lost, regardless of the state of the container.

Note: the implementation of this file change notifier of docker daemon monitoring host / etc/resolv.conf relies on the inotify feature of the linux kernel, while the inotfy feature is not compatible with overlay fs, so docker deamon using overlay fs driver will not be able to use the / etc/resolv.conf automatic update feature. 、

Embedded DNS in user-defined networks

In docker version 1.10, docker daemon implements something called embedded DNS server when you create a container that meets the following conditions:

Use a custom network

A name is provided through-- name,--network-alias or-- link when the container is created

Docker daemon uses embedded DNS server to resolve the names of all containers in the entire custom network (you can understand it as a kind of service discovery in a network).

Therefore, when you start the container to meet the above conditions, the domain name resolution of the container should not consider the / etc/hosts, / etc/resolv.conf in the container, but should keep it unchanged or even empty, and configure all the domain names to be resolved to the corresponding embedded DNS server. The specific configuration parameters and instructions are as follows:

When OptionsDescription--name=CONTAINER-NAME starts the container, it configures CONTAINER-NAME and the container's IP to the embedded DNS server in the custom network to which the container is connected, which provides domain name resolution within the custom network scope-network-alias=ALIAS configures the container's name-ip map to the embedded DNS server of other networks to which the container is connected. PS: a container may be connected to multiple networks. -- when link=CONTAINER_NAME:ALIAS starts the container, configure the container IP corresponding to ALIAS and CONTAINER_NAME/ID to the embedded DNS server in the custom network to which the container is connected, but only if the container configured with the link can resolve the rule. -- dns= [IP _ ADDRESS...] When embedded DNS server is unable to resolve a dns query of the container, the request is foward to these-- dns-configured IP_ADDRESS DNS Server, which further resolves the domain name. Note that these-- dns configuration to nameserver IP_ADDRESS are all managed by the corresponding embedded DNS server and will not be updated to the / etc/resolv.conf.--dns-search=DOMAIN... in the container When the container starts, the DOMAIN configured with-dns-search will be configured to the embedded DNS server and will not be updated to / etc/resolv.conf within the container. -- dns-opt=OPTION... When the container starts, the OPTION configured with-dns-opt will be configured to the embedded DNS server and will not be updated to / etc/resolv.conf within the container.

Description:

If docker run does not contain-- dns=IP_ADDRESS...,-- dns-search=DOMAIN..., or-- dns-opt=OPTION... Parameter, docker daemon will copy the / etc/resolv.conf of the local host, and then process the copy (discard those nameserver items in the / etc/resolv.conf that do not understand ping), and the part left after processing will be regarded as the internal / etc/resolv.conf of the container. Therefore, if you want to use the nameserver configured in / etc/resolv.conf in the host for domain name resolution, you need to configure an IP in the host that can ping the dns service in the host.

Note that the DNS server configured in the container / etc/resolv.conf will be used only if the the embedded DNS server cannot parse a certain name.

Embedded DNS server source code analysis

All the embedded DNS server-related code is in the libcontainer project, and the main files are / libnetwork/resolver.go,/libnetwork/resolver_unix.go,sandbox_dns_unix.go.

OK, let's first look at the definition of the embedded DNS server object in docker:

Libnetwork/resolver.go// resolver implements the Resolver interfacetype resolver struct {sb * sandbox extDNSList [maxExtDNS] extDNSEntry server * dns.Server conn * net.UDPConn tcpServer * dns.Server tcpListen * net.TCPListener err error count int32 tStamp time.Time queryLock sync.Mutex} / / Resolver represents the embedded DNS server in Docker. It operates// by listening on container's loopback interface for DNS queries.type Resolver interface {/ / Start starts the name server for the container Start () error / / Stop stops the name server for the container. Stopped resolver / / can be reused after running the SetupFunc again. Stop () / / SetupFunc () provides the setup function that should be run / / in the container's network namespace. SetupFunc () func () / / NameServer () returns the IP of the DNS resolver for the / / containers. NameServer () string / / SetExtServers configures the external nameservers the resolver / / should use to forward queries SetExtServers ([] string) / / ResolverOptions returns resolv.conf options that should be set ResolverOptions () [] string}

It can be seen that resolver is embedded DNS server, and each resolver bind a sandbox and defines a corresponding dns.Server, as well as a list of external DNS objects, but when embedded DNS server cannot parse a certain name, it will forward to those external DNS.

Resolver Interface defines the interfaces that embedded DNS server must implement, and here we will focus on SetupFunc () and Start (), as analyzed below.

The implementation of dns.Server, all handed over to github.com/miekg/dns, is limited to space, and I will not follow in the analysis here.

From the perspective of the entire container create process, docker daemon's processing of embedded DNS server begins with endpoint Join a sandbox:

Libnetwork/endpoint.gofunc (ep * endpoint) Join (sbox Sandbox, options... EndpointOption) error {. Return ep.sbJoin (sb, options...)} func (ep * endpoint) sbJoin (sb * sandbox, options... EndpointOption) error {. If err = sb.populateNetworkResources (ep); err! = nil {return err}.}

In the process of sandbox join a sandbox, sandbox. PopulateNetworkResources does the setting of network resources, which includes the startup of embedded DNS server.

Libnetwork/sandbox.gofunc (sb * sandbox) populateNetworkResources (ep * endpoint) error {... If ep.needResolver () {sb.startResolver (false)}...} libnetwork/sandbox_dns_unix.gofunc (sb * sandbox) startResolver (restore bool) {sb.resolverOnce.Do (func () {var err error sb.resolver = NewResolver (sb) defer func () { If err! = nil {sb.resolver = nil}} () / In the case of live restore container is already running with / / right resolv.conf contents created before. Just update the / / external DNS servers from the restored sandbox for embedded / / server to use. If! restore {err = sb.rebuildDNS () if err! = nil {log.Errorf ("Updating resolv.conf failed for container% s,% Q", sb.ContainerID () Err) return}} sb.resolver.SetExtServers (sb.extDNS) sb.osSbox.InvokeFunc (sb.resolver.SetupFunc ()) if err = sb.resolver.Start () Err! = nil {log.Errorf ("Resolver Setup/Start failed for container% s,% Q", sb.ContainerID (), err)}})}

Sandbox.startResolver is the key to the process:

/ etc/resolv.conf in container is generated through sanbdox.rebuildDNS

Set the forward DNS list of embedded DNS server through resolver.SetExtServers (sb.extDNS)

Start two randomly available ports as TCP and UDP Linstener of embedded DNS server (127.0.0.11) through resolver.SetupFunc ()

Set up the iptable in the container through resolver.Start () (see below), and start a nameserver through miekg/dns to provide services on port 53.

Now I will introduce each of the above steps one by one.

Sanbdox.rebuildDNS

Sanbdox.rebuildDNS is responsible for building the resolv.conf in the container. The construction rules are mentioned in the first section of river parameter configuration:

Save the external name servers in resolv.conf in the sandbox

Add only the embedded server's IP to container's resolv.conf

If the embedded server needs any resolv.conf options add it to the current list

Libnetwork/sandbox_dns_unix.gofunc (sb * sandbox) rebuildDNS () error {currRC, err: = resolvconf.GetSpecific (sb.config.resolvConfPath) if err! = nil {return err} / / localhost entries have already been filtered out from the list / / retain only the v4 servers in sb for forwarding the DNS queries sb.extDNS = resolvconf.GetNameservers (currRC.Content Types.IPv4) var (dnsList = [] string {sb.resolver.NameServer ()} dnsOptionsList = resolvconf.GetOptions (currRC.Content) dnsSearchList = resolvconf.GetSearchDomains (currRC.Content)) dnsList = append (dnsList, resolvconf.GetNameservers (currRC.Content, types.IPv6)...) ResOptions: = sb.resolver.ResolverOptions () dnsOpt:... DnsOptionsList = append (dnsOptionsList, resOptions...) _, err = resolvconf.Build (sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList) return err} resolver.SetExtServers

Set the forward DNS list of embedded DNS server so that when embedded DNS server cannot parse a name, it will forward the request to ExtServers. The code is very simple, not a lot of nonsense.

Libnetwork/resolver.gofunc (r * resolver) SetExtServers (dns [] string) {l: = len (dns) if l > maxExtDNS {l = maxExtDNS} for I: = 0; I < l; iTunes + {r.extDNSList.ipStr = dns [I]}} resolver.SetupFunc

Start the two randomly available ports as TCP and UDP Linstener for embedded DNS server (127.0.0.11).

Libnetwork/resolver.gofunc (r * resolver) SetupFunc () func () {return (func () {var err error / / DNS operates primarily on UDP addr: = & net.UDPAddr {IP: net.ParseIP (resolverIP),} r.conn, err = net.ListenUDP ("udp") Addr). / / Listen on a TCP as well tcpaddr: = & net.TCPAddr {IP: net.ParseIP (resolverIP),} r.tcpListen, err = net.ListenTCP ("tcp", tcpaddr).})} resolver.Start

Two important steps in resolver.Start are:

SetupIPTable sets the iptables in the container

Start dns nameserver to provide domain name resolution service at port 53

Func (r * resolver) Start () error {... If err: = r.setupIPTable (); err! = nil {return fmt.Errorf ("setting upIP table rules failed:% v", err)}. TcpServer: = & dns.Server {Handler: r, Listener: r.tcpListen} r.tcpServer = tcpServer go func () {tcpServer.ActivateAndServe ()} () return nil}

Let's first take a look at how to set the iptables in the container:

Func (r * resolver) setupIPTable () error {. / / two local random listening ports laddr: = r.conn.LocalAddr () .String () ltcpaddr: = r.tcpListen.Addr () .String () cmd: = & exec.Cmd {Path: reexec.Self () / / pass these two ports to the setup-resolver command and start the execution of Args: append ([] string {"setup-resolver"}, r.sb.Key (), laddr, ltcpaddr), Stdout: os.Stdout, Stderr: os.Stderr,} if err: = cmd.Run () Err! = nil {return fmt.Errorf ("reexec failed:% v", err)} return nil} / / init when registering the handlerfunc init () {reexec.Register ("setup-resolver", reexecSetupResolver)} / / setup-resolver corresponding to setup-resolver, the handler definition func reexecSetupResolver () {. / / encapsulates iptables data _, ipPort _: = net.SplitHostPort (os.Args [2]) _, tcpPort, _: = net.SplitHostPort (os.Args [3]) rules: = [] [] string {{"- t", "nat", "- I", outputChain, "- d", resolverIP, "- p", "udp", "- dport", dnsPort, "- j", "DNAT", "- to-destination" Os.Args [2]}, {"- t", "nat", "- I", postroutingchain, "- s", resolverIP, "- p", "udp", "- sport", ipPort, "- j", "SNAT", "- to-source", ":" + dnsPort}, {"- t", "nat", "- I", outputChain, "- d", resolverIP, "- p" "tcp", "--dport", dnsPort, "- j", "DNAT", "--to-destination", os.Args [3]}, {"- t", "nat", "- I", postroutingchain, "- s", resolverIP, "- p", "tcp", "- sport", tcpPort, "- j", "SNAT", "- to-source", ": + dnsPort}" }... / / insert outputChain and postroutingchain...}

Iptables adding outputChain and postroutingchain are clearly defined in reexecSetupResolver (). The dns query request in the container is redirected to the two randomly available ports of udp/tcp on embedded DNS server (127.0.0.11), and the return data of embedded DNS server (127.0.0.11) is redirected to port 53 in the container, thus completing the entire dns query request.

The model is as follows:

Post an example picture:

At this point, the source analysis of embedded DNS server is over. Of course, there are many details that are left to the reader to read the code.

Welfare

In addition, I won't repeat the wheel by borrowing a timing diagram drawn by my colleague wuke to see where the operation of embedded DNS server is in the entire container create process.

The above is all the content of this article "how to configure docker container DNS". Thank you for reading! I believe we all have a certain understanding, hope to share the content to help you, if you want to learn more knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Servers

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report