CertGrid CertGrid
Concepts·Podman

Podman Network Drivers Beyond Bridge

`--network none` leaves a container with loopback and nothing else. `host` gives it your namespace outright. And a bridge with a subnet you chose is how you stop Podman picking 10.89.0.0/24 for you.

Networking Guide 30 of 47 Advanced

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. none, and host

    The two extremes, and both are one flag.

    --network none produces a container with only loopback. ip -o addr returns nothing for a real interface. Nothing reaches out and nothing reaches in. Genuinely useful: a build step that must not download anything, a batch job processing a mounted file, or running something you do not trust.

    --network host is the opposite - the container uses your network namespace directly, so eth0 is the host's eth0 at 192.168.0.21. No mapping, no pasta, no published ports because there is nothing to publish through: a process listening on 8080 in the container is listening on the host's 8080.

    Note that this looked identical to the default rootless case in guide 53. The addresses match. What differs is that pasta gives the container a *copy* of the host's configuration in its own namespace, while host gives it the namespace - so with host a container binding a port really does take that port from the host.

    bash Example session
    podman run --rm --network none docker.io/library/alpine ip -o addr1: lo    inet 127.0.0.1/8 scope host lo\       valid_lft forever preferred_lft forever1: lo    inet6 ::1/128 scope host \       valid_lft forever preferred_lft foreverpodman run --rm --network host docker.io/library/alpine 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::215:5dff:fe01:115a/64 scope link \       valid_lft forever preferred_lft forever

    Expected resultNo interface output from none, and the host's address from host.

    Success conditionYou can pick between total isolation and none of it.

  2. A bridge on a subnet you chose

    podman network create picks a free /24 from 10.89 upward, which is fine until it is not - a 10.89 range that collides with something you route to, or a firewall rule that needs to name the subnet.

    So specify it:

    podman network create --driver bridge --subnet 10.90.0.0/24 \
      --gateway 10.90.0.1 fixed

    The container gets 10.90.0.2/24, and the gateway is where aardvark-dns listens, exactly as in guide 52.

    Worth doing deliberately for anything long-lived. An auto-allocated subnet is reproducible only as long as no other network is created first, so two hosts provisioned in different orders end up with different addresses - which is the sort of difference that surfaces much later, in a firewall rule.

    bash Example session
    podman network create --driver bridge --subnet 10.90.0.0/24 --gateway 10.90.0.1 fixedfixedpodman network inspect fixed --format 'subnet={{range .Subnets}}{{.Subnet}} gw={{.Gateway}}{{end}}'subnet=10.90.0.0/24 gw=10.90.0.1podman run --rm --network fixed docker.io/library/alpine ip -o addr show eth02: eth0    inet 10.90.0.2/24 brd 10.90.0.255 scope global eth0\       valid_lft forever preferred_lft forever2: eth0    inet6 fe80::bc24:94ff:fea8:55cb/64 scope link tentative \       valid_lft forever preferred_lft forevertime="2026-08-22T12:03:25Z" level=error msg="Removing container 3d5a52b3359f8991421ae73898d382d4db809d426d2cbce61beb1f4e2fb12b0e: cleaning up container 3d5a52b3359f8991421ae73898d382d4db809d426d2cbce61beb1f4e2fb12b0e: removing container 3d5a52b3359f8991421ae73898d382d4db809d426d2cbce61beb1f4e2fb12b0e network: 1 error occurred:\n\t* rootless netns: kill network process: permission denied\n\n"podman network rm fixedfixed

    Expected resultA network on 10.90.0.0/24 with the gateway you named, and a container addressed from it.

    Success conditionYou created a network whose addresses you chose.

  3. macvlan, and why it is not demonstrated here

    The remaining driver worth knowing is macvlan, which gives a container its own MAC address on your physical network. It appears to other machines as a separate host with its own LAN address - not a port forward, not NAT, an actual peer.

    podman network create -d macvlan -o parent=eth0 \
      --subnet 192.168.0.0/24 --gateway 192.168.0.1 \
      --ip-range 192.168.0.240-192.168.0.250 lan

    Not run on this host, and no output for it appears above. It needs a range of addresses reserved on the lab's real LAN, and taking ten addresses this network has not allocated would produce a conflict rather than a lesson.

    What to know about it anyway:

    • It needs root. There is no rootless macvlan, because handing out MAC addresses on a physical interface is privileged.
    • The host usually cannot reach the container on its macvlan address - traffic leaves the parent interface and does not come back. This surprises everyone once.
    • Many wireless interfaces and cloud networks reject it, because a second MAC on one port is exactly what port security prevents.
    • You must reserve the range in your DHCP server, or something else will lease an address you handed to a container.

    Use it when something genuinely has to look like a machine on the network - a DHCP server, something doing service discovery by broadcast, a legacy appliance. For everything else a bridge and a published port is simpler and works rootless.

    bash Example session
    podman network lsNETWORK ID    NAME        DRIVER2f259bab93aa  podman      bridge

    Expected resultThe network list, back to just the default.

    Success conditionYou can say what macvlan is for and why you would avoid it.

Troubleshooting

Official sources