Learn Podman - Networking
Episode 8 of 23

Learn Podman - Networking

Connecting containers and pods through the netavark and aardvark-dns networking stack: per-container DNS, port mapping with -p, a comparison of bridge, macvlan, ipvlan, and host network types, and how rootless port forwarding works with pasta and slirp4netns.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 7 you stored data with volumes and mounts. Now it's time to connect everything together: networking. Episode 8 covers Podman's modern networking stack — netavark and aardvark-dns — along with per-container DNS, port mapping, the available network types, and how port forwarding works in rootless mode.

Netavark and aardvark-dns

Podman uses a networking architecture separate from the container engine daemon. Since Podman 4, the default stack is a combination of two components developed by Red Hat:

  • netavark — a network configuration tool that builds bridges and firewall rules for each container, working directly with the kernel.
  • aardvark-dns — a per-container DNS resolver that runs a local DNS service for containers on the same network.

This two-component architecture replaces the Docker daemon handles everything model: netavark manages the data path, aardvark-dns manages name resolution. With this separation, both can be developed and tested independently. In Podman 6, this stack moved to a second generation (v2) with more modern handling — and it remains the default choice.

podman network inspect shows network details including the names of registered containers, and podman info shows which components are currently in use for networking.

Per-Container DNS

Because aardvark-dns works per network, every container connected to the same network can call each other by name — without needing to guess an IP:

DNS between containers
podman network create mynet
podman run -d --network mynet --name db mariadb:latest
podman run --rm --network mynet --name client alpine ping -c1 db

The client container calls db by name — not by IP — and aardvark-dns resolves it to the db container's address on the mynet network. When a container's IP changes due to a restart, the name stays the same; this is why per-container DNS is the foundation of service-to-service communication.

Port Mapping

For a service to be reachable from outside — a browser, a load balancer, or a container on another network — the container port must be mapped to the host:

Mapping a container port to the host
podman run -d --name web -p 8080:80 nginx:latest
podman port web

-p 8080:80 maps port 80 inside the container to port 8080 on the host. podman port web shows the active mappings. For one-directional mapping (only allowing access from a specific port), the flag can be written more explicitly, for example -p 127.0.0.1:8080:80 so it's only accessible from localhost.

Network Types

Podman provides several network types, each with its own trade-offs:

TypeHow it worksUse case
bridgeIsolated virtual network, NAT outDefault, most common
macvlanContainers use MAC addresses on the physical networkContainers on the same LAN
ipvlanContainers use IPs on the physical network, without their own MACSubnets constrained by MAC addresses
hostContainer uses the host network namespace directlyMaximum performance, no isolation

Bridge (Default)

When podman run runs without the --network option, the container joins the default bridge. Each container gets a virtual IP, and outbound traffic goes through NAT. This is the safest isolation and is the choice for almost all workloads:

Creating a custom bridge network
podman network create --driver bridge backend
podman run -d --network backend --name api myapp:latest

podman network create --driver bridge backend creates a new bridge, and the api container attaches to it. podman network ls lists all networks, while podman network rm removes one — make sure no container is still using it.

Macvlan and Ipvlan

For containers that must appear like ordinary devices on the physical network, macvlan gives each container its own MAC address on the same LAN. Its downside: it can't communicate with the same host via a physical address, and many switches/APs limit the number of MAC addresses. ipvlan groups several containers under a single MAC, splitting traffic based on IP — suitable when MAC count is a constraint.

Aspectmacvlanipvlan
MAC addressOne per containerOne shared among all
Switch limitationsProne to MAC capsUnaffected
Traffic from the hostNot supportedDepends on mode

Host

The host network places the container directly in the host network namespace. There's no IP isolation and no NAT — maximum performance, but container ports directly occupy host ports. Suitable for workloads extremely sensitive to latency, with security consequences you should be aware of.

Rootless Port Forwarding

In rootless mode, containers can't build a kernel bridge. As you learned in episode 5, traffic is forwarded by a user-space process — pasta or slirp4netns. On modern Podman, pasta is the default choice for rootless because its port forwarding is more efficient.

Port forwarding on a rootless container
podman run -d --name app -p 8080:8080 myapp:latest
podman ps --format "table {{.Names}}\t{{.Ports}}"

The command is identical to root mode; only the data path differs — through user-space, not the host kernel. Remember the limitation from episode 5: low ports below 1024 can't be opened directly without extra configuration, and rootless port forwarding adds a little overhead.

Warning

The same port mapping can't be used by two containers at once. If podman run fails with a port already in use message, check with podman ps -a or ss -tlnp — another container or host process may already occupy the port.

Connecting a Pod to a Network

Pods also attach to networks the same way. A pod created with a specific --network makes every container inside it share one address on that network:

Pod with a network and port
podman pod create --name apipod --network backend -p 9000:9000
podman run -d --pod apipod --name api myapp:latest

Because all pod members share a network namespace, the port mapping above only needs to be declared once when the pod is created — exactly the pattern you learned in episode 6. Per-container DNS still applies: other containers on backend can call the pod by its name.

Closing

Episode 8 covered Podman networking in full: the netavark and aardvark-dns stack as the foundation, per-container DNS that makes service-to-service communication easy, port mapping with -p, a comparison of bridge, macvlan, ipvlan, and host network types, how rootless port forwarding works with pasta and slirp4netns, and placing pods on a network.

The key points to take home:

  • Netavark builds the network, aardvark-dns resolves names — two components working together.
  • Per-container DNS removes the dependency on static IPs — call containers by name.
  • Bridge is the safe default — choose macvlan, ipvlan, or host only when there's a specific reason.
  • Rootless port forwarding runs through user-space — same command, different data path.

In the next episode, Episode 9, you'll switch from running images to building your own images: Containerfile and Buildah — from FROM, RUN, COPY, CMD, ENTRYPOINT, HEALTHCHECK, all the way to multi-stage builds with cache.

Learn Podman - Networking | Learn Podman