Nix is a better Docker image builder than Docker's image builder

Nix vs. Docker as Image Builders

  • Nix-based builds are praised for declarative, fine‑grained dependency management and tighter reproducibility than typical Dockerfiles.
  • Dockerfiles are criticized for imperceptible non‑determinism (floating tags, apt-get without pinning, git clone of branches), though some argue disciplined use of digests, snapshots, and mirrors can make Docker reproducible too.
  • Several note that Docker’s layer model is hierarchical and oriented around imperative build steps, while Nix maps a dependency graph to layers, enabling more reusable, content‑addressed layers.

Layering, Snapshotters, and Tooling

  • The Docker 128‑layer limit is a real pain when naively mapping Nix store paths to layers; people use heuristics or clumping, which hurts cache reuse.
  • nix-snapshotter integrates Nix with containerd: containers mount directly from the Nix store; docker pull becomes Nix substitution, avoiding tarball duplication and the layer limit. Deployment is straightforward on containerd‑based clusters but trickier on managed k8s.
  • nix2container and Nix’s buildLayeredImage improve caching and registry uploads by streaming layers and storing them in the Nix cache, and by letting users explicitly choose what goes into each layer.

Image Size and Optimization

  • Some report Nix-built images being unexpectedly large (e.g., large Nix base images, full JDKs, glibc with all locales).
  • Others show that with careful use of musl, headless JREs, minimal JREs, and overrides to strip unused features, Nix images can be competitive or small; buildLayeredImage enables sharing large deps (glibc, JDK) across many images.

Developer Experience and Complexity

  • Strong divide: enthusiasts value that a single flake can describe builds, dev shells, Docker images, NixOS modules, and tests; skeptics find flakes and nix language hard to learn, over‑abstracted, and poorly documented.
  • Common complaints: opaque errors, “dark corners,” steep cross‑compilation learning curve, and large, custom flake architectures that overwhelm newcomers.
  • Various attempts to tame complexity are mentioned (flake structuring patterns, higher‑level frameworks, tools like flox), but consensus is that DX remains a major barrier.

Cross‑Platform and Ecosystem Concerns

  • macOS/darwin users face slow or fragile cross‑compilation, missing Hydra caches, and complicated Docker integration; many resort to remote or VM Linux builders.
  • Guix is cited as a similar functional alternative with guix pack -f docker, but suffers from slower package updates and review delays.
  • For simple use cases (e.g., Go/Java services), some argue language‑specific image builders (ko, Jib, Bazel rules_oci) are preferable to the complexity of Nix.