distill: 48 cross-project best-practices from 2026-07 reflection sweep
Promotions from reflecting 21 projects' session logs (incl. agent-runtimes 122-log drain). Adds coverage across networking (eBPF VIP/VPN SNAT/VLAN bridge/forward-auth preflight/ingress TLS), kubernetes (CSI hotplug/PodSecurity debug/self-managed GitOps/runtime annotations), CI (dispatch tokens/runner death/base image), git (CI-rebase/shallow reset/PR governance), python (async session pool/httpx redirects/logging), TDD (AsyncMock/xfail lifecycle), api-integration (SDK parse/token-scope 404/schema probing), plus docker, scripting, debugging, security-architecture, secrets, react, octopus. State: .distill-state.json refreshed with current HEADs + 5 newly-tracked projects.
This commit is contained in:
33
docker.md
33
docker.md
@@ -132,6 +132,29 @@ When a module will run inside a container, create its `_cli.py` entry point and
|
||||
|
||||
Treat "module + CLI shim + ENTRYPOINT verification" as one atomic unit of work.
|
||||
|
||||
## Pin All Container Images by Digest, Never by Tag
|
||||
|
||||
Mutable tags (`:latest`, `:v1.2.3`, `:stable`) can silently resolve to a different image after a rebuild. An image pinned to `myimage:v1.2.3` at deploy time may pull a newly-built `myimage:v1.2.3` months later that contains different code — no signal to the deployer that anything changed.
|
||||
|
||||
**Rule:** always pin to a content-addressable digest. Obtain the digest at build time:
|
||||
```bash
|
||||
docker buildx build --push -t reg.io/img@sha256:<digest> .
|
||||
```
|
||||
|
||||
In Dockerfiles, reference the digest directly:
|
||||
```dockerfile
|
||||
FROM reg.io/base@sha256:a1b2c3d4e5f6...
|
||||
```
|
||||
|
||||
In Kubernetes manifests and Helm values, use:
|
||||
```yaml
|
||||
image: reg.io/img@sha256:a1b2c3d4e5f6...
|
||||
```
|
||||
|
||||
If using a tag is unavoidable, add a pre-flight check that fails if the tag resolves to a different digest than the one baked into the deployment config.
|
||||
|
||||
The semver versioning system (where available) encodes expectations about change severity — a patch bump should not silently include unrelated changes. Digest pinning makes the version-content contract verifiable.
|
||||
|
||||
## PostgreSQL Alpine Image Runs as UID 70, Not 999
|
||||
|
||||
The `postgres:*-alpine` images run postgres as **UID 70**, not the 999 used by Debian-based `postgres:*` images. Setting data-directory ownership to 999 (or 1000) via host `chown` or Ansible `file` modules silently breaks access — `pg_isready` may still pass while internal operations fail with "Permission denied" on WAL writes, replication slots, or extension installs.
|
||||
@@ -142,3 +165,13 @@ docker exec --user postgres <container> id
|
||||
```
|
||||
|
||||
Match the automation to the actual UID. If a project mixes Alpine and Debian Postgres images across environments, treat the UID as per-environment config, not a hardcoded constant.
|
||||
|
||||
## Drop Placeholder `require` Lines Before `hugo mod get`/`go get @branch`
|
||||
|
||||
When a `go.mod` pins a module to the placeholder version `v0.0.0` (common for a not-yet-tagged private dependency), `hugo mod get <module>@<branch>` (and `go get`) still tries to resolve the existing `v0.0.0` first and fails with `unknown revision v0.0.0` — even though a valid `@branch` override is supplied.
|
||||
|
||||
Fix: run `go mod edit -droprequire=<module>` for each placeholder dep *before* the `mod get`. Dropping the require line lets the `@branch` fetch proceed cleanly. Prefer this over editing `go.mod` with sed/bash arithmetic (no `set -e` footguns). Works inside any image bundling Go (e.g. the Hugo build image).
|
||||
|
||||
## Make a Script Self-Contained When It Runs in a Different Image
|
||||
|
||||
A helper script that imports the app's package (`from myapp import ...`) breaks with `ModuleNotFoundError` when copied into a separate, minimal image that doesn't install that package. When a script is destined to run inside a different (e.g. slimmer, single-purpose) image than the one it was authored against, inline its dependencies — call the underlying library (`httpx`, etc.) directly instead of importing the application package. Don't assume the target image shares the source image's installed packages.
|
||||
|
||||
Reference in New Issue
Block a user