Chapter 19Lesson 05~155 minutes

Checkpoint Lab — Port Publishing, NAT, Firewall Interaction, Direct Routing, Host Binding, and Exposure Security

Produce an exposure matrix for one service through internal-only, loopback-published, and all-interface-published states, then restore the safest local-only state with an evidence packet.

Checkpoint labExposure matrixEvidenceRollbackReproducibility

Learning objectives

  • Predict and verify container listener, Docker publish, host bind, and client-path changes across three controlled exposure states.
  • Capture an evidence packet containing versions/context, image/container identity, port mappings, host-path observations, and assumptions.
  • Demonstrate the difference between internal-only service availability, loopback-only host access, and broader host-interface publication.
  • Use optional read-only firewall/routing evidence without making host policy changes.
  • Finish by restoring the safest local-only state and bridging the operating model to persistent data in Chapter 20.
Checkpoint objective. Produce an evidence-backed exposure matrix for one service. The final state must be loopback-only. If your environment is not safe for a brief all-interface test, document that constraint and simulate the matrix from Docker mapping evidence rather than opening the service to an uncontrolled network.

1. Workspace, evidence directory, and preflight

mkdir -p da19-checkpoint/evidence
cd da19-checkpoint

{
  date -Iseconds
  docker version
  docker info
  docker context show
  docker compose version || true
  docker buildx version || true
} > evidence/platform.txt 2>&1

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

docker ps -a --filter label=devops-academy.lab=ch19-checkpoint   > evidence/preexisting-lab-resources.txt

2. Write predictions before execution

Record at least these predictions in evidence/predictions.txt before starting containers:

  • Prediction A: internal-only service responds inside the container but has no docker port mapping and no host URL.
  • Prediction B: loopback publication creates a HostIp of 127.0.0.1 and the host can request the service at the chosen high port.
  • Prediction C: all-interface publication records an unspecified/all-interface HostIp and may permit authorized peer access depending on host/network policy.
  • Prediction D: after rollback to loopback-only, the broader mapping no longer exists.
cat > evidence/predictions.txt <<'EOF'
A. Internal-only: app works inside container; no host mapping exists.
B. Loopback: HostIp is 127.0.0.1; localhost request succeeds.
C. All-interface: mapping is broader; peer result depends on authorized host/network policy.
D. Final rollback: only loopback publication remains.
EOF

3. State 1 — internal-only

docker run -d \
  --name da19-cp-internal \
  --label devops-academy.lab=ch19-checkpoint   busybox:1.36.1 sh -c   'mkdir -p /www; echo state-internal >/www/index.html; exec httpd -f -p 8080 -h /www'

docker exec da19-cp-internal wget -qO- http://127.0.0.1:8080/   | tee evidence/state1-internal-response.txt

docker port da19-cp-internal > evidence/state1-docker-port.txt
docker inspect da19-cp-internal > evidence/state1-inspect.json

Verify state1-docker-port.txt is empty. This is not a failure: the checkpoint intentionally proves that internal service availability does not imply host exposure.

4. State 2 — loopback publication

Use host port 18280 unless it is already occupied; record any substitution. Keep state 1 running so the evidence shows separate objects, not a mutation hidden in history.

docker run -d \
  --name da19-cp-loopback \
  --label devops-academy.lab=ch19-checkpoint   -p 127.0.0.1:18280:8080   busybox:1.36.1 sh -c   'mkdir -p /www; echo state-loopback >/www/index.html; exec httpd -f -p 8080 -h /www'

docker port da19-cp-loopback | tee evidence/state2-docker-port.txt
docker inspect da19-cp-loopback > evidence/state2-inspect.json
curl -fsS http://127.0.0.1:18280/ | tee evidence/state2-host-response.txt

ss -lnt 2>/dev/null | grep ':18280 ' > evidence/state2-host-socket.txt || true

5. State 3 — controlled all-interface publication

Safety gate: perform this only on a trusted/disposable host. If the machine is on an uncontrolled LAN or public interface, skip the runtime creation and write SKIPPED: unsafe environment to the evidence file. You can still explain the expected Docker mapping from the documented semantics.

docker run -d \
  --name da19-cp-all \
  --label devops-academy.lab=ch19-checkpoint   -p 18281:8080   busybox:1.36.1 sh -c   'mkdir -p /www; echo state-all >/www/index.html; exec httpd -f -p 8080 -h /www'

docker port da19-cp-all | tee evidence/state3-docker-port.txt
docker inspect da19-cp-all > evidence/state3-inspect.json
curl -fsS http://127.0.0.1:18281/ | tee evidence/state3-host-response.txt

If an authorized second host exists, test the Docker host's LAN address on port 18281 and record success/failure plus the peer identity/trust zone. Do not weaken host firewall policy merely to make the peer test pass.

6. Optional native-Linux packet-filter evidence

# Optional/read-only and often requires administrative authorization:
sudo iptables -t nat -S 2>/dev/null | grep -E 'DOCKER|1828'   > evidence/iptables-nat.txt || true
sudo iptables -S 2>/dev/null | grep -E 'DOCKER|1828'   > evidence/iptables-filter.txt || true
sudo nft list ruleset 2>/dev/null | grep -E 'docker|1828'   > evidence/nftables.txt || true

For Docker Desktop, replace missing native-Linux rule evidence with a note that the Desktop backend/VM owns forwarding. Docker mappings and host/client tests remain valid evidence.

7. Build the exposure matrix

State Internal response Docker HostIp Host response Authorized peer Expected security meaning
Internal only Success None No mapped URL No Service exists only on Docker network namespace/path.
Loopback Success 127.0.0.1 Success Normally no direct LAN path in current NAT semantics Local-host development/admin boundary.
All interfaces Success Unspecified/all interfaces Success Environment-dependent; test only if authorized Broader host exposure requiring host/network policy.

Fill the matrix with your actual evidence filenames and observed values. Do not replace failed observations with expected answers; discrepancies are the most valuable checkpoint data.

8. Restore the safest local-only state

The final intended state is one loopback-published container. Remove the broader all-interface container and the internal-only comparison container, then verify only the loopback lab object remains.

docker rm -f da19-cp-all da19-cp-internal 2>/dev/null || true

docker ps --filter label=devops-academy.lab=ch19-checkpoint   > evidence/final-resources.txt
docker port da19-cp-loopback | tee evidence/final-loopback-mapping.txt
curl -fsS http://127.0.0.1:18280/ | tee evidence/final-loopback-response.txt

If you skipped state 3, the rollback command remains safe because it targets only the exact disposable name.

9. Evidence packet checklist

  • Engine/CLI/Compose/Buildx versions, active context, host/Desktop assumption.
  • BusyBox image ID and RepoDigest when available.
  • Three container IDs/inspect records for attempted states.
  • In-container application response proving listener health.
  • docker port and inspect mapping for each state.
  • Host HTTP response for loopback/all-interface states.
  • Optional host socket and firewall/NAT rule snapshots.
  • Optional authorized peer result, or explicit reason it was skipped.
  • Predictions versus observations table.
  • Final resource inventory and final loopback mapping.
  • Assumptions/limitations note covering firewall, VPN, Desktop VM, and route environment.
cat > evidence/assumptions.txt <<'EOF'
Chapter 19 checkpoint assumptions:
- Disposable local Docker resources only.
- No production endpoints or credentials.
- Host firewall/daemon settings were not changed.
- All-interface testing was performed only if the host network was trusted.
- Direct-routing gateway modes were studied but not enabled by the mandatory lab.
- Docker Desktop host forwarding may differ from native Linux rule visibility.
EOF

tar -czf da19-evidence.tgz evidence
ls -lh da19-evidence.tgz

10. Final cleanup after evidence review

After confirming the evidence archive exists, remove the final loopback container. Keep the evidence archive if you want to compare future Docker versions or host configurations.

docker rm -f da19-cp-loopback 2>/dev/null || true
docker ps -a --filter label=devops-academy.lab=ch19-checkpoint

# Do not delete unrelated images/networks/caches.

11. What Chapter 19 adds to the production operating model

You can now separate service health from exposure, express host-binding scope deliberately, prove exact publish mappings, understand where NAT/firewall/direct-routing behavior sits in the packet path, and diagnose exposure failures without destructive host changes. Most importantly, you can recognize accidental broad publication as a declarative security bug rather than “a firewall problem.”

Chapter 20 moves from network exposure to data persistence. The same evidence discipline applies: container writable state, named-volume identity, mount ownership, backup/restore artifacts, and cleanup intent must be proven independently.

Next lesson

Next: Volumes, Named Volumes, Volume Drivers, Backup/Restore, Sharing, and Persistent Data Patterns

Carry forward the habit of separating declaration, daemon object state, host implementation, and externally observed behavior. Chapter 20 applies that same model to persistent storage and backup/restore.

Knowledge check

Why does the checkpoint keep internal-only and loopback containers as separate objects?

What should you do if an all-interface step is unsafe on the current network?

What is the required final exposure state?

If localhost works but an authorized LAN peer fails, should you rebuild the image?

What is the key distinction between EXPOSE and -p?

Official references and version notes

Version baseline, verified 2026-09-21.

Docker Engine 29.8.1 is the current Engine 29 release. On Linux, Docker uses iptables by default and the Engine 29 nftables backend remains experimental. Docker Desktop implements host exposure through its managed VM/backend and can differ from native Linux host rule inspection. The labs therefore make Docker API/container-visible evidence mandatory and host firewall inspection optional/read-only.

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.