7 ms·
Nix, guix and traditional package managers that support multiple versions (like dnf) are better solutions than just containerizing the whole thing. But here we
by IceWreck 5y ago
Nix, guix and traditional package managers that support multiple versions (like dnf) are better solutions than just containerizing the whole thing.
But here we are, some projects only give development instructions based on containers, others support only container based deployment. You need to go out of the way trying to convert dockerfiles into regular install/setup instructions.
Containers are great and all, they solve many problems but they're not the only solution and theyre definitely not the best solution to every problem.
- terrywang 5y agonix is really nice (finding it much better than homebrew cross macOS and Linux) and do good jobs at the best cost for some of my uses cases (kind of binenv / arkade, etc. that manages some binaries that the target hosts use). However, nix has its own problems that I may not qualified to comment (not savvy enough user) - a bit of learning curve (NixOS vs nix package manager) - memory hogging while running system-wide update - disk space consumption is a mystery (GC & optimisation doesn't do good jobs freeing up space) Don't get me wrong, I do like nix ;-)
- cwp 5y agoThe learning curve is the biggest issue. Nix is different, and that makes it hard to learn unless you're already into functional programming. I like it too, but damn, it's so hard to get someone up to speed, even if they're sold on the benefits and want to learn.
- nineteen999 5y ago> Containers are great and all, they solve many problems but they're not the only solution and theyre definitely not the best solution to every problem. There a large number of developers around now who've never done traditional (RPM, DEB, SysV) packaging and don't understand it. So while the large distros like Redhat and Debian push on with it, the development community only sees Dockerfiles, Snaps, Flatpaks etc.
- thejosh 5y agoMost packaging for software was done by the distro and not the actual software authors though right?
- nickelpro 5y agoYes, packaging has always been a distro issue never an upstream issue. At the extreme end of this you can look at Arch's saga with Visual Studio Code, since the Arch packagers want to disentangle the .asar app from the specific Electron version it ships inside of (they view Electron as a system library).
- pabs3 5y agoChromium (and thus Electron, although they deliberately lag behind Chromium) has very frequent security updates. While clearly not all of those affect Electron, and not all of those affect every Electron app, some of them will affect Electron and some will affect some Electron apps. While some Electron apps will follow the (deliberately lagging) Electron security update cycle, most developers probably do not update their app for every Electron security update. So it makes sense for distros like Arch to want to ship the security supported Electron version and have every Electron app use that, but maybe all the changes in Electron are breaking apps that use it, so maybe it makes sense to ship one Electron version per Electron app, but then you get an unknown amount of security issues with each app, depending on how out of date the app's Electron version is. So the choice is between a working app with an unknown amount of security issues, or a regularly broken app with fewer security issues. Neither seem like great options to me. Perhaps Electron needs an LTS version to solve this issue.
- KronisLV 5y ago> There a large number of developers around now who've never done traditional (RPM, DEB, SysV) packaging and don't understand it. I'm one of these developers (at least as far as my day job is concerned) and the only methods of delivery in a professional context that i've seen have been: - delivering .jar or .war application files (Java), mostly through FTP or even e-mail - delivering other files, like documentation etc., mostly through FTP or even e-mail - using containers and pushing images to registries (mostly due to my initiative) This is across ~5 years of software development and while looking at projects from multiple companies in my country - not once have i seen a DEB or RPM package repository be used. To me, it seems like previously people opted for the simplest solution in their eyes, which was just shuffling a bunch of files around through FTP, i guess since that doesn't lock you down to using a particular distro or even OS. However, streamlining that process on our end and eventually migrating over to containers, to where both the CI and CD are automated (or at least based on a manually invoked pipeline, when we're sure about making a release) seemed to be a no-brainer. Suddenly delivering software isn't something that takes an hour - even if needless cruft (making Jira issues manually etc.) is still there, any automation and getting rid of the human factor makes things safer and easier. That said, it surprises me that previously no one bothered to set up their own DEB or RPM repositories, since then the clients could use the package management solutions that they're already familiar with. Any idea what are some of the reasons for it? Why doesn't everyone just make it so that their software can be installed and updated through apt/yum/...?
- 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.
- tikhonj 5y agoOne thing I like with Nix is that it can build containers, so it's totally compatible with deployment systems that require containers. I don't mean using Nix commands in a Dockerfile, I mean having a Nix derivation that produces a container. I've been writing normal Dockerfiles at work recently and the whole toolchain is annoying on multiple fronts; I'd love to jump to Nix instead, except it's really hard to convince other people to learn non-trivial technology that's off the beaten path :(.
- the_duke 5y agoI second that. Using nix for building docker images [1] is brilliant, especially when combined with flakes. You don't need messy shell scripts to set up the environment and can get 100% reproducibility. You just build a regular Nix derivation (aka package) with the software you need and then just specify that in your image. It does take some work to get the image size down though. I'll also mention Nixery [2], which is a Docker registry that automatically builds images based on Nix. [1] https://nix.dev/tutorials/building-and-running-docker-images https://nix.dev/tutorials/building-and-running-docker-images [2] https://github.com/tazjin/nixery https://github.com/tazjin/nixery
- throwaway984393 5y ago"Supporting multiple versions" is a misnomer. You can't use multiple versions of a dependency on a single system without completely separating both the build-time and run-time environments, which is what containers do. If Nix did that implicitly it would mean that the applications would all have to be patched - not only to load specific library versions, but to call exec() on specific versions of binaries of completely unrelated apps. Otherwise two apps that call each other but use incompatible dependencies will never know that they're incompatible, creating an unresolvable conflict. I doubt anyone behind Nix is writing patches for every single application that exists, and every version of every application, in order to achieve this. The only other way to do it is by re-building all of the deps and installing them in an environment specific to an application (what containers do), and then having an interface to be able to choose what versions of what environments to combine with which applications in what ways. You can't even create a Bash one-liner using two different apps/environments and ensure it'll work, unless you explicitly define what versions of the shell commands you're going to use together. It's impossible to automate. Hence "regular" distros with specific package trees, and containers to provide the interface to mix application/environment pairs. There is no better solution, because all software development itself is inherently flawed. It's all 1970s programming: a single system with a single set of dependencies per application (both build-time & run-time). There is no solution to that problem other than to reinvent how software works so that versions are explicit in all code execution on a system. An application would have to request code execution with a specific version, and the system would have to figure out how to provide that version of that code at run time.
- fuzzy2 5y ago> You can't use multiple versions of a dependency on a single system without completely separating both the build-time and run-time environments Sure you can. It's what version numbers in library file names are for. Works for executable names, too. Until Python 2.7 died, you commonly had 2.7 and 3.x installed at the same time. But maybe you meant something different?
- throwaway984393 5y agoIt's impossible at the package manager level. First, install python 2 and python 3. Next, install a script that calls "#!/usr/bin/python". How do you make the script work, without modifying the script, so that it will work with the specific version of Python it was designed against? You can't. You have to either modify the script to point at the specific executable it was designed for, or you have to modify the environment to point "/usr/bin/python" at either python2 or python3. The former, "modifying the script", is recompiling all applications to point all of the executables they run at a custom executable, like "/run/app/v2/bin/app". The latter, "changing the environment", requires that you specify the environment before you run the script (". /etc/python2.env ; /some/script.py"). But then you have to know that, right now, you want to run the script against Python 2. What if you install an upgraded version of the script that's built against Python 3? How do you know which script to run when? You have to have an interface and pick which one to use each time you run it. And every application that runs that script. You can, of course, install two versions of your script, and rename the scripts, so that you know script2.py runs against python2 and script3.py runs against python3. But what if you have another program that needs to call the script? How does it know which of these 2 custom names to run? Now you'll have to compile a new custom package for this new program, and rename it too, and hard-code that one to call the specific new custom script name that targets the specific Python version. And on, and on, and on, you will need to have duplicate packages for every possible dependency graph that could possibly exist of different versions of different programs. You would end up with 16,000 packages of this python script, each with a custom name and custom paths. Because some combination of dependent packages could lead to a recursive bug where the wrong app eventually calls the wrong script. And it also requires patching literally every single application that is ever packaged by Nix to be able to rename applications and libraries. Every C program that ever calls "wc" needs to be patched to run "wc" version 2.0.0, "wc" version 2.0.1, "wc" version 3.0.0, etc, for every version of wc that may exist, and for every version of wc that may call a different program which also has multiple versions. This is why the problem is unsolvable with any tooling whatsoever. There is no way to automatically determine the correct dependencies without modifying and packaging every application for every dependency tree that could possibly exist. The only solution is what containers give you: an interface that forces you to pick a version of an application with one dependency tree, and lets you figure out how to combine them (how to run containers together). The only way to solve it without either 16,000 variants of one package, or an interface to pick environments at exec time, is to fundamentally change how software is designed and run today.