Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others


0 votes
in Technique[技术] by (71.8m points)

node.js - How do I include my source code in Nix Docker Tools image?

I'm building a web server using NodeJS, and I'm using the Docker Tools that Nix provides to build images for my server.

I have the following Dockerfile that I'm tring to convert into a .nix file

FROM node:12.20.0-alpine3.11 as build-deps
WORKDIR /hedwig-app
COPY ["package.json", "package-lock.json*", "./"]
RUN npm install
COPY . .
RUN npm run build
CMD [ "node", "build/index.js" ]

However, I don't know how to copy my source code into the Docker image to be built. This is what I have so far

{ pkgs ? import <nixpkgs> {} }:

    baseImage = pkgs.dockerTools.pullImage {
        imageName = "alpine";
        imageDigest = "sha256:3c7497bf0c7af93428242d6176e8f7905f2201d8fc5861f45be7a346b5f23436";
        sha256 = "119pbb2nrhs6nvbhhpcd52fqy431ag46azgxvgdmyxrwii97f4ah";
        finalImageName = "alpine";
        finalImageTag = "3.12";
    sourceFiles = builtins.toString ./.;
    gitignoreSrc = pkgs.fetchFromGitHub { 
        owner = "hercules-ci";
        repo = "gitignore";
        # put the latest commit sha of gitignore Nix library here:
        rev = "c4662e662462e7bf3c2a968483478a665d00e717";
        # use what nix suggests in the mismatch message here:
        sha256 = "sha256:1npnx0h6bd0d7ql93ka7azhj40zgjp815fw2r6smg8ch9p7mzdlx";
    inherit (import gitignoreSrc { inherit (pkgs) lib; }) gitignoreSource;
    src = gitignoreSource ./.;
    pkgs.dockerTools.buildImage {
        name = "hedwig-api";
        tag = "latest";

        fromImage = baseImage;
        contents = [ pkgs.nodejs ];
        runAsRoot = ''
        mkdir /hedwig-app
        cp -r ${src} /hedwig-app
        npm install
        npm run build

        config = {
            ExposedPorts = {
                "8080/tcp" = {};
            WorkingDir = "/hedwig-app";
            Cmd = ["node" "build/index.js"];

How could I copy my source code into the image before running npm run build?

Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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.

Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share