CertGrid CertGrid
Troubleshooting·Podman

Podman Default Network DNS Behavior

`getent hosts beta` exits 2 on the default network and resolves on a user-defined one. One `podman network create` is the whole fix, and it changes the container's address from your host's IP to 10.89.0.2.

Networking Guide 28 of 47 Beginner

Written against the versions above. Podman follows the distribution here rather than a vendor repository, so the version you get is the one Ubuntu shipped. The commands are stable across 5.x.

Every command on this page ran on podman01.
Server NameIP AddressOSRolesCPURAMHDD
PODMAN01192.168.0.21Ubuntu 26.04 LTSPrimary Container Host2 Core4 GB50 GB

Before you start

  1. Two containers that cannot find each other

    Start two containers with no --network flag, so both land on the default podman network. Then ask one to resolve the other:

    $ podman exec alpha getent hosts beta
    [exit 2]

    Nothing. Exit 2 from getent means the name did not resolve.

    This is the single most common surprise for someone arriving from Docker, where the default bridge also has no DNS but --link and Compose papered over it for years. There is no name resolution here because the network has dns=false.

    Two more readings from the same containers, which are worth noticing now and are explained in guide 53: NetworkSettings.IPAddress is empty, its Networks map is empty, and the container's eth0 is 192.168.0.21 - the host's own LAN address, not anything from 10.88.0.0/16.

    bash Example session
    podman run -d --name alpha docker.io/library/alpine sleep 30061c5617cecac5356d955e03eb80b851cf17e75a22a708ee25e842b3c83c54eb1podman run -d --name beta docker.io/library/alpine sleep 3008354166f0fa25490e026120949753e2ed58c3d7471b8257b8c8d0cbe214c898dpodman inspect alpha --format 'ip=[{{.NetworkSettings.IPAddress}}] net={{range $k,$v := .NetworkSettings.Networks}}{{$k}}{{end}}'ip=[] net=podman exec alpha ip -o addr show eth02: eth0    inet 192.168.0.21/24 brd 192.168.0.255 scope global eth0\       valid_lft forever preferred_lft forever2: eth0    inet6 fe80::a05d:b8ff:fea9:b6cc/64 scope link flags 02 \       valid_lft forever preferred_lft foreverpodman exec alpha getent hosts beta [exit 2]

    Expected resultAn empty IP field, the host's address on eth0, and a failed lookup.

    Success conditionYou have reproduced the failure and know it is the network's fault, not the container's.

  2. One command changes everything

    podman network create appnet - no flags. Inspect it:

    driver=bridge subnet=10.89.0.0/24 dns=true

    dns=true, and a subnet of 10.89.0.0/24 rather than the default network's 10.88.0.0/16. User-defined networks are allocated from 10.89 upward, one /24 at a time.

    So DNS is not a flag you forgot. It is the difference between the default network and every network you create, and the default is the only one without it.

    bash Example session
    podman network create appnetappnetpodman network inspect appnet --format 'driver={{.Driver}} subnet={{range .Subnets}}{{.Subnet}}{{end}} dns={{.DNSEnabled}}'driver=bridge subnet=10.89.0.0/24 dns=true

    Expected resultA bridge network with dns=true on 10.89.0.0/24.

    Success conditionYou have a network whose inspect output says DNS is on.

  3. The same two containers, now on a real bridge

    Start them again with --network appnet, and three things change at once.

    They get bridge addresses. eth0 is 10.89.0.2/24 - an address from the network's subnet, which the default network never gave them.

    Resolution works:

    $ podman exec alpha getent hosts beta
    10.89.0.3         beta.dns.podman  beta.dns.podman beta

    Both the bare name and a fully qualified beta.dns.podman.

    And /etc/resolv.conf explains how:

    search dns.podman practicelabpro.local
    nameserver 10.89.0.1

    The nameserver is the network's gateway address, where aardvark-dns is listening, and dns.podman is in the search list so bare names work. Note the host's own search domain was inherited too - Podman merges the host's resolver configuration with its own rather than replacing it, so external names still resolve.

    The rule to take away: if containers need to talk to each other by name, put them on a network you created. This is the same conclusion Compose reaches by creating a project network for you, and it is why guide 21 used a pod instead - containers in a pod share one namespace and need no DNS at all.

    bash Example session
    podman run -d --network appnet --name alpha docker.io/library/alpine sleep 30069c52943fec12a11a6d2bf31490c60ba143ee79c7499277a13d33c45c98d80b3podman run -d --network appnet --name beta docker.io/library/alpine sleep 3001dd7107d7c4d08cb59d0fadfc9d7f85d80e373f239d06e26ea3464871df0c482podman exec alpha ip -o addr show eth02: eth0    inet 192.168.0.21/24 brd 192.168.0.255 scope global eth0\       valid_lft forever preferred_lft forever2: eth0    inet6 fe80::a05d:b8ff:fea9:b6cc/64 scope link flags 02 \       valid_lft forever preferred_lft foreverpodman exec alpha getent hosts beta [exit 2]podman exec alpha cat /etc/resolv.confsearch dns.podman practicelabpro.localnameserver 10.89.0.1

    Expected resultA 10.89.0.2 address, a successful lookup of beta, and a nameserver at 10.89.0.1.

    Success conditionOne container resolved another by name.

Troubleshooting

Official sources