Docker networking determines how containers communicate with each other, with the host, and with external networks. RHEL 8 adds a layer of complexity because Docker writes its own iptables rules at startup, which can interact unexpectedly with firewalld — the default firewall manager on RHEL 8. Understanding Docker’s network drivers and how they map to the underlying Linux networking stack lets you build reliable, secure multi-container architectures. This tutorial covers the bridge, host, and macvlan drivers as well as the firewalld considerations unique to RHEL 8.

Prerequisites

  • Docker CE installed and running on RHEL 8
  • Root or sudo access, or membership in the docker group
  • firewalld running (verify with sudo systemctl status firewalld)
  • Basic familiarity with IP addressing and ports

Step 1 — Understand the Default Bridge Network

When Docker installs, it creates a virtual bridge named docker0 and assigns the default subnet 172.17.0.0/16 to it. Every container started without an explicit network flag is connected to this bridge and can reach the internet through NAT, but cannot resolve other containers by name.

docker network ls
docker network inspect bridge

The inspect output shows connected containers, subnet, and gateway. User-defined bridge networks (created in the next step) are preferred over the default bridge because they provide automatic DNS resolution between containers.

Step 2 — Create a User-Defined Bridge Network

Create a custom bridge network and start two containers on it. Containers on the same user-defined network can reach each other using their container names as hostnames, without needing to expose ports to the host.

docker network create mynet

docker run -d --name backend --network mynet redis:alpine
docker run -d --name frontend --network mynet nginx:alpine

# Verify DNS resolution between containers
docker exec frontend ping -c 3 backend

The ping succeeds because Docker’s embedded DNS server resolves backend to the container’s internal IP automatically on user-defined networks.

Step 3 — Expose Ports and Understand firewalld Interaction

Use the -p flag to publish a container port on the host. On RHEL 8, Docker bypasses firewalld by writing directly to the iptables DOCKER chain, meaning a port published with -p is accessible from the network regardless of your firewalld rules.

# Publish container port 80 on host port 8080
docker run -d --name webserver --network mynet -p 8080:80 nginx:alpine

# Confirm the iptables rule Docker created
sudo iptables -t nat -L DOCKER -n --line-numbers

To restrict external access to a published port, bind it to a specific host IP: -p 127.0.0.1:8080:80 makes the port available only on localhost.

Step 4 — Use the Host Network Driver

The host network driver removes the network namespace isolation between the container and the host. The container shares the host’s network stack directly — useful for high-throughput workloads or legacy applications that require the host IP.

docker run -d --name hostnet-app --network host nginx:alpine
curl http://localhost:80

With --network host, the -p flag has no effect — the container binds directly to host ports. This driver is not available on macOS or Windows Docker Desktop; it is Linux-only and works natively on RHEL 8.

Step 5 — Configure macvlan for Direct LAN Access

A macvlan network assigns each container its own MAC address and IP on your physical LAN, making containers appear as first-class network devices to your router and other hosts. This requires knowing your host’s network interface name and LAN subnet.

# Replace ens3, 192.168.1.0/24, and 192.168.1.1 with your LAN values
docker network create -d macvlan 
  --subnet=192.168.1.0/24 
  --gateway=192.168.1.1 
  -o parent=ens3 
  macvlan_net

docker run -d --name lan-app 
  --network macvlan_net 
  --ip 192.168.1.150 
  nginx:alpine

Note: the host cannot communicate directly with containers on a macvlan network without a macvlan sub-interface on the host side, which is a common source of confusion.

Step 6 — Inspect and Remove Networks

List all networks, inspect a specific one to see connected containers and configuration, then remove networks that are no longer needed.

docker network ls
docker network inspect mynet
docker network rm mynet

# Remove all networks not used by any container
docker network prune

Docker will refuse to remove a network that still has containers connected to it. Stop or remove the containers first, or disconnect them with docker network disconnect mynet container_name.

Conclusion

You now understand Docker’s core networking drivers on RHEL 8 and how to handle the critical firewalld interaction where Docker-published ports bypass firewalld rules by writing directly to iptables. User-defined bridge networks are the right default for most multi-container applications because they provide automatic container DNS without exposing ports to the host unnecessarily. Reserve the host network driver for performance-critical single-container workloads and macvlan for scenarios where containers must be addressable directly on your physical network.

Next steps: How to Manage Docker Images and Containers on RHEL 8, How to Use Docker Volumes and Bind Mounts on RHEL 8, and How to Install Docker Compose on RHEL 8.