Pinned Image Digests Turn a Container Tag into a Reproducible Dependency
A mutable tag tells you what to ask for; a digest tells you what bytes you actually accepted.
TOPIC
Lessons, explainers, experiments, and implementation notes.
A mutable tag tells you what to ask for; a digest tells you what bytes you actually accepted.
The safest time to decide how to recover is before the change has modified the evidence you depend on.
Fixing one incident is useful; changing the system so the same class of failure becomes detectable or impossible is more valuable.
A reviewed repository can still be disconnected from the state actually running on the host.
We can declare a desired state, but real systems rarely arrive there instantly. Failure, delay, and change exist along the path. Reconciliation is interesting because it checks the relationship repeatedly instead of trusting a one-time command.
If the provider already reports scheduled, publishing or published, the reconciler should observe rather than repeat the side effect.
Operational confusion falls when desired configuration, mutable data and confidential values stop competing to be one source of truth.
The authoritative article text can remain stable while each destination has its own mutable publishing lifecycle.
Production work continued in multiple streams, so safe synchronization had to preserve both histories rather than overwrite whichever side moved first.
When a network response is lost, retrying a create request can duplicate the side effect even if the first request succeeded remotely.
Separating image construction, configuration injection and runtime startup makes failures easier to localize.
Container process state only proves that PID 1 exists; readiness has to test the behavior the dependency actually needs.
Content intent and remote-delivery progress are different state machines and should not be collapsed into one post status.
You cannot reliably roll back to yesterday's image if the tag you used yesterday points somewhere else today.
A production checkout owned by another identity can be readable on disk while Git refuses to trust it.
A configuration should render successfully from a clean checkout before it is trusted on a production host.
A service can be reachable and still be routed through the wrong authentication or application layer.
Restarting a service whenever one of its dependencies is temporarily unhealthy is not always helpful. An external failure may not be fixed by restarting the application, and useful in-flight work can be lost in the process.
Counting containers does not tell you how much pressure a server is under. One container may do very little while another holds data, caches, and many threads. Two servers with the same container count can have very different resource needs.
When the remote API lacks your preferred idempotency primitive, deterministic discovery can recover an uncertain previous attempt.
A successful target deployment is not a full success if the change quietly damages another workload on the same host.
An application can pass isolated logic tests while its database schema still fails to create, upgrade or enforce the intended constraint.
When a deployment fails later, the first forensic question is which reviewed source revision actually produced it.
A posture check should distinguish evidence it cannot read from evidence that proves the system is wrong.
Live files that are absent from Git are technical debt even when the service is currently healthy.
Comparing HEAD with origin/main proves consistency with the last fetched view, not with the current remote repository.
Retry counts and backoff are not just performance settings when the job performs external side effects.
Building from scratch is a great way to learn, but existing software may solve a user's problem faster and more reliably. Reuse does not remove engineering judgment; it changes what must be evaluated.
Cleanliness answers whether local tracked files changed; freshness answers whether the revision is the one you intended to run.
When a network response disappears, a user may retry even though the first operation already succeeded on the server. Whether the second request creates new work or returns the result of the first operation is part of the application's contract.
An audit trail is only useful if its schema is simpler and more dependable than the systems it records.
Repository boundaries should not become operational blind spots on a shared production host.
A container command is only reproducible when you know whether the image entrypoint wraps, replaces or transforms it.
Recording containers, ports and revisions after deployment gives future incident response a known-good comparison point.
CI failed because the image entrypoint changed how arguments were interpreted, not because the OpenBao configuration was invalid.
Infrastructure source is incomplete if Compose points at files that only exist on the current server.
Incident investigation becomes easier when a release can answer which source produced which artifact. A label such as latest is not enough. Latest changes with time; a commit or artifact identity does not.
Schema declarations are executable code; a one-word typo can prevent the application model from initializing correctly.
A configuration file copied with the wrong mode can behave differently depending on the build context and base image defaults.
A scheduler can enqueue work before crashing; recovery logic must discover incomplete deliveries after the process returns.
A running process is useful information, but it does not prove the process is completing the work it exists to do. A web server can be alive while its required database is unreachable.
Seeing a service in Portainer does not tell you which repository, runbook or backup path can recreate it.