Checkpoint Lab — Docker DNS, Service Discovery, Aliases, IPv4/IPv6, Custom Subnets, and Multi-Network Applications
Create and verify a front/back multi-network Docker application, prove DNS scope and isolation, record addressing evidence, and preserve explicit cleanup intent.
Learning objectives
- Build a front/back Compose topology in which an API is deliberately dual-homed while front and database services remain isolated.
- Record normalized Compose configuration, network IDs/IPAM, endpoint IPv4/IPv6 assumptions, resolver state, aliases, and container IDs before interpreting connectivity.
- Prove allowed discovery/application paths and prove that an unauthorized front-only service cannot resolve or reach the back-only database path.
-
Predict and verify important network-state changes rather than
treating
compose upas one undifferentiated success. - Produce an evidence packet and exact cleanup that bridge naturally to Chapter 19 port-publishing and host-exposure analysis.
1. Scenario and architecture
Build a disposable application with four services:
- frontend — front network only; can call the API but must not discover the database.
-
api — front and back networks; alias
apion front andapi-internalon back. -
database — back network only; alias
data; serves a synthetic HTTP response instead of a real database. - observer — front network only; used to prove the denied back-end path without changing the frontend.
flowchart LR
F[frontend front only] -->|api:8080| A[api front + back]
O[observer front only] -->|api:8080| A
A -->|data:9090| D[database back only]
F -. must not resolve/reach .-> D
O -. must not resolve/reach .-> D
2. Preflight and assumptions
docker version
docker info
docker context show
docker compose version || true
docker network ls
docker ps -a --no-trunc
# Record the lab image identity before use.
docker pull busybox:1.36.1
docker image inspect busybox:1.36.1 \
--format 'ID={{.Id}} RepoDigests={{json .RepoDigests}}'
mkdir -p da18-checkpoint/evidence
cd da18-checkpoint
docker version > evidence/docker-version.txt 2>&1
docker info > evidence/docker-info.txt 2>&1
docker context show > evidence/context.txt 2>&1
docker compose version > evidence/compose-version.txt 2>&1 || true
docker image inspect busybox:1.36.1 \
--format 'ID={{.Id}} RepoDigests={{json .RepoDigests}}' \
> evidence/image-identity.txt
Upstream reference baseline: Engine 29.8.1 and Compose v5.5.1 were current when this lesson was authored (2026-09-21). Your evidence files, not those reference versions, define the actual execution environment. No Buildx/BuildKit action is required in this chapter because the lab uses a prebuilt image; record those tools only if your academy-wide evidence policy requires them.
3. Predict state changes before execution
| Prediction | How you will verify it |
|---|---|
| Compose creates exactly two project networks, front and back. |
docker compose config,
docker network ls, project labels.
|
| API receives two endpoints; frontend/database/observer receive one each. |
docker compose ps -q +
docker inspect.
|
data resolves from API but not from
frontend/observer.
|
Bounded nslookup in each caller. |
| API can fetch database HTTP; frontend/observer cannot use the back-only path. |
wget results captured separately from lookup
results.
|
docker compose down removes project
containers/networks; image remains shared cache.
|
Post-cleanup filtered Docker inventory. |
4. Declare the exact Compose model
name: da18-checkpoint
services:
frontend:
image: busybox:1.36.1
command: ["sh", "-c", "sleep 3600"]
labels:
devops-academy.lab: ch18-checkpoint
networks:
front: {}
observer:
image: busybox:1.36.1
command: ["sh", "-c", "sleep 3600"]
labels:
devops-academy.lab: ch18-checkpoint
networks:
front: {}
api:
image: busybox:1.36.1
command:
- sh
- -c
- mkdir -p /www && echo api-ok >/www/index.html && httpd -f -p 8080 -h /www
labels:
devops-academy.lab: ch18-checkpoint
networks:
front:
aliases: [api]
back:
aliases: [api-internal]
database:
image: busybox:1.36.1
command:
- sh
- -c
- mkdir -p /www && echo db-ok >/www/index.html && httpd -f -p 9090 -h /www
labels:
devops-academy.lab: ch18-checkpoint
networks:
back:
aliases: [data]
networks:
front:
labels:
devops-academy.lab: ch18-checkpoint
back:
internal: true
labels:
devops-academy.lab: ch18-checkpoint
Save this as compose.yaml. No host ports are published;
the checkpoint tests service-to-service discovery only. Chapter 19
will deliberately add host exposure.
5. Normalize before execution
docker compose config > evidence/compose-normalized.yaml
docker compose config --services > evidence/services.txt
docker compose config --networks > evidence/networks.txt
cat evidence/services.txt
cat evidence/networks.txt
Expected services: frontend, observer,
api, database. Expected networks:
front, back. If the normalized model does
not match the design, stop here—do not debug runtime state for a
configuration that was never intended.
6. Reconcile the project and capture resource inventory
docker compose up -d
docker compose ps --all > evidence/compose-ps.txt
docker network ls --filter label=com.docker.compose.project=da18-checkpoint \
> evidence/project-networks.txt
docker network inspect da18-checkpoint_front \
> evidence/front-network.json
docker network inspect da18-checkpoint_back \
> evidence/back-network.json
for s in frontend observer api database; do
cid=$(docker compose ps -q "$s")
docker inspect "$cid" > "evidence/${s}-inspect.json"
done
Verify the API has entries for both project networks. Verify the database has only the back network and frontend/observer only the front network. Compose labels are evidence of project ownership; network IDs are the exact daemon objects.
7. Capture resolver and alias evidence
docker compose exec -T frontend cat /etc/resolv.conf \
> evidence/frontend-resolv.conf
docker compose exec -T api cat /etc/resolv.conf \
> evidence/api-resolv.conf
# Allowed discovery.
docker compose exec -T frontend nslookup api \
> evidence/frontend-lookup-api.txt 2>&1
docker compose exec -T api nslookup data \
> evidence/api-lookup-data.txt 2>&1
docker compose exec -T database nslookup api-internal \
> evidence/database-lookup-api-internal.txt 2>&1
# Denied discovery: preserve exit/output without aborting the lab.
docker compose exec -T frontend nslookup data \
> evidence/frontend-lookup-data-denied.txt 2>&1 || true
docker compose exec -T observer nslookup data \
> evidence/observer-lookup-data-denied.txt 2>&1 || true
The denied files are successful security/isolation evidence when they show that front-only callers cannot discover the back-only name.
8. Prove allowed and denied application paths
docker compose exec -T frontend wget -qO- http://api:8080/ \
| tee evidence/frontend-to-api.txt
docker compose exec -T api wget -qO- http://data:9090/ \
| tee evidence/api-to-data.txt
# Expected denial/failure from front-only observer.
docker compose exec -T observer wget -T 2 -qO- http://data:9090/ \
> evidence/observer-to-data-denied.txt 2>&1 || true
Expected allowed outputs are api-ok and
db-ok. The denied path must not be “repaired” by
joining the observer to the back network; it proves the intended
architecture.
9. Optional IPv6 evidence, without changing checkpoint success criteria
The mandatory checkpoint is IPv4 and works on standard user-defined networks. If your Linux Docker daemon supports IPv6 and your environment permits a local ULA network, create a separate optional test network after the main checkpoint, capture its IPAM and endpoint addresses, and remove it afterward. Do not alter the production-style checkpoint topology or daemon configuration merely to obtain IPv6 evidence.
# Optional capability-gated exercise, outside the Compose project:
docker network create --ipv6 \
--subnet fd00:da:18:5::/64 \
--label devops-academy.lab=ch18-checkpoint \
da18-checkpoint-v6
docker network inspect da18-checkpoint-v6 \
> evidence/optional-ipv6-network.json
docker network rm da18-checkpoint-v6
10. Evidence packet checklist
- Installed Engine/CLI/Compose version and active context.
- BusyBox local image ID and recorded repository digest when available.
- Normalized Compose model and service/network list.
- Compose project container IDs/states.
- Front/back network IDs, drivers, IPAM, labels, and endpoint inventories.
- API dual-network endpoint addresses and aliases; single-network evidence for other services.
- Frontend/API resolver files.
- Allowed and denied name-resolution outputs.
- Allowed and denied application-connection outputs.
- Optional IPv6 capability/result note, if attempted.
-
An
assumptions.txtrecording host OS/Desktop boundary, custom DNS/VPN conditions, and why no host ports were published.
cat > evidence/assumptions.txt <<'EOF'
Chapter 18 checkpoint assumptions:
- Local disposable Docker daemon/context only.
- No production networks, credentials, registries, or endpoints used.
- No host ports published; Chapter 19 handles host exposure.
- Docker embedded DNS/service discovery is tested only within declared project networks.
- IPv6 is optional and capability-gated; external IPv6 routing is not assumed.
- Endpoint IPs are evidence, not durable service identities.
EOF
tar -czf da18-evidence.tgz evidence compose.yaml
ls -lh da18-evidence.tgz
11. Cleanup and rollback
# Remove this Compose project's containers and project networks.
# There are no named volumes in this checkpoint.
docker compose down
# Defensive cleanup of the optional exact network only, if it remains.
docker network rm da18-checkpoint-v6 2>/dev/null || true
# Verify project/lab resources are gone.
docker ps -a --filter label=com.docker.compose.project=da18-checkpoint
docker network ls --filter label=com.docker.compose.project=da18-checkpoint
docker network ls --filter label=devops-academy.lab=ch18-checkpoint
# Keep da18-evidence.tgz for review. Do not prune unrelated Docker state.
12. What Chapter 18 adds to the production operating model
You can now prove service discovery as a chain: declared network membership → scoped service name/alias → resolver evidence → current endpoint allocation → application connection. You can segment a multi-network application without relying on container IPs, document custom IPAM decisions, and treat IPv6 as an explicit capability/routing requirement rather than a checkbox.
The next chapter adds the boundary we intentionally avoided here: exposing container services through host addresses and ports. That introduces NAT/direct routing, firewall interaction, host binding, and exposure-security decisions.
Knowledge check
The frontend can resolve api but not
data. Is the checkpoint broken?
No. That is the intended policy: frontend shares the front network with API, while data is scoped to the back network.
What proves the API is dual-homed?
Its container inspect evidence shows two
NetworkSettings.Networks entries with separate
endpoints/addresses and network-scoped aliases.
Why capture docker compose config before
up?
It proves the normalized declarative model first, separating configuration mistakes from runtime networking failures.
What is the correct response if optional IPv6 creation is unsupported?
Record the capability/limitation and continue. The mandatory checkpoint does not require daemon mutation or public IPv6.
A developer asks to publish the database port to make the frontend test easier. What should you say?
Do not add host exposure to bypass intended network isolation. Test through the intended API path; host publication is a separate security decision covered in Chapter 19.
Official references and version notes
-
Docker Docs — Networking overview
— resolver behavior, custom-network embedded DNS, and
127.0.0.11. - Docker Docs — Bridge network driver — user-defined bridge isolation and automatic name/alias resolution.
- Docker Docs — docker network connect — endpoint attachment and network-scoped aliases.
- Docker Docs — Networking in Compose — project networks and service-name discovery.
- Compose Specification — service network aliases — aliases are scoped to the network on which they are declared.
-
Compose Specification — networks
— IPAM,
enable_ipv4,enable_ipv6, internal/external networks, and custom names. - Docker Docs — IPv6 networking — Linux-daemon support, IPv6 network creation, ULA allocation, and Compose examples.
- Docker Engine 29 release notes — current Engine behavior and networking fixes.
Docker Engine 29.8.1 (released 2026-09-15) is the current Engine 29 release in the primary release notes, and Docker Compose v5.5.1 is the current upstream Compose release. The runnable labs deliberately record your Engine/CLI/Compose versions and context because DNS, IPv6, Desktop networking, firewall integration, and helper-tool availability vary by platform. The mandatory path uses only local disposable networks and containers; IPv6 is an optional capability-gated extension.
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.