Lab: Docker Networking¶
Pairs with: Docker Networking Fundamentals
Environment: Any host with Docker installed. An equivalent docker-compose.yml is shown below if you prefer Compose over the raw docker commands.
docker-compose.yml (optional)
services:
web:
image: nginx:1.27-alpine
networks:
- lab_net
web2:
image: nginx:1.27-alpine
ports:
- "8080:80"
networks:
lab_net:
driver: bridge
The lab itself is written around the raw docker CLI so each step (explicit network creation, explicit lack of one) stays visible; both forms give the same networking behavior.
Starting conditions¶
- Docker installed and running (
docker psworks without error). - No containers or networks from this lab already present (run
docker network lsto confirm a clean baseline).
Instructions¶
Part 1 — Prove name resolution requires network membership, not just "Docker is running"¶
docker network create lab_net
docker run -d --name web --network lab_net nginx
docker run -it --rm --name tester --network lab_net alpine sh -c "wget -qO- http://web || echo FAILED"
Then, without --network lab_net:
Part 2 — Prove -p is NAT, not a direct bind, and that it bypasses host firewall rules you might expect to apply¶
docker run -d --name web2 -p 8080:80 nginx
sudo ufw deny 8080/tcp 2>/dev/null || echo "(ufw not installed, skip this specific check)"
curl -i http://localhost:8080/
Expected results¶
- Part 1:
tester(onlab_net) succeeds —wgetresolveswebby name and gets nginx's default page.outsider(not onlab_net) fails with a DNS resolution error — the namewebmeans nothing outside that specific network's embedded DNS. - Part 2: even with a
ufw deny 8080/tcprule in place,curlagainst the published port still succeeds — demonstrating that Docker's own iptables/nftables rules for published ports are evaluated independently ofufw's rules, which only govern the standardINPUTchain, not theDOCKER/DOCKER-USERchains Docker itself manages.
Diagnosis checklist¶
- [ ] Did you confirm
outsider's failure is specifically a DNS resolution failure (the namewebdoesn't resolve), not a connection-refused or timeout — this is the signal that it's a network-membership issue, not a reachability issue at the IP level? - [ ] Did you verify the
ufwrule was actually in place (ufw status) before concluding it had no effect, rather than assuming? - [ ] Can you explain why
ufw's rule doesn't apply — specifically, which iptables/nftables chain Docker inserts its own NAT rules into, and how that relates to chain evaluation order?
Success criteria¶
You can explain to someone else, using this lab's own output as evidence, why "I set a firewall rule to block this Docker port and it didn't work" is a frequently-reported, genuinely confusing but fully explainable behavior — not a Docker bug.
Cleanup / rollback¶
docker rm -f web web2 2>/dev/null
docker network rm lab_net 2>/dev/null
sudo ufw delete deny 8080/tcp 2>/dev/null || true
Confirm with docker network ls and docker ps -a that no lab containers or networks remain before considering the environment cleaned up.