Inside Nix, you can't run npm install
. Each step can only do one of two things:
- either compute a new store path without network access: a regular derivation
- or produce an output that satisfies a hardcoded hash using a sufficiently simple* process that can access the network: a fixed output derivation
These constraints ensure that the build is highly likely to be reproducible.
npm install
needs access to the network in order to fetch its dependencies, which puts it in the fixed output derivation category. However, dockerTools.buildImage
will execute it in a regular derivation, so it will fail to contact the npmjs repository.
For this reason, we generally can't map a Dockerfile directly to a series of buildImage
calls. Instead, we can build the software with the Nix language infrastructures, like yarn2nix
, node2nix
or the various tools for other languages.
By doing so, your build becomes reproducible, it tends to be more incremental and you don't have to worry about source files or intermediate files ending up in your container images.
I'd also recommend to limit the contents
parameter to a pkgs.buildEnv
or pkgs.symlinkJoin
call, because the contents are copied to the root of the container while also remaining in its store.
*: sufficiently simple excludes anything beyond fetching a single resource, because that tends to be too fragile. If, for any reason, the fixed output derivation builder produces a different result and the only way to fix it is by changing the output hash, your entire build is essentially not reproducible.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…