← All craftbooks

Containerize a Service

Build: software and codeevalv1.0.0released 2026-06-05workflow: build-loop

Containerize an application with a production-grade Dockerfile — small, secure, reproducible, and buildable — plus the supporting files to run it. Scopes the container contract FIRST — base image, build vs runtime stages, dependencies, exposed port, entrypoint, env config, and the size/security bar — then writes the Dockerfile + .dockerignore + compose, then a reviewer confirms it builds, runs, and meets the bar. Covers multi-stage builds, slim base images, layer caching, non-root user, .dockerignore, healthchecks, EXPOSE/ENTRYPOINT, and reproducible image builds.

Steps

Entry step: scope. Each step names the specialist role it wants; the full working prompt is expandable.

  1. Scope the containerplannerentry

    lock base image, stages, port, entrypoint, bar

    Show working prompt
    Scope the container before writing the Dockerfile. Step 1: Identify the runtime (language/version) and pick a slim, pinned base image. Step 2: Decide the build strategy: a multi-stage build (build deps in one stage, copy only artifacts to a slim runtime stage) and what gets copied forward. Step 3: List the dependencies to install, the port to EXPOSE, the ENTRYPOINT/CMD, and the env vars the app needs at runtime. Step 4: Set the bar: run as a non-root user, a .dockerignore that excludes junk, a healthcheck, and a rough image-size target. Step 5: Write a numbered acceptance-criteria checklist of 5-9 items (e.g. 'docker build succeeds from a clean context', 'the container starts and serves on the exposed port', 'runs as non-root', 'final image uses a multi-stage slim base'). `write_task_note` the scope + checklist and write the same to the produces path.
  2. Write the Dockerfiledeveloper

    implement the multi-stage Dockerfile + support files

    Show working prompt
    Author the containerization files to the scope. Step 1: Write a multi-stage `Dockerfile` — a build stage that installs deps and builds, then a slim runtime stage that copies only the needed artifacts. Step 2: Order layers for cache efficiency (copy manifest + install deps BEFORE copying source), pin the base image, set a non-root USER, EXPOSE the port, and define ENTRYPOINT/CMD and a HEALTHCHECK. Step 3: Write a `.dockerignore` that excludes node_modules, .git, build output, and secrets. Step 4: If a service needs orchestration, add a minimal compose/run file. Step 5: Build the image and confirm it succeeds and the container starts. Write the Dockerfile to the produces path. On a loop-back, fix only the named gaps. `write_task_note` the file paths and which criteria now pass.
  3. Verify the imagereviewer

    confirm it builds, runs, and meets the bar

    Show working prompt
    Verify the container build. Step 1: Build the image from a clean context and confirm the build succeeds. Step 2: Run the container and confirm it starts and serves on the exposed port (hit the healthcheck/endpoint). Step 3: Confirm the bar: multi-stage slim base, non-root user, a real .dockerignore, pinned base image, and a sane final size. Step 4: Confirm no secrets or junk were baked into the image layers. Write a verification note with the build result, run check, and size to the produces path.
  4. Evaluatereviewer

    Grade the deliverable against every acceptance criterion. All pass → finish; any fail → loop back and fix the gap.

    Show working prompt
    Build and run the image. For EACH acceptance criterion: confirm `docker build` succeeds from a clean context, confirm the container starts and serves on the exposed port, confirm it runs as non-root with a multi-stage slim base and a .dockerignore, and confirm no secrets/junk were baked in. Write PASS/FAIL per criterion.
    
    Then route — this is the whole point of the loop:
    
    - **Every criterion PASSES →** call `advance_task_step({ ref, stepId: "evaluate", next: "finish" })`.
    - **Any criterion FAILS →** write the specific gaps to notes, then call `advance_task_step({ ref, stepId: "evaluate", next: "build" })` to loop back. The builder fixes exactly those gaps.
    
    Never route to `finish` while any criterion is unmet. The build phase's completion gate already blocked a grossly-incomplete deliverable; your job is the judgment an automated check cannot make (does it actually work, read well, look right). After ~3 unproductive loops, stop and report DONE_WITH_CONCERNS so the user can step in.
  5. Finishdeveloper

    All acceptance criteria met. Stamp a short summary and report DONE.

    Show working prompt
    Every acceptance criterion passed. Write a one-paragraph DONE summary to task notes via `write_task_note`: what was built, the deliverable path(s), and a one-line confirmation that each criterion is met. Then report DONE.

Triggers

Phrases that suggest this craftbook to a crew.

Source

View this craftbook on GitHub · MIT license