I have three projects with three directories, a, b, and c.
Projects a and b are standalone things I build into a package and a docker container with just that package.
Directory a has a default.nix
and a.nix
and from directory a I can nix-build -A a
just fine.
Directory b has a default.nix
and a b.nix
and from directory b I can nix-build -A b
just fine.
In directory c I want to create a new project that includes the packages from a and b as well as some of its own content, and build these into a docker container.
I can’t figure out the syntax for this, and I haven’t been able to find documentation explaining how to do this. I’d appreciate any help or even just pointers to what documentation I should read to figure out how to do this.
From c/default.nix
, you could use an expression like import ../a {}
(passing whatever arguments, if any), or even import ../a/a.nix {}
, similar to what you might do to use a.nix
in default.nix
.
If those nix files have arguments, you might pass those in import ../a/a.nix { pkgs = pkgs; }
.
You could then access the a
attribute from a/default.nix
e.g. let aPkgs = import ../a {}; in .... aPkgs.a ....
.
(EDIT: if you don’t want to hard-code the relative paths of a
and b
in the c
code, then you could pass these as arguments to a function in c/default.nix
, or use some technique like that).
(These values can then be used as part of building a Docker image).
For reference:
Hm. User error. I just wasn’t sure where.
Before posting my question I had tried callPackage in the let binding, but then using that variable in the paths, it complains that the resulting store object /nix/store/.....-docker-image-a.tar.gz
is a file and can’t be merged into an environment using pkgs.buildEnv
Later I tried a few different methods using import, which (after I figured out how to inherit the arguments to pass along) resulted in similar errors.
This, and reading the replies above, has led me to believe that I’ve made a false assumption reguarding a an b. They produce a docker image, they don’t produce a package. The logic to produce the package is inside a let binding just before the call to build the package!
When I wrote a.nix
and b.nix
I didn’t know how to reference an external file – I didn’t even realize that the things in the files were function definitions until many re-readings of the documentation later, I assumed I had the syntax wrong – so I used a let binding to hold all of the logic for building the package (so a was bound to the package inside a.nix) and then I basically replaced the body of a.nix with the logic to build the docker image. The result was from default.nix in a, a = the docker image. From within a.nix, a = the package. So trying to use those in c.nix I was trying to put the docker tar result into my paths instead of the packages.
So, I need to change a and b to just produce a package.
I moved the container logic out into a-docker.nix and b-docker.nix. Then I put callPackage references to these in their respective default.nix
. In that container building logic I used let bindings to assign the project name variable to the package. Now I can build my containers with nix-build -A a-docker
, nix-build -A b-docker
but doing nix-build -A a
or nix-build -A b
generates just the package. So now I can use that from c.nix
with either callPackages or import and it works like it should.
1 Like