Comment by Cyph0n
4 days ago
Nix handles containerization better than Docker does.
Here is a flake that builds a Go app and a Docker image for it (based on headless Chrome): https://github.com/aksiksi/ncdmv/blob/aa108a1c1e2c14a13dfbc0...
And here is how the image is built in CI: https://github.com/aksiksi/ncdmv/blob/aa108a1c1e2c14a13dfbc0...
here is a derivation that fetches https://www.usememos.com/ from source, changes the color palette, builds a docker image out of it and spins up a container that traefik exposes automatically: https://gist.github.com/knoopx/afde5e01389e3b8446f469c056e59...
Very cool! I actually considered implementing the Compose Build spec this way for compose2nix, but instead opted to just use Docker/Podman directly.
You're going to need to do more than just link to the flake if you want to show why that's better than the Dockerfile equivalent, because the code itself isn't selling it.
1. Unbelievable layer reuse out of the box. Each Nix build output is placed in its own layer, including your binary (up to a max of 120 or so layers). Rebuilding the image will only result in the final layer changing, which minimizes work on image push.
2. Everything is pinned to nixpkgs, including dependencies. Anyone who builds this image will get the exact same versions (vs. apt-get update in a Dockerfile pulling a more recent version). It’s just sqlite in this case, but you can imagine how it would work with more dependencies.
3. It is trivial to build a “FROM scratch” image - in fact, that’s the default behavior in Nix, because Nix implicitly includes all runtime dependencies alongside your binary. This is less of a challenge with Go, but YMMV with other languages.
4. You can define your entrypoint script - or any other one-off script - in-line. Not a huge advantage, but still quite useful.
There is even an alternative pattern that allows you to reap these same benefits directly in your Dockerfile:
https://mitchellh.com/writing/nix-with-dockerfiles
Hope that helps.