Chapter 37Lesson 05~235 minutes

Checkpoint Lab — Developer Workflows, Dev Containers, Inner Loop Optimization, Compose-Based Labs, and Local Parity

Onboard a clean workspace into a pinned containerized development environment, prove the inner loop, record identities, build production separately, and document parity gaps.

CheckpointOnboardingTool identityProduction imageParity gaps

Learning objectives

  • Onboard a clean synthetic workspace into a pinned, non-root development environment.
  • Exercise an edit/test inner loop while recording source, runtime, user, tool, cache, and port evidence.
  • Build the production image independently from the development container and record its immutable identity.
  • Create an explicit parity-gap list covering kernel/platform, mounts, ports, secrets, tooling, and data services.
  • Clean only checkpoint-owned resources while retaining the evidence packet.

1. Checkpoint contract

The checkpoint succeeds only when another developer could reconstruct what you used: source revision/checksum, Compose model, base-image reference and observed identity, runtime user, Python version, cache volume, local port, test result, production image identity, and a written list of differences between the developer environment and production. The dev service itself is not promoted.

2. Workspace and preflight

set -eu
LAB=dca37-checkpoint
mkdir -p "$LAB/src" "$LAB/evidence"
date -u +%Y-%m-%dT%H:%M:%SZ | tee "$LAB/evidence/time-start.txt"
docker context show | tee "$LAB/evidence/context.txt"
docker version | tee "$LAB/evidence/docker-version.txt"
docker compose version | tee "$LAB/evidence/compose-version.txt"
docker buildx version | tee "$LAB/evidence/buildx-version.txt"

3. Create clean source

