Chapter 18Lesson 05~150 minutes

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.

Checkpoint labComposeIsolationDNS evidenceReproducibility

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 up as one undifferentiated success.
  • Produce an evidence packet and exact cleanup that bridge naturally to Chapter 19 port-publishing and host-exposure analysis.
Checkpoint contract. The lab is complete only when the normalized model, exact project/network identities, DNS scope, endpoint allocations, allowed connections, denied connection, and cleanup state are all independently evidenced. A running set of containers alone is not proof.

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 api on front and api-internal on 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.
Checkpoint communication policy
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.txt recording 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.

Next lesson

Next: Port Publishing, NAT, Firewall Interaction, Direct Routing, Host Binding, and Exposure Security

Keep the Chapter 18 network and DNS mental model. Chapter 19 will add host port publication and show why “service resolves internally” and “service is safely reachable from outside the Docker network” are completely different states.

Knowledge check

The frontend can resolve api but not data. Is the checkpoint broken?

What proves the API is dual-homed?

Why capture docker compose config before up?

What is the correct response if optional IPv6 creation is unsupported?

A developer asks to publish the database port to make the frontend test easier. What should you say?

Official references and version notes

Version baseline, verified 2026-09-21.

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.