Recommendations on workflow with node application (shell.nix + docker)

Hey there!

I’m relatively new to nix and have already used it to configure my home-environment and my NixOS installation.
Now I wanted to get some hands-on experience using it during development. The main problem is that I don’t want to use nix just for the sake of using it.

The Situation is the following:

  • Monorepo including frontend and backend, both Node Projects
  • Backend is Nestjs
  • Frontend Angular
  • Mongodb as the database
  • Optionally a redis instance for volatile values, depends on the project config

In frontend and backend exist docker-compose.yml files which launch all the services needed for testing the application locally.

Now I wanted to create a shell.nix file to provide all the dev-dependencies for working on the project. One of my goals is to show my colleagues how easy it is to set up dev environments using nix.
This is easily done for most of the programs needed, but when it comes to docker I hit a roadblock.

As I have read it online it seems that including docker as a dependency in a shell.nix file is finicky as you have to make sure that the virtualization-options on your machine are configured correctly.

Some people say, that the “nix way” to handle this, would be to completely replace the docker-compose part of the workflow by making sure that the services are running in the shell-hook of the shell.nix file. However I don’t want to be too pushy towards the other devs on my team.

As it stands now I’ve only added all the packages needed for development - excluding docker - and print a message that it assumes that docker is running correctly on the machine.

Another question I was asking myself was: “should I try to ‘replace’ npm with nix-build?”. But to be honest I don’t see the benefit of that at the moment when the application is currently only in development and is never meant to be shared apart from our repository. Maybe I could replace the Dockerfile using nix tooling for deploying the application to our servers?

How would you handle the situation? I’m grateful for every piece of advice!
However, I would like to stay away from flakes until I have a solid grasp on the basics.

Cheers! And thanks in advance!

This is a pretty reasonable approach if you can’t (or don’t want to) abolish existing docker infrastructure.

Running things bare-metal can be convenient, because debuggers and generally just interacting with the processes for development reasons is much more convenient when they’re not hidden inside a container.

If you’re clever about the build and leverage something like dream2nix to its fullest potential, you might also end up with faster builds than you would with a Dockerfile calling npm, which would directly improve cycle time.

IMO those are the main advantages running services from a nix shell has over docker-compose - the latter can even be achieved if you still use docker-compose for actually spinning up the development environment.

As a side benefit you become more resilient to leftpad incidents. Just make sure you have a reasonable source mirroring process on top of all of this.

I think this would be my angle here; having a tool that can easily spin up a testing env is great, and it significantly reduces the amount of stuff new team members need to learn immediately to get to working on the project when they join.

So, get nix to build the docker images, and have it launch docker-compose with those images to actually get them running correctly. Then in the long term angle for getting rid of docker-compose as well (probably replacing it with devenv), since it slowly becomes an unnecessary middle man that just makes debugging harder.

As part of this you’ll probably also end up being able to build the project with nix-build if you really want to, but that will almost certainly remain slower and less convenient than just using npm for simpler development flows (especially given how addicted the web ecosystem is to those rebuild-to-refresh browser flows, which will be practically impossible to achieve with nix).

Ironically, this may mean that you want to add a way to call nix from npm at some point :wink:

You can even consider trying out podman to see if you can remove the requirement of installing docker, since podman doesn’t need a system service.

I think nix is unlikely to improve your development flow much in any other area. The web dev ecosystem is just too npm-centric - if you run into issues no amount of stackoverflow or complaining upstream will be able to help you, the rest of the world will just be disinterested. And for better or worse, many developers need stackoverflow, and all of us are subject to the decisions of some upstream, lest we incur additional maintenance burden to keep patches for our own use cases alive.

1 Like

Just as a side note, I personally use npm on bare NixOs by enabling nix-ld. Quite practical since npm really like pre-built binaries (looking at you electron), this way I can develop quick and dirty applications like in any other system.

I think that’s good for quick-and-dirty, but in a serious project probably the opposite of what you want to do. Nix gives you a chance to actually know where you may be leftpadded or have potential licensing issues, nix-ld removes a lot of that capability.

If you’re going to spend time on developing better build infrastructure anyway, might as well just build the random binaries people want you to download.

Might be a tad harder with electron, in fairness, but I don’t think that’s as much of an issue for the kind of project described here.

Yeah definitely, but when prototyping it might be convenient to just copy/paste regular instructions without worrying about setting-up dream2nix or alike (I remember having annoying bugs with it at some points, where dream2nix was not providing the good version etc, maybe it is fixed now).

1 Like