# dca37-checkpoint/src/app.py
import sys
print("checkpoint-app=ready")
print(f"python={sys.version_info.major}.{sys.version_info.minor}")
# dca37-checkpoint/src/test_app.py
from pathlib import Path
text = Path("/workspace/src/app.py").read_text()
assert "checkpoint-app=ready" in text
print("checkpoint-test=pass")
sha256sum dca37-checkpoint/src/* | tee dca37-checkpoint/evidence/source.sha256
git rev-parse HEAD 2>/dev/null | tee dca37-checkpoint/evidence/source-revision.txt || printf 'synthetic-checksums-above
' | tee dca37-checkpoint/evidence/source-revision.txt

4. Create pinned-readable development definition

# dca37-checkpoint/Dockerfile.dev
# syntax=docker/dockerfile:1
FROM python:3.13-alpine
RUN addgroup -g 10001 dev && adduser -D -u 10001 -G dev dev     && mkdir -p /workspace/src /home/dev/.cache     && chown -R dev:dev /workspace /home/dev
WORKDIR /workspace
USER dev
CMD ["sh", "-lc", "python /workspace/src/app.py && sleep infinity"]
# dca37-checkpoint/compose.yaml
services:
  dev:
    build:
      context: .
      dockerfile: Dockerfile.dev
    working_dir: /workspace
    volumes:
      - ./src:/workspace/src
      - dca37-checkpoint-cache:/home/dev/.cache
    ports:
      - "127.0.0.1:18039:8000"
    labels:
      academy.lab: dca37-checkpoint
volumes:
  dca37-checkpoint-cache:
    name: dca37-checkpoint-cache
    labels:
      academy.lab: dca37-checkpoint

5. Predict state changes before execution

Prediction 1: Compose will create one project service plus the exact named cache volume dca37-checkpoint-cache.
Prediction 2: the dev process will run as UID/GID 10001 inside the container unless the definition is changed.
Prediction 3: editing the host source bind will immediately change /workspace/src in the dev container.
Prediction 4: the production image built later will contain copied source but no source bind mount or development cache volume.
Prediction 5: cleanup will remove only the checkpoint Compose objects, exact cache volume, and exact production image tag.

6. Render configuration before starting

docker compose -p dca37-checkpoint -f dca37-checkpoint/compose.yaml config | tee dca37-checkpoint/evidence/compose.rendered.yaml
docker compose -p dca37-checkpoint -f dca37-checkpoint/compose.yaml up -d --build

7. Record dev runtime and tool identities

CID=$(docker compose -p dca37-checkpoint -f dca37-checkpoint/compose.yaml ps -q dev)
printf '%s
' "$CID" | tee dca37-checkpoint/evidence/dev-container-id.txt
docker inspect "$CID" \
  --format 'image={{.Image}} user={{.Config.User}} mounts={{json .Mounts}} ports={{json .NetworkSettings.Ports}}' | tee dca37-checkpoint/evidence/dev-inspect.txt
docker compose -p dca37-checkpoint -f dca37-checkpoint/compose.yaml exec dev id | tee dca37-checkpoint/evidence/dev-id.txt
docker compose -p dca37-checkpoint -f dca37-checkpoint/compose.yaml exec dev python --version | tee dca37-checkpoint/evidence/python-version.txt
docker volume inspect dca37-checkpoint-cache | tee dca37-checkpoint/evidence/cache-volume.json

8. Exercise edit/test inner loop

printf '
# checkpoint-edit=1
' >> dca37-checkpoint/src/app.py
docker compose -p dca37-checkpoint -f dca37-checkpoint/compose.yaml exec dev tail -n 2 /workspace/src/app.py | tee dca37-checkpoint/evidence/edit-visible.txt
docker compose -p dca37-checkpoint -f dca37-checkpoint/compose.yaml exec dev python /workspace/src/test_app.py | tee dca37-checkpoint/evidence/test.txt

9. Optional Compose Watch variant

# Replace the source bind with this in a copy of the Compose file if Compose >= 2.22:
develop:
  watch:
    - action: sync
      path: ./src
      target: /workspace/src
      initial_sync: true

If you exercise this optional variant, capture the Watch output and final file checksum. Do not claim you tested Watch if you only used the bind-mounted checkpoint path.

10. Build production separately

# dca37-checkpoint/Dockerfile
# syntax=docker/dockerfile:1
FROM python:3.13-alpine AS runtime
RUN addgroup -g 10001 app && adduser -D -u 10001 -G app app
WORKDIR /app
COPY --chown=app:app src/app.py /app/app.py
USER app
CMD ["python", "/app/app.py"]
docker build -f dca37-checkpoint/Dockerfile -t dca37-checkpoint-prod:1 dca37-checkpoint | tee dca37-checkpoint/evidence/prod-build.log
docker image inspect dca37-checkpoint-prod:1 \
  --format 'id={{.Id}} repoDigests={{json .RepoDigests}} user={{.Config.User}}' | tee dca37-checkpoint/evidence/prod-image.txt
docker run --rm dca37-checkpoint-prod:1 | tee dca37-checkpoint/evidence/prod-run.txt

11. Record the parity-gap list

Required parity-gap note:
- Source: production image contains source as of the production build; dev sees live host edits.
- User: both examples are non-root, but dev UID ownership and production runtime ownership serve different goals.
- Filesystem: dev has source bind + cache volume; production image has neither.
- Kernel/host: Docker Desktop/host development kernel may differ from production.
- Ports: checkpoint publishes only loopback; production ingress is not modeled.
- Secrets: none are required; real secret-provider behavior is not modeled.
- Tooling: dev may gain editor/debug tools; production target intentionally does not.
- Data services/scale: no production database, replicas, load balancer, or failover is modeled.

12. Verify predictions

Prediction Verification
Exact cache volume exists docker volume inspect dca37-checkpoint-cache
Dev is non-root captured id output
Edit reaches dev workspace captured tail/test output
Production has no dev bind/cache production container/image inspect and Dockerfile
Cleanup is bounded only project, named volume, exact image tag removed

13. Exact cleanup

docker compose -p dca37-checkpoint -f dca37-checkpoint/compose.yaml down
docker volume rm dca37-checkpoint-cache 2>/dev/null || true
docker image rm dca37-checkpoint-prod:1 2>/dev/null || true
printf 'Retain dca37-checkpoint/evidence for review.
'

14. Required evidence packet

Evidence family Required record
Source revision or synthetic checksums; dirty-state note if applicable
Docker host context, Engine, Compose and Buildx versions
Dev definition rendered Compose; Dockerfile.dev checksum
Identity dev container ID/image ID; runtime UID/GID; Python/tool versions
Workspace mount source/target or Watch rule and observed edit
Cache named volume identity and intended retention
Network loopback published port or forwarding mechanism
Test inner-loop test output
Production production Dockerfile; image ID/digest evidence; runtime output
Parity explicit gap list; no claim of full environment equivalence
Cleanup exact project/volume/image objects removed

15. What Chapter 37 adds to the operating model

You can now make onboarding and the inner loop reproducible without conflating them with production delivery. Source, developer tooling, workspace synchronization, caches, identities and local ports are all explicit evidence. Production remains a separately built artifact with a documented parity contract.

Chapter 38

Production Container Patterns, Immutable Delivery, Configuration, Statelessness, Sidecars, and Operational Contracts

Next, the course converts the build/runtime/security evidence accumulated so far into production container patterns and operational contracts.

Knowledge check

What proves the developer environment is reproducible enough to review?

Why does the checkpoint build production after the inner-loop test?

If you did not run Compose Watch, may you claim Watch behavior was verified?

What is the correct cleanup unit?

What should the final parity note contain?

Official references and version notes

Checkpoint baseline: 2026-09-22. The runnable path requires only Docker/Compose and local files. Dev Container tooling and Docker Desktop premium synchronized sharing are optional; the evidence and parity contract does not depend on them.

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.