Skip to content

Day 154 — Week 2 review + recall

Month 6 · Week 2 · ⬅ Day 153 · Day 155 ➡ · Journal index

🎯 Learning Objective

Consolidate the week's shipping skills — containerize, compose, harden, CI, config/secrets, graceful shutdown — and prove retention with active recall.

📚 Topics

  • Multi-stage builds · distroless hardening · Compose stacks
  • GitHub Actions (vet/race/cover/govulncheck) · 12-factor config & secrets · signals/shutdown

📖 Reading / Sources

📝 Notes

  • This is a light consolidation day; the full retro, re-quiz, and metrics live in the week review.
  • One-line thread: the same static binary flows through build → harden → compose → CI → run, configured by the environment and shut down cleanly on a signal.

💻 Code Examples

// The shape every service in this week shares: load config, start, drain.
func main() {
    cfg, err := config.Load()           // 12-factor: env in, fail fast
    if err != nil { log.Fatal(err) }
    ctx, stop := signal.NotifyContext(context.Background(),
        syscall.SIGINT, syscall.SIGTERM) // catch SIGTERM from `docker stop`
    defer stop()
    run(ctx, cfg)                        // ListenAndServe + Shutdown drain
}

Runnable: examples/month-06/graceful · examples/month-06/config

🏋️ Exercises / Practice

Exercise Status Link
envconfig · secretsource · drain (all go test green) exercises/month-06/week-2/

🐛 Mistakes Made

  • Early in the week I conflated "container started" with "service ready" — healthchecks and graceful shutdown both hinge on that distinction.

❓ Open Questions

  • Where does observability (metrics/tracing) bolt onto this lifecycle? → next week.

🧠 Active Recall (answer without looking)

  1. Q: Trace one static binary from go build to a running, hardened, gracefully-stopping container — name the key tool at each step.
    A

CGO_ENABLED=0 go build (static binary) → multi-stage Dockerfile into distroless static:nonroot (small, non-root, has CA certs) → docker compose for the local stack → GitHub Actions runs vet/-race/cover/govulncheck → config from env (os.LookupEnv + errors.Join), secrets via *_FILEsignal.NotifyContext + srv.Shutdown(ctx) drains on SIGTERM. 2. Q: Two production "fail-fast vs drain-slow" rules from this week?

A

Fail fast at startup on bad config (errors.Join all problems, exit non-zero). Drain slow at shutdown: bound Shutdown with a timeout shorter than the platform kill grace, treating http.ErrServerClosed as success.

🪶 Feynman Reflection

This week was about the gap between "my code compiles" and "my service runs in production." That gap is packaging, configuration, automation, and lifecycle — none of it changes the business logic, all of it decides whether the thing survives a deploy, a restart, and a bad dependency.

🕳️ Knowledge Gaps

✅ Summary

Week 2 done: I can ship a Go service as a small hardened image, run it in a local stack, gate it in CI, configure it the 12-factor way, and shut it down gracefully.

⏭️ Next Steps / Prep for Tomorrow

  • Month 6 · Week 3: observability — metrics, tracing, and dashboards on top of this lifecycle.

Time spent Difficulty Confidence
75 min 🟦⬜⬜⬜⬜ 🟦🟦🟦🟦⬜

Suggested commit: docs(journal): week 2 review + recall (day 154)