Update tech_docs/docker_compose_guide.md
This commit is contained in:
@@ -1,3 +1,150 @@
|
||||
Learning-GOAL: “I can read, reason about and harden any Dockerfile or `docker run` incantation I meet—without drowning in trivia.”
|
||||
|
||||
Below is a **minimal, language-agnostic curriculum** expressed as executable **pseudocode**.
|
||||
Each block is a self-contained kata you can type, break, fix and extend.
|
||||
```plaintext
|
||||
--------------------------------------------------
|
||||
0. Bootstrapping Sandbox
|
||||
--------------------------------------------------
|
||||
function bootstrap():
|
||||
vm = create_ephemeral_vm() // multipass, lima, or cloud instance
|
||||
install("docker engine") // or podman, nerdctl
|
||||
alias d="docker"
|
||||
return vm
|
||||
|
||||
--------------------------------------------------
|
||||
1. Core Primitives (must be muscle memory)
|
||||
--------------------------------------------------
|
||||
// 1.1 Image = read-only template
|
||||
function image_primitives():
|
||||
img = build("Dockerfile_hello") // FROM alpine; COPY hello.sh /; CMD ["sh","/hello.sh"]
|
||||
tag = tag(img, "demo:v1")
|
||||
id = inspect(tag, ".Id")
|
||||
layers = history(tag) // list of diff-IDs
|
||||
return {img, tag, id, layers}
|
||||
|
||||
// 1.2 Container = writable runtime instance
|
||||
function container_primitives():
|
||||
c1 = run("-d --name c1 demo:v1")
|
||||
top = exec(c1, "ps aux") // what’s running?
|
||||
delta = diff(c1) // which files changed?
|
||||
commit(c1, "demo:v1-smeared") // bake delta into new image
|
||||
rm(c1)
|
||||
|
||||
// 1.3 Registry = image transport
|
||||
function registry_primitives():
|
||||
reg = start_local_registry() // docker run -d -p 5000:5000 registry:2
|
||||
push("demo:v1", reg)
|
||||
rmi("demo:v1")
|
||||
pull("demo:v1", reg)
|
||||
|
||||
--------------------------------------------------
|
||||
2. Storage & State (volumes, bind mounts, tmpfs)
|
||||
--------------------------------------------------
|
||||
function storage_primitives():
|
||||
vol = volume_create("db_data")
|
||||
c2 = run("-d -v db_data:/var/lib/postgresql postgres:15")
|
||||
c3 = run("-d --mount src=$(pwd),dst=/src,type=bind alpine sh -c 'sleep 3600'")
|
||||
c4 = run("--tmpfs /tmp:size=100m alpine sh -c 'dd if=/dev/zero of=/tmp/big'")
|
||||
cleanup([c2,c3,c4])
|
||||
|
||||
--------------------------------------------------
|
||||
3. Networking (CNB model)
|
||||
--------------------------------------------------
|
||||
function networking_primitives():
|
||||
net = network_create("demo_net", driver="bridge")
|
||||
nginx = run("-d --net demo_net --name web nginx")
|
||||
curl = run("--rm --net demo_net alpine/curl curl http://web")
|
||||
assert "Welcome to nginx" in curl.output
|
||||
rm(nginx); network_rm(net)
|
||||
|
||||
--------------------------------------------------
|
||||
4. Build Secrets & Multi-stage (no plaintext keys)
|
||||
--------------------------------------------------
|
||||
function build_hardening():
|
||||
// Dockerfile.multi
|
||||
// FROM golang:1.22 AS build
|
||||
// RUN --mount=type=secret,id=gh_token \
|
||||
// git config --global http.extraheader "Authorization: Bearer $(cat /run/secrets/gh_token)"
|
||||
// COPY . .
|
||||
// RUN go build -o app .
|
||||
// FROM gcr.io/distroless/static
|
||||
// COPY --from=build /src/app /app
|
||||
// CMD ["/app"]
|
||||
img = build("--secret id=gh_token,env=GH_TOKEN -f Dockerfile.multi .")
|
||||
scan(img) // trivy or grype
|
||||
|
||||
--------------------------------------------------
|
||||
5. Security Profiles
|
||||
--------------------------------------------------
|
||||
function security_primitives():
|
||||
c5 = run("--cap-drop ALL \
|
||||
--cap-add NET_BIND_SERVICE \
|
||||
--security-opt no-new-privileges:true \
|
||||
--user 1000:1000 \
|
||||
--read-only \
|
||||
--tmpfs /tmp \
|
||||
alpine:latest whoami")
|
||||
assert c5.stdout == "1000"
|
||||
|
||||
--------------------------------------------------
|
||||
6. Orchestration Lite (Compose as state-machine)
|
||||
--------------------------------------------------
|
||||
function compose_primitives():
|
||||
services = load("compose.yml") // web, redis, db
|
||||
stack = compose_up(services)
|
||||
assert http_get("http://localhost:8080") == 200
|
||||
compose_down(stack)
|
||||
|
||||
--------------------------------------------------
|
||||
7. Observability & Debug (no black boxes)
|
||||
--------------------------------------------------
|
||||
function observability():
|
||||
c6 = run("-d demo:v1")
|
||||
logs_tail(c6)
|
||||
stats = container_stats(c6) // cpu, mem, blkio
|
||||
enter(c6, "sh") // nsenter for low-level poke
|
||||
rm(c6)
|
||||
|
||||
--------------------------------------------------
|
||||
8. Cleanup Ritual
|
||||
--------------------------------------------------
|
||||
function cleanup(containers):
|
||||
for c in containers:
|
||||
stop(c, timeout=5)
|
||||
rm(c, volumes=True)
|
||||
system_prune(all=True)
|
||||
|
||||
--------------------------------------------------
|
||||
9. Mastery Checklist
|
||||
--------------------------------------------------
|
||||
can_i:
|
||||
▢ explain the difference between an image, a layer, and a container
|
||||
▢ build multi-stage with secrets and non-root user
|
||||
▢ launch two containers on a custom bridge and capture traffic
|
||||
▢ run a read-only container that still writes temporary files
|
||||
▢ read `docker inspect` JSON and spot the security-options stanza
|
||||
▢ translate a `docker run` one-liner into compose YAML and back
|
||||
▢ upgrade base image without cache, then surgically bust only the vulnerable layer
|
||||
|
||||
--------------------------------------------------
|
||||
10. Exit Condition
|
||||
--------------------------------------------------
|
||||
if mastery_checklist.all_true():
|
||||
print("You now own the primitives. Dive into BuildKit, rootless, or Kubernetes.")
|
||||
else:
|
||||
iterate()
|
||||
|
||||
--------------------------------------------------
|
||||
Usage Notes
|
||||
--------------------------------------------------
|
||||
- Replace every function with real shell commands (`docker build …`, `docker network create …`).
|
||||
- No single file is more than 40 lines; the goal is repetition, not rote memorization.
|
||||
- Re-run the entire pseudocode weekly on a fresh VM to avoid stale muscle memory.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Ah, I see—you’re asking for a **meta-comparison** that aligns with your framing of *"deterministic serendipity"* (predictable yet flexible configurations) and focuses on **functional parallels** between Docker Compose and Talos Linux’s approach, even if their primary use cases differ. Let’s reframe this as:
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user