Trying to create and copy a config file to use in Docker image

Hi All,

I’ve only been using Nix for a short amount of time, so far enjoying the ride. However today I’m stuck and no amount of googling/reading gives me the answer I’m looking for.

I’m trying to create a config file and copy it to the Docker image. I’m tried a few things and none seem to work. When I log in to the container the supervisord.conf file doesn’t exist. I’m sure I’m doing something silly but any pointers would be helpful.

{ pkgs ? import <nixpkgs> {}, pkgsLinux ? import <nixpkgs> { system = "x86_64-linux"; } }:

let
  supervisord = pkgs.writeTextDir "/etc/supervisor/supervisord.conf" ''
    [supervisord]
    nodaemon=true

    [program:example]
    command=/bin/sshd -D
  '';

in pkgs.dockerTools.buildImage {
  name = "nix";
  tag = "latest";
  copyToRoot = pkgs.buildEnv {
    name = "image-root";
    pathsToLink = [ "/bin" supervisord ];
     paths = [
      pkgs.bash
      pkgs.coreutils-full
      pkgs.python311Packages.supervisor
    ];
  };
  config = {
    Env = [
        "NIX_PAGER=cat"
        "USER=nobody"
      ];
    ExposedPorts = {
        "22/tcp" = { };
      };
  };
}

Haven’t tried this, so might be a shot in the dark, but the output of pkgs.writeTextDir is the path to a derivation, so you should put that into paths and add the inner path that you actually want to link to pathsToLink:

    pathsToLink = [ "/bin" "/etc" ];
     paths = [
      supervisord
      pkgs.bash
      pkgs.coreutils-full
      pkgs.python311Packages.supervisor
    ];
1 Like

Thank you so much for your help.

That worked!

When I tried this with /etc/ssh/sshd_config I got an error about collision between derivations.
Should I place the derivation from writeTextDir inside of contents instead of copyToRoot.paths?
Here is the flake setup I’ve used,

{
  # https://discourse.nixos.org/t/building-docker-image-with-dockertools-buildimage-and-flake-env/24936
  # https://ryantm.github.io/nixpkgs/builders/images/dockertools/
  # https://discourse.nixos.org/t/trying-to-create-and-copy-a-config-file-to-use-in-docker-image/30340
  inputs = {

    nixpkgs.url = "github:nixos/nixpkgs/nixos-23.05";
    flake-utils.url = "github:numtide/flake-utils";
  };
  description = "docker container for nfs server";

  outputs = { self, nixpkgs, flake-utils }:

    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
        ssh-config = pkgs.writeTextDir "/etc/ssh/sshd_config" (builtins.readFile ./config/sshd_config);
		# add same ssh keys across builds
        rsa_host = pkgs.writeTextDir "/etc/ssh/ssh_host_rsa_key" (builtins.readFile ./keys/ssh_host_rsa_key);
        ecdsa_host = pkgs.writeTextDir "/etc/ssh/ssh_host_ecdsa_key" (builtins.readFile ./keys/ssh_host_ecdsa_key);
        ed25519_host = pkgs.writeTextDir "/etc/ssh/ssh_host_ed25519_key" (builtins.readFile ./keys/ssh_host_ed25519_key);
      in
      {
        packages.nfs-server = pkgs.dockerTools.buildImage {
          name = "nfs";
          tag = "latest";
          copyToRoot = pkgs.buildEnv {
            name = "nfs-img";
            paths = [ ssh-config rsa_host ecdsa_host ed25519_host ] ++ (with pkgs; [ openssl nfs-utils krb5 openssh bash coreutils-full which iproute2 unixtools.procps ]); #packages to install inside docker container
            pathsToLink = [ "/bin" "/etc" ];
          };
          runAsRoot = ''
                        #!${pkgs.runtimeShell}
                        ${pkgs.dockerTools.shadowSetup}
                        groupadd -r sshd
                        useradd -r -g sshd sshd
                        mkdir /data
						# passwd is docker
						echo "root:$1$Zf99WdFX$kiUFVxOMM0B/hnym5WajX/" | chpasswd -e
                        chown sshd:sshd /data # dont need but will later
            			ssh-keygen -A
            			mkdir -p /var/empty
            			/bin/sshd -f /etc/ssh/sshd2_config # try adding this to config
          '';
          config = {
            ExposedPorts = { "2244/tcp" = { }; };
          };
        };
      }
    );

}

And the output of building.

warning: Git tree '/home/watashi/PARA/Projects/pount' is dirty
error: builder for '/nix/store/82dic9vhqnhhy0sfyl887yqfqrpz02x0-nfs-img.drv' failed with exit code 25;
       last 1 log lines:
       > error: collision between `/nix/store/h02zqhl4p9rm0k1zhq0hg009fgadn8p3-openssh-9.3p2/etc/ssh/sshd_config' and `/nix/store/z9scq6ngbg854v19zdbb7nj1h553yx6b-sshd_config/etc/ssh/sshd_config'
       For full logs, run 'nix log /nix/store/82dic9vhqnhhy0sfyl887yqfqrpz02x0-nfs-img.drv'.
error: 1 dependencies of derivation '/nix/store/i3sa2dqwkf01y0wf8wyd9w23fdaqwfj7-docker-layer-nfs.drv' failed to build
error: 1 dependencies of derivation '/nix/store/b3qdx76bjra588g00n0mlsnfvc0na48i-docker-image-nfs.tar.gz.drv' failed to build

Sorry for replying so late. In buildEnv there is an additional option called ignoreCollisions.

The error in your case comes from openssh trying to overwrite your custom config, so you need to change your invocation of buildEnv like this:

copyToRoot = pkgs.buildEnv {
  name = "nfs-img";
  paths = (with pkgs; [ openssl nfs-utils krb5 openssh bash coreutils-full which iproute2 unixtools.procps ])
    ++ [ ssh-config rsa_host ecdsa_host ed25519_host ] ;
  pathsToLink = [ "/bin" "/etc" ];
  ignoreCollisions = true;
};

Now, your custom config comes after openssh, so it will overwrite the default config, and that collision will be ignored.