Checkpoint Lab — Container Networking Foundations: Bridge, Host, None, User-Defined Networks, Endpoints, and Namespaces
Construct two isolated bridge networks with one dual-homed test container, capture endpoint and routing evidence, and prove exactly which communication paths exist without enabling forwarding.
Learning objectives
- Build two labeled, isolated user-defined bridge networks and record their exact IDs/IPAM state before container creation.
- Create one service on each network plus a dual-homed test container without enabling IP forwarding or privileged behavior.
- Predict and verify which direct communication paths should succeed and which should fail.
- Capture container IDs, endpoint IDs, per-network IP/MAC/gateway data, routes, DNS, image identity, Engine/context assumptions, and application evidence.
- Clean up only exact checkpoint resources and bridge naturally to Chapter 18 service discovery, aliases, IP versions, custom subnets, and multi-network identity.
1. Setup and assumptions
Create a local evidence directory and record versions first. The mandatory path works on Docker Engine/Linux and Docker Desktop with ordinary bridge networking. Host networking, cloud registries, external DNS, and paid capabilities are not required.
mkdir -p da-network17-checkpoint/evidence
cd da-network17-checkpoint
docker version > evidence/docker-version.txt
docker info > evidence/docker-info.txt
docker context show > evidence/docker-context.txt
docker compose version > evidence/compose-version.txt 2>&1 || true
docker buildx version > evidence/buildx-version.txt 2>&1 || true
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
Assumptions to write down: Engine/Desktop version, OS/context, bridge driver availability, no production containers using the checkpoint names, and no need to alter daemon/firewall configuration.
2. Create two isolated network objects
The networks are “isolated” from each other by separate user-defined bridge membership. We intentionally let Docker choose non-overlapping subnets so the lab does not collide with an unknown host VPN/LAN.
docker network create --driver bridge --label devops-academy.lab=network17-checkpoint da-net17-left
docker network create --driver bridge --label devops-academy.lab=network17-checkpoint da-net17-right
docker network inspect da-net17-left > evidence/left.empty.json
docker network inspect da-net17-right > evidence/right.empty.json
3. Predict state changes before containers exist
-
Prediction A:
left-servicewill have one endpoint only onda-net17-left;right-servicewill have one endpoint only onda-net17-right. -
Prediction B:
dual-testwill have two endpoints, one address/gateway context per network, while keeping a single container ID/PID 1. -
Prediction C:
dual-testcan reach each service by its network-scoped name because it is a member of both networks. -
Prediction D:
left-servicecannot directly resolve/reachright-service, because they share no network and we do not enable routing throughdual-test. - Prediction E: no host port is published and no daemon/firewall setting changes.
4. Create one service per network plus a dual-homed tester
docker run -d \
--name da-net17-left-service \
--network da-net17-left \
--label devops-academy.lab=network17-checkpoint busybox:1.36.1 sh -c 'mkdir -p /www; echo left > /www/index.html; exec httpd -f -p 8080 -h /www'
docker run -d \
--name da-net17-right-service \
--network da-net17-right \
--label devops-academy.lab=network17-checkpoint busybox:1.36.1 sh -c 'mkdir -p /www; echo right > /www/index.html; exec httpd -f -p 8080 -h /www'
docker run -d --name da-net17-dual-test --network da-net17-left --label devops-academy.lab=network17-checkpoint busybox:1.36.1 sleep 3600
docker network connect da-net17-right da-net17-dual-test
5. Capture endpoint, route, DNS, and identity evidence
docker inspect da-net17-left-service --format '{{json .NetworkSettings.Networks}}' > evidence/left-service.networks.json
docker inspect da-net17-right-service --format '{{json .NetworkSettings.Networks}}' > evidence/right-service.networks.json
docker inspect da-net17-dual-test --format '{{json .NetworkSettings.Networks}}' > evidence/dual-test.networks.json
docker inspect da-net17-dual-test --format 'id={{.Id}} image={{.Image}} pid={{.State.Pid}} status={{.State.Status}}' > evidence/dual-test.identity.txt
docker exec da-net17-dual-test ip addr > evidence/dual-test.ip.txt
docker exec da-net17-dual-test ip route > evidence/dual-test.routes.txt
docker exec da-net17-dual-test cat /etc/resolv.conf > evidence/dual-test.resolver.txt
docker network inspect da-net17-left > evidence/left.with-endpoints.json
docker network inspect da-net17-right > evidence/right.with-endpoints.json
Review the evidence before testing connectivity. Confirm the dual-homed container has two network entries and two address contexts. This proves membership; it does not prove forwarding between the networks.
6. Verify the predicted communication matrix
# These two should succeed:
docker exec da-net17-dual-test wget -qO- http://da-net17-left-service:8080/ | tee evidence/dual-to-left.txt
docker exec da-net17-dual-test wget -qO- http://da-net17-right-service:8080/ | tee evidence/dual-to-right.txt
# Left service should not resolve/reach right service directly:
docker exec da-net17-left-service sh -c 'wget -qO- -T 2 http://da-net17-right-service:8080/ || true' > evidence/left-to-right.expected-failure.txt 2>&1
# Right service should not resolve/reach left service directly:
docker exec da-net17-right-service sh -c 'wget -qO- -T 2 http://da-net17-left-service:8080/ || true' > evidence/right-to-left.expected-failure.txt 2>&1
# No host publication should exist:
docker port da-net17-left-service > evidence/left.published-ports.txt
docker port da-net17-right-service > evidence/right.published-ports.txt
The success/failure pattern is the core checkpoint result. The
dual-homed test container can initiate connections to both networks
because it owns endpoints on both. The two single-homed services
remain isolated from each other because there is no shared network
and we did not configure dual-test as a forwarding
router.
7. Evidence packet checklist
| Evidence | Why it matters |
|---|---|
| Docker version/info/context | Pins platform, daemon, client, and context assumptions. |
| BusyBox image ID + RepoDigest | Pins lab image identity separately from network state. |
| Left/right network IDs + IPAM | Pins exact network objects and gateways/subnets. |
| All three container IDs | Pins endpoint ownership to concrete container objects. |
Per-container NetworkSettings.Networks |
Shows single- versus dual-homed endpoint sets. |
| Dual-test interfaces/routes/resolver | Proves container-visible stack after second attachment. |
| Successful dual→left/right HTTP responses | Proves intended application-level connectivity. |
| Expected left↔right failures | Proves isolation rather than merely assuming it. |
| Published-port evidence | Proves host exposure was not part of the checkpoint. |
| Assumptions/limitations note | Records Desktop/native Linux/firewall-backend differences without mutating them. |
Create the limitations note:
cat > evidence/ASSUMPTIONS.txt <<'EOF'
Lab: Docker Chapter 17 checkpoint
Baseline checked: 2026-09-21
Mandatory network mode: user-defined bridge only
No host port publication, daemon mutation, firewall edit, privileged mode, or IP forwarding enabled
Dual-homed container is a test endpoint, not a router
Docker Desktop may implement host/bridge internals behind a managed VM; Engine API/container evidence is authoritative for this lab
Engine 29 nftables backend is experimental; this lab does not change firewall backend
EOF
8. Verification checklist
- Two labeled bridge network objects exist with distinct IDs/IPAM ranges.
- Left and right services each have exactly one intended endpoint.
- Dual-test has endpoints on both networks and remains one container/process object.
- Dual-test reaches both service names over their respective networks.
- Left and right services cannot directly reach each other by name.
- No published host ports exist.
- No firewall, daemon, routing-forwarding, or privilege setting was changed.
- All image/network/container IDs and timestamps are retained before cleanup.
9. Cleanup and rollback
docker rm -f da-net17-left-service da-net17-right-service da-net17-dual-test 2>/dev/null || true
docker network rm da-net17-left da-net17-right 2>/dev/null || true
# Verify checkpoint ownership is gone:
docker ps -a --filter label=devops-academy.lab=network17-checkpoint
docker network ls --filter label=devops-academy.lab=network17-checkpoint
# Keep evidence/ for review.
No broad prune is needed. The image can remain cached because it may be shared by other labs; delete it only after separately proving no dependent container requires it.
10. What Chapter 17 adds to the production operating model
You can now represent connectivity as evidence: exact Docker network object, endpoint membership, container-visible addresses/routes/DNS, host/platform assumptions, and application-level proof. That makes network intent reviewable and prevents “fixes” that flatten trust boundaries or expose ports unnecessarily.
11. Bridge to Chapter 18
Chapter 17 treated basic network membership and namespace/endpoint mechanics. Chapter 18 builds on that foundation with Docker DNS, service discovery aliases, IPv4/IPv6, custom subnets, and multi-network application identity. Keep one rule: network membership creates the scope in which names, aliases, and addresses have meaning.
Knowledge check
Why can the dual-test container reach both services?
It has one endpoint on each user-defined bridge, so it participates in both network-scoped DNS/connectivity domains.
Why can left-service not reach right-service even though dual-test is attached to both?
The services share no network, and merely multi-homing dual-test does not enable IP forwarding/routing between its interfaces.
What evidence proves this checkpoint did not test host exposure?
The services have no published ports, and the successful tests originate from a container peer on the corresponding user-defined bridge.
Why record image identity in a networking checkpoint?
It prevents a workload/image change from being confused with a network-state change and preserves the full causal evidence chain.
What Chapter 18 concept depends directly on Chapter 17 network membership?
Network-scoped DNS names/aliases and multi-network identities only make sense relative to the networks/endpoints a container actually owns.
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.