Chapter 17Lesson 02~145 minutes

Container Networking Foundations: Bridge, Host, None, User-Defined Networks, Endpoints, and Namespaces: Guided Hands-On Workflow and Core Operations

Build disposable user-defined bridge networks, inspect endpoint/IP/route/DNS state, connect and disconnect a second network, and compare bridge, host, and none modes safely.

User-defined bridgeDNSRoutesConnect/disconnectIsolation

Learning objectives

  • Inspect built-in Docker networks before creating any lab resource.
  • Create a labeled user-defined bridge and prove same-network name resolution, endpoint addressing, routes, and DNS.
  • Connect and disconnect a second user-defined network while tracking the container's multiple endpoint identities.
  • Prove isolation between unrelated user-defined bridges without publishing ports or altering firewall policy.
  • Compare bridge, none, and host modes safely, treating host mode as optional when platform support is absent.
Lab boundary. Everything uses local disposable networks/containers labeled devops-academy.lab=network17. No daemon configuration, firewall edits, privileged containers, host namespace mounts, Docker socket mounts, external registry, or production endpoint is required.

1. Preflight and baseline evidence

Record the exact client/daemon/context before interpreting network behavior. The commands below use BusyBox 1.36.1 as a small lab image; after pulling it, record the repository digest so the human tag and resolved content identity are both retained.

mkdir -p da-network17/evidence
cd da-network17

docker version > evidence/docker-version.txt
docker info > evidence/docker-info.txt
docker context show > evidence/docker-context.txt
docker network ls > evidence/networks.before.txt

docker pull busybox:1.36.1
docker image inspect busybox:1.36.1   --format 'id={{.Id}} repodigests={{json .RepoDigests}}'   > evidence/busybox.identity.txt

docker network inspect bridge > evidence/default-bridge.json
docker network inspect host > evidence/host-network.json
docker network inspect none > evidence/none-network.json

2. Create one user-defined bridge with explicit ownership

docker network create changes daemon network-object state. The label gives cleanup a narrow ownership guard. Let Docker choose a non-overlapping subnet unless your environment requires explicit IPAM.

docker network create   --driver bridge   --label devops-academy.lab=network17   da-net17-main

docker network inspect da-net17-main > evidence/main.network.json

Inspect the JSON before starting containers. Record the driver, network ID, subnet, gateway, options, and labels. A newly created bridge has no application endpoint yet.

3. Attach a server and client; prove DNS and routes

The server writes only synthetic content into its own writable layer and starts BusyBox HTTP on port 8080. Nothing is published to the host. The client joins the same user-defined bridge and can therefore resolve the server name through Docker embedded DNS.

docker run -d \
  --name da-net17-server \
  --network da-net17-main \
  --label devops-academy.lab=network17   busybox:1.36.1   sh -c 'mkdir -p /www; echo network17-ok > /www/index.html; exec httpd -f -p 8080 -h /www'

docker run -d   --name da-net17-client   --network da-net17-main   --label devops-academy.lab=network17   busybox:1.36.1 sleep 3600

docker exec da-net17-client wget -qO- http://da-net17-server:8080/
docker exec da-net17-client ip addr
docker exec da-net17-client ip route
docker exec da-net17-client cat /etc/resolv.conf

docker inspect da-net17-server --format '{{json .NetworkSettings.Networks}}'   > evidence/server.networks.json
docker inspect da-net17-client --format '{{json .NetworkSettings.Networks}}'   > evidence/client.networks.main.json
docker network inspect da-net17-main > evidence/main.with-endpoints.json

Expected evidence: both containers have endpoints on da-net17-main; their IP addresses belong to that bridge subnet; the client has a route through the bridge gateway; and custom-network DNS uses Docker's embedded resolver. The HTTP request proves application listening plus DNS plus same-network reachability without any host publication.

4. Add a second endpoint, then remove it

Connecting a running container to another network changes its endpoint set, not its image and not its PID 1. This is a useful demonstration of multi-homing.

docker network create   --driver bridge   --label devops-academy.lab=network17   da-net17-extra

docker network connect da-net17-extra da-net17-client

docker inspect da-net17-client --format '{{json .NetworkSettings.Networks}}'   > evidence/client.networks.two.json
docker exec da-net17-client ip addr > evidence/client.ip.two.txt
docker exec da-net17-client ip route > evidence/client.routes.two.txt

docker network disconnect da-net17-extra da-net17-client

docker inspect da-net17-client --format '{{json .NetworkSettings.Networks}}'   > evidence/client.networks.after-disconnect.json

Compare the three endpoint snapshots. The container ID should remain the same while network membership changes. That separates daemon network attachment state from container object identity and process identity.

5. Prove unrelated user-defined bridges are isolated

docker network create   --driver bridge   --label devops-academy.lab=network17   da-net17-isolated

docker run -d \
  --name da-net17-isolated-server \
  --network da-net17-isolated \
  --label devops-academy.lab=network17   busybox:1.36.1   sh -c 'mkdir -p /www; echo isolated > /www/index.html; exec httpd -f -p 8080 -h /www'

# This should fail because the name is not in the client's network-scoped DNS view:
docker exec da-net17-client sh -c   'ping -c 1 -W 1 da-net17-isolated-server >/tmp/isolation.txt 2>&1; rc=$?; cat /tmp/isolation.txt; exit $rc'   || true

docker network inspect da-net17-isolated > evidence/isolated.network.json

The failed lookup/reachability is expected policy evidence, not an error to “fix.” Do not join every service to one flat network merely to make a test pass. Network membership is part of least privilege.

6. Compare the none driver

docker run --rm --network none busybox:1.36.1 sh -c '
  echo "== links =="; ip link;
  echo "== addresses =="; ip addr;
  echo "== routes =="; ip route || true;
  echo "== resolver =="; cat /etc/resolv.conf || true
' > evidence/none-container.txt

Docker's current none driver documentation describes a container stack with only loopback. The point is not “broken networking”; it is explicit absence of network connectivity.

7. Optional host-network comparison

Do this only if the platform supports host networking. Linux Engine supports it directly. Docker Desktop 4.34+ requires the feature to be enabled and implements it with Desktop-specific limitations. If unsupported, record “not available” and skip—the learning objective is the design distinction, not forcing a host mutation.

# Optional capability check / comparison:
docker run --rm --network host busybox:1.36.1 sh -c '
  echo "== addresses =="; ip addr;
  echo "== routes =="; ip route
' > evidence/host-mode.txt 2>&1 || true

Do not combine host networking with -p: host mode has no separate container IP/network namespace for publishing to map, so publication options are ignored.

8. Challenge: choose the failing layer

A web container is healthy and responds to wget http://127.0.0.1:8080 from inside itself. A client container cannot resolve the web container by name. Both are running. Which layer should you inspect first?

Answer path: inspect each container's NetworkSettings.Networks and the intended Docker network object. The application listener is already proven locally; this is most likely endpoint/network membership or network-scoped DNS, not an image rebuild or published-port problem.

9. Exact cleanup

docker rm -f   da-net17-server   da-net17-client   da-net17-isolated-server 2>/dev/null || true

docker network rm   da-net17-main   da-net17-extra   da-net17-isolated 2>/dev/null || true

# Verify only this lab's resources are gone:
docker ps -a --filter label=devops-academy.lab=network17
docker network ls --filter label=devops-academy.lab=network17

The cleanup removes exact named disposable resources only. There is no need for global network/system pruning.

Next lesson

Next: Configuration, Design Choices, and Tradeoffs

Turn the lab observations into design decisions: when to use user-defined bridge, host, none, internal networks, multiple attachments, or static addressing, and what evidence each choice requires.

Knowledge check

Why did the client reach the server without publishing port 8080 to the host?

What changed when docker network connect added da-net17-extra?

Why is failure to resolve the isolated server an expected result?

What should a none-network container show?

If host mode fails on Docker Desktop, should the learner change daemon/firewall policy to force it?

Official references and version notes

Version baseline checked 2026-09-21.

Docker Engine 29.8.1 is the current Engine release baseline used for version-sensitive discussion. Docker Engine on Linux uses iptables by default for bridge-network firewall rules; the nftables backend introduced in Engine 29 remains experimental. Docker Desktop host networking is supported from Desktop 4.34+ as an opt-in feature and operates at layer 4. Always record the installed Engine/Desktop version and actual network/firewall state before drawing conclusions.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.