4 ms·
> Nix, guix and traditional package managers that support multiple versions (like dnf) are better solutions than just containerizing the whole thing. Interesti
by occz 5y ago
> Nix, guix and traditional package managers that support multiple versions (like dnf) are better solutions than just containerizing the whole thing.
Interesting viewpoint! What are your arguments for this being a better solution than containerization?
- remexre 5y agoMost package managers running in containers (whether apt, apk, or something else) aren't built for reproducibility, so doing e.g. `apt update && apt install neovim` can change the versions of libraries inside the container. Furthermore, people don't (in general) write Dockerfiles for reproducibility -- it's very rare to see one where the `apt install` command (or equivalent) has exact version numbers specified for all dependencies, the FROM command uses a hash, etc.
- mikeyjk 5y agoAre there any examples of people doing this? Sounds interesting
- throwaway984393 5y ago$ VER=$(dpkg -s alsa-oss | grep -m1 '^Version: ' | sed -e 's/^Version: //g') $ cat > Dockerfile <<EOF FROM ubuntu:21.04 RUN apt-get update && apt-get install -y alsa-oss=$VER EOF $ cat Dockerfile FROM ubuntu:21.04 RUN apt-get install alsa-oss=1.1.8-1 $ docker build -t testimg . $ docker run --rm -it testimg dpkg -s alsa-oss | grep ^Version: Version: 1.1.8-1 That's a complicated example. All you need to do is get a working system, specify the base image tag, run dpkg -l and write down all the versions, then pass them to apt-get install. It's super easy. It's much more complicated to do something like download a static Go app from a specific URL, import a GPG key, validate the key, verify the checksum, etc. This would freeze all the packages on the system into a file for use in a Docker container: $ dpkg -l | awk '{print $2,$3}' | sed -e 's/ /=/g' | tail -n +6 | xargs > packages.txt $ cat > Dockerfile <<EOF FROM ubuntu:21.04 COPY packages.txt /packages.txt RUN apt-get update && apt-get install -y $(cat /packages.txt) EOF If you just want to find out the dependencies for a package, use something like apt-cache rdepends alsa-oss and then get the versions and pin them. It's pretty trivial to just read the man pages for dpkg or apt and get what you want done. You commit packages.txt and Dockerfile to a Git repo, and you push your built images to an artifact repository. Test it, validate it, ship it to production. It's all immutable so it doesn't need to be reproduced, you just roll back to the last artifact.
- remexre 5y agoAh, though note there, you want to specify the base image by hash instead of by tag -- I've been bitten by that before...
- throwaway984393 5y agoThe use of a non-static tag is intentional to pick up security and bug fixes. It's like using a "stable" branch, where you expect to get any emergency fixes to the stable branch. Only in this case it's a release-specific stable branch. If you ran a system with some compliance mandate that not even security fixes could be automatically applied, then you'd pin to the hash.
- jbboehr 5y agoI may be wrong, but I believe one caveat here is apt may not always have some version of packages available. I believe only the latest one in each `deb-src` is available. This is not an issue with nix as nix has the ability to build the entire system from source forever in a single command.
- habibur 5y agoYour software is first a separate application running on the OS. But gradually over time as its usage increase and it's extended by more and more even larger applications -- your app will turn into part of the OS. Containerizing your app doesn't help in this case. Imagine how many services from the OS you are using. Next imagine each one running in a different container and you have to build your app using 100s such containers.
- tikhonj 5y agoIt's a better solution for dependency management specifically. I need to go to bed so I can't go in too much depth, but here's a high-level summary: - Nix packages can compose in arbitrary ways, containers can't - Nix can get much more consistent and granular caching - once an image is built it's reproducible, but the Dockerfile to run it probably isn't—unless it was written very, very carefully to pin everything—so what happens if you need to update one or two packages in an image? - not 100% sure here, but it seems that lightweight sandboxing like Nix shells or virtualenvs are a lot more convenient for local development and tooling integration That said, containers might make more sense for, say, deploying and sandboxing services—that's just a different problem from reproducibly managing dependencies and development environments. Nix can build container images, which lets you get the best of both worlds.