
Why isolation ≠ reproducibility and what that means for dev environments
The post started as a simple explainer on standardized dev environments and turned into something more interesting: a direct comparison between how containers and Nix-style environments actually achieve (or don't achieve) reproducibility.
The short version: containers correlate isolation with reproducibility, but they're not the same thing. A Dockerfile is a procedural recipe that calls out to mutable external systems. Package indexes, install scripts, base image tags. node:22 is a mutable reference. The practical unit of reproducibility ends up being the digest-pinned image, not the Dockerfile that produces it.
Nix, Guix, and Flox approach it differently. Reproducibility is a function of the declared input graph, the lockfile, and the realized store closure. Running flox activate or nix develop against the same definition realizes the same cryptographically-hashed store paths, on any machine, at any time.
To make this concrete, we built the same Python 3.14 + Node.js 25 dev environment four ways: Dockerfile, Guix manifest, Nix flake, and Flox manifest, then walked through how each one resolves (or doesn't) to a reproducible output. The Nix flake and Flox sections include the actual flake.nix and manifest.toml, along with the lockfile behavior.
(Disclosure: this is the Flox account)