diff --git a/libpod/container_internal_common.go b/libpod/container_internal_common.go index 05a36e49b8..b26b4c95cc 100644 --- a/libpod/container_internal_common.go +++ b/libpod/container_internal_common.go @@ -1993,24 +1993,35 @@ func (c *Container) generateResolvConf() error { return err } + networkBackend := c.runtime.config.Network.NetworkBackend nameservers := make([]string, 0, len(c.runtime.config.Containers.DNSServers)+len(c.config.DNSServer)) - nameservers = append(nameservers, c.runtime.config.Containers.DNSServers...) - for _, ip := range c.config.DNSServer { - nameservers = append(nameservers, ip.String()) + + // If NetworkBackend is `netavark` do not populate `/etc/resolv.conf` + // with custom dns server since after https://github.com/containers/netavark/pull/452 + // netavark will always set required `nameservers` in statsBlock and libpod + // will correctly populate `networkNameServers`. Also see https://github.com/containers/podman/issues/16172 + + // Exception: Populate `/etc/resolv.conf` if container is not connected to any network + // ( i.e len(netStatus)==0 ) since in such case netavark is not invoked at all. + if networkBackend != string(types.Netavark) || len(netStatus) == 0 { + nameservers = append(nameservers, c.runtime.config.Containers.DNSServers...) + for _, ip := range c.config.DNSServer { + nameservers = append(nameservers, ip.String()) + } } // If the user provided dns, it trumps all; then dns masq; then resolv.conf - var search []string keepHostServers := false if len(nameservers) == 0 { keepHostServers = true // first add the nameservers from the networks status nameservers = networkNameServers - // when we add network dns server we also have to add the search domains - search = networkSearchDomains // slirp4netns has a built in DNS forwarder. nameservers = c.addSlirp4netnsDNS(nameservers) } + // Set DNS search domains + search := networkSearchDomains + if len(c.config.DNSSearch) > 0 || len(c.runtime.config.Containers.DNSSearches) > 0 { customSearch := make([]string, 0, len(c.config.DNSSearch)+len(c.runtime.config.Containers.DNSSearches)) customSearch = append(customSearch, c.runtime.config.Containers.DNSSearches...) diff --git a/libpod/networking_common.go b/libpod/networking_common.go index ac914493b2..816e1d1c08 100644 --- a/libpod/networking_common.go +++ b/libpod/networking_common.go @@ -39,9 +39,15 @@ func (c *Container) convertPortMappings() []types.PortMapping { } func (c *Container) getNetworkOptions(networkOpts map[string]types.PerNetworkOptions) types.NetworkOptions { + nameservers := make([]string, 0, len(c.runtime.config.Containers.DNSServers)+len(c.config.DNSServer)) + nameservers = append(nameservers, c.runtime.config.Containers.DNSServers...) + for _, ip := range c.config.DNSServer { + nameservers = append(nameservers, ip.String()) + } opts := types.NetworkOptions{ ContainerID: c.config.ID, ContainerName: getNetworkPodName(c), + DNSServers: nameservers, } opts.PortMappings = c.convertPortMappings() diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index 3880fbc5b5..9bb2eac3c7 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -126,6 +126,37 @@ var _ = Describe("Podman run networking", func() { Expect(session).Should(Exit(0)) }) + It("podman verify resolv.conf with --dns + --network", func() { + // Following test is only functional with netavark and aardvark + // since new behaviour depends upon output from of statusBlock + SkipIfCNI(podmanTest) + net := createNetworkName("IntTest") + session := podmanTest.Podman([]string{"network", "create", net}) + session.WaitWithDefaultTimeout() + defer podmanTest.removeNetwork(net) + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"run", "--name", "con1", "--dns", "1.1.1.1", "--network", net, ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + // Must not contain custom dns server in containers + // `/etc/resolv.conf` since custom dns-server is + // already expected to be present and processed by + // Podman's DNS resolver i.e ( aarvark-dns or dnsname ). + Expect(session.OutputToString()).ToNot(ContainSubstring("nameserver 1.1.1.1")) + // But /etc/resolve.conf must contain othe nameserver + // i.e dns server configured for network. + Expect(session.OutputToString()).To(ContainSubstring("nameserver")) + + session = podmanTest.Podman([]string{"run", "--name", "con2", "--dns", "1.1.1.1", ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + // All the networks being used by following container + // don't have dns_enabled in such scenario `/etc/resolv.conf` + // must contain nameserver which were specified via `--dns`. + Expect(session.OutputToString()).To(ContainSubstring("nameserver 1.1.1.1")) + }) + It("podman run network expose port 222", func() { SkipIfRootless("iptables is not supported for rootless users") session := podmanTest.Podman([]string{"run", "-dt", "--expose", "222-223", "-P", ALPINE, "/bin/sh"}) diff --git a/test/system/500-networking.bats b/test/system/500-networking.bats index 20f25728a6..3b797be089 100644 --- a/test/system/500-networking.bats +++ b/test/system/500-networking.bats @@ -651,7 +651,7 @@ EOF " CONTAINERS_CONF=$containersconf run_podman run --rm $IMAGE cat /etc/resolv.conf - is "$output" "search example.com$nl.*" "correct search domain" + is "$output" "search example.com.*" "correct search domain" is "$output" ".*nameserver 1.1.1.1${nl}nameserver $searchIP${nl}nameserver 1.0.0.1${nl}nameserver 8.8.8.8" "nameserver order is correct" # create network with dns @@ -660,9 +660,13 @@ EOF run_podman network create --subnet "$subnet.0/24" $netname # custom server overwrites the network dns server CONTAINERS_CONF=$containersconf run_podman run --network $netname --rm $IMAGE cat /etc/resolv.conf - is "$output" "search example.com$nl.*" "correct search domain" - is "$output" ".*nameserver 1.1.1.1${nl}nameserver $searchIP${nl}nameserver 1.0.0.1${nl}nameserver 8.8.8.8" "nameserver order is correct" - + is "$output" "search example.com.*" "correct search domain" + local store=$output + if is_netavark; then + is "$store" ".*nameserver $subnet.1.*" "integrated dns nameserver is set" + else + is "$store" ".*nameserver 1.1.1.1${nl}nameserver $searchIP${nl}nameserver 1.0.0.1${nl}nameserver 8.8.8.8" "nameserver order is correct" + fi # we should use the integrated dns server run_podman run --network $netname --rm $IMAGE cat /etc/resolv.conf is "$output" "search dns.podman.*" "correct search domain"