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.
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.
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.
Knowledge check
Why did the client reach the server without publishing port 8080 to the host?
Both endpoints were on the same user-defined bridge, where direct container-to-container connectivity is available. Host publication is a separate exposure mechanism.
What changed when docker network connect added
da-net17-extra?
The running container gained another network endpoint/interface/address/route set. Its image and container ID did not need to change.
Why is failure to resolve the isolated server an expected result?
Docker DNS/service discovery is network-scoped and unrelated user-defined bridges are isolated by design.
What should a none-network container show?
An isolated network stack with loopback only and no normal external connectivity.
If host mode fails on Docker Desktop, should the learner change daemon/firewall policy to force it?
No. Record the version/feature limitation and skip the optional comparison; the mandatory path is bridge/none and does not require platform mutation.
Official references and version notes
- Docker Docs — Networking overview: container-visible interfaces, routes, gateways, DNS, and built-in drivers.
- Docker Docs — Bridge network driver: default versus user-defined bridges, DNS, isolation, masquerading, and dynamic connect/disconnect.
- Docker Docs — Host network driver: shared host networking, ignored port publishing, Linux support, and Docker Desktop limitations.
- Docker Docs — None network driver: isolated network stack with loopback only.
-
Docker CLI —
docker network create: bridge creation,--internal, IPAM, labels, and network scope. - Docker Docs — Packet filtering and firewalls: firewall rules for bridge networks and backend selection.
-
Docker Docs — Docker with iptables: current iptables rule ownership and
DOCKER-USERbehavior. - Docker Docs — Docker with nftables: Engine 29 experimental nftables backend and migration caveats.
-
Docker Desktop networking how-tos: VM-boundary networking and
host.docker.internal. - Docker Engine 29 release notes: current Engine 29 networking changes and compatibility notes.
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.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.