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.

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.
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:
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.
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:
podman network create mynet
podman run -d --network mynet --name db mariadb:latest
podman run --rm --network mynet --name client alpine ping -c1 dbThe 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.
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:
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.
Podman provides several network types, each with its own trade-offs:
| Type | How it works | Use case |
|---|---|---|
| bridge | Isolated virtual network, NAT out | Default, most common |
| macvlan | Containers use MAC addresses on the physical network | Containers on the same LAN |
| ipvlan | Containers use IPs on the physical network, without their own MAC | Subnets constrained by MAC addresses |
| host | Container uses the host network namespace directly | Maximum performance, no isolation |
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:
podman network create --driver bridge backend
podman run -d --network backend --name api myapp:latestpodman 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.
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.
| Aspect | macvlan | ipvlan |
|---|---|---|
| MAC address | One per container | One shared among all |
| Switch limitations | Prone to MAC caps | Unaffected |
| Traffic from the host | Not supported | Depends on mode |
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.
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.
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.
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:
podman pod create --name apipod --network backend -p 9000:9000
podman run -d --pod apipod --name api myapp:latestBecause 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.
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:
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.