Skip to content

Host Network Example


The host network sounds simple in theory: give the container the host’s network namespace and let it use the host network directly.

Let’s make that difference visible.

We’ll build the same kind of small scenario as the bridge example, but this time the container will use --network host. The important thing to watch is what happens to ports.

The Goal

With the bridge example, the pattern was:

Host :8080
    |
    | published port
    v
Container :80

Now we want:

Host :80
    |
    v
Container process

There is no separate container network in the middle.

The container process is using the host’s network namespace.

Start a Host-Networked Container

Run nginx with host networking:

docker container run -d \
  --name host-web \
  --network host \
  nginx:alpine

Notice what is missing:

--publish

We don’t need it.

The nginx process is using the host network directly.

Test the Container

Open:

http://localhost

If nginx starts successfully, you should see the nginx welcome page.

The important part is the address:

localhost:80

We didn’t configure:

8080:80

The container’s nginx process is listening through the host’s network namespace.

The path is simply:

Browser
   |
   v
Host :80
   |
   v
nginx process inside container

Compare that with bridge networking:

Browser
   |
   v
Host :8080
   |
   v
port publishing
   |
   v
Container :80

That’s the difference we wanted to see.

Check the Network Mode

We can inspect the container:

docker inspect host-web

Look for the network configuration.

You should find that its network mode is:

host

This confirms that Docker did not create a separate network namespace for the container.

What Happened to the Container IP?

With a bridge network, you would expect something like:

host-web
172.x.x.x

But host networking doesn’t work that way.

The container is sharing the host’s network namespace.

So instead of:

container IP
      ↓
host IP

think:

container process
      ↓
host network interfaces

There is no separate private container network sitting between nginx and the host.

The Port Belongs to the Host

Let’s make the important part explicit.

When nginx listens on port 80 in this container:

host-web
   |
   └── nginx :80

that port is effectively a port in the host’s network namespace.

So if something else on the host is already listening on port 80, nginx cannot use it.

This is the downside of sharing the host network.

See the Port Collision

Let’s deliberately create a conflict.

First stop and remove the nginx container:

docker container rm -f host-web

Now imagine another host process is already listening on port 80.

If you start a host-networked nginx container while that port is occupied:

docker container run -d \
  --name host-web \
  --network host \
  nginx:alpine

nginx may fail to start because port 80 is already in use.

The exact behavior depends on what is already listening and how the application handles the bind failure, but the important rule is:

A host-networked container cannot independently claim a port that is already occupied in the host’s network namespace.

With bridge networking, containers have separate network namespaces, so multiple containers can each listen on their own port 80.

For example:

Bridge:

Container A :80
Container B :80
Container C :80

All possible because each has
a separate network namespace.

With host networking:

Host network namespace

Container A :80
Container B :80  ← conflict
Container C :80  ← conflict

There is only one :80.

Compare It Directly with Bridge Networking

Let’s recreate the same web service using the default bridge.

Remove the host-networked container first:

docker container rm -f host-web

Now run nginx with bridge networking:

docker container run -d \
  --name bridge-web \
  --publish 8080:80 \
  nginx:alpine

Now the architecture is:

    flowchart LR
    Browser["Browser<br/>localhost:8080"] --> H["Host :8080"]
    H --> P["Port publishing"]
    P --> B["bridge-web :80"]
  

Open:

http://localhost:8080

The browser reaches nginx.

Now compare:

    flowchart LR
    Browser1["Browser<br/>localhost:80"] --> H1["Host network :80"]
    H1 --> C1["host-web<br/>nginx process"]
  

The two commands look similar:

# Bridge
docker container run -d \
  --name bridge-web \
  --publish 8080:80 \
  nginx:alpine
# Host
docker container run -d \
  --name host-web \
  --network host \
  nginx:alpine

But the networking architecture is completely different.

The Important Comparison

BridgeHost
Container network namespaceSeparateShared with host
nginx listens inContainer networkHost network
Host URLlocalhost:8080localhost:80
--publishNeeded for host accessNot needed
Multiple containers on port 80PossibleConflict
docker0 bridgeUsedNot used

This table is really just another way of expressing the diagrams.

What About Container-to-Container Communication?

The bridge example also showed another important feature:

web → backend
      |
      app-net
      |
      Docker DNS

That isn’t the model we’re demonstrating here.

With host networking, containers share the host network namespace instead of joining a private user-defined bridge.

If two host-networked containers need to communicate, they use addresses and ports available through that shared host network.

For example:

Host network namespace
        |
        +── service A :8000
        |
        +── service B :9000

A process can connect to another using the appropriate host-network address and port.

The important thing is that there is no private app-net bridge and no separate container IP for Docker to resolve in the same way as the user-defined bridge example.

Why Would This Be Useful?

So far, host networking may look like a worse version of bridge networking.

That’s because bridge networking is usually the better choice for ordinary applications.

Host networking becomes interesting when the application specifically benefits from direct access to the host’s network stack.

For example, imagine a network monitoring tool that needs to observe network traffic or work closely with host interfaces.

A bridge adds another networking layer:

Application
    |
    v
Container network
    |
    v
Docker networking
    |
    v
Host network

Host networking removes that container-side network namespace:

Application
    |
    v
Host network

For the right workload, that can be valuable.

The trade-off is the loss of network isolation.

One More Important Observation

Don’t interpret the example as:

“Host networking is faster, therefore always use it.”

That’s too simplistic.

The benefit depends on the workload, platform, and networking behavior of the application.

The correct decision is:

Do I need normal container network isolation?
        |
       Yes
        ↓
Use bridge networking

Do I specifically need the host network namespace?
        |
       Yes
        ↓
Consider host networking

The reason to choose host networking should be a concrete requirement, not simply the assumption that fewer networking layers must always be better.

Clean Up

Remove the bridge example:

docker container rm -f bridge-web

If the host-networked container is still running, remove it too:

docker container rm -f host-web

Your Docker host is now back to the state it was in before the experiment.

What You Should Remember

The entire exercise can be reduced to these two pictures.

Bridge

Browser
   |
Host :8080
   |
Port publishing
   |
Container :80

Host

Browser
   |
Host :80
   |
Container process

And the rule behind them:

Bridge networking gives the container its own network namespace. Host networking makes the container share the host’s network namespace.

Once that difference is clear, the behavior of ports, localhost, container IPs, and port conflicts all follows naturally.

What’s Next

We’ve now covered the three main single-host networking modes you’ll encounter:

bridge → normal isolation
host   → share the host network
none   → no network

Next, we’ll look at the shortest of the three: none networking.

It’s deliberately boring — and that’s exactly why it is useful.

Last updated on