This project relied on https://channels.nix.gsc.io/ to get commits to nixos channels. This website is no longer updated so no new Docker images are built and uploaded to Docker Hub. If you want to built one image manually, see #23.
We are no longer maintaining this project. Reach out if you want to take over.
This project automatically generates Docker images for nixpkgs channels. The images come with a prefetched nixpkgs, corresponding to the image tag, which is the nixpkgs commit hash. All basic Nix utilities are preinstalled, including Cachix. Also included is the export-profile
script, allowing super minimal images via multi-stage builds.
See the Usage section for how to use it in your project.
All images come prefetched with the nixpkgs version corresponding to the image tag. So the image niteo/nixpkgs-nixos-20.03:14006b724f3d1f25ecf38238ee723d38b0c2f4ce
contains a prefetched tarball of 14006b724f3d. This allows Nix builds that pin nixpkgs to that version to start quickly, without having to first fetch and unpack a tarball.
All images come preinstalled with a basic set of dependencies needed for working with Nix. This currently includes Cachix and all dependencies of Nix, but may be expanded in the future as the need arises. Since the intent is to use these images as the first stage in a multi-stage build, they won't influence the final image size, allowing the addition of more tools without a significant cost.
These dependencies notably come from the very nixpkgs version that is prefetched. If you need these tools or their dependencies in a Nix build, this saves you the cost of having to download them.
Every hour, a GitHub Action runs to detect any nixpkgs channel updates, in which case a new Docker image is built and pushed to DockerHub with the corresponding tag.
Additionally, if this repository changes how images are built, the image tags corresponding to the latest channel versions are updated to incorporate these changes. This is the only way in which tagged images are updated, meaning once a nixpkgs channel commit is outdated, its image won't get updated anymore. So if this repository receives an update, you need to update nixpkgs to the latest version of the channel.
All images contain the export-profile
utility, which allows easy creation of a final stage in Docker multi-stage builds. The resulting image then contains only exactly the dependencies needed to run the programs you specify, nothing else.
To use this for your project, you should ensure that the prefetched nixpkgs tarball can be used, such that builds can start as fast as possible. This requires that you pin nixpkgs to the nixpkgs commit of the channel that you wish to use. Specifically, the Nix expression that evaluates to the prefetched version is
fetchTarball {
name = "nixpkgs-src";
url = "https://github.com/NixOS/nixpkgs/archive/<commit>.tar.gz";
sha256 = "<sha256>";
}
Note that choosing the name as nixpkgs-src
is very important, because Nix can only reuse a prefetched version if the name matches.
Only Nix channels specified in channel matrix in the push workflow are available, but new ones may be added over time.
Using Niv
If you use Niv to manage your nixpkgs source, you need to ensure the following:
- The
nix/sources.nix
file was generated by a Niv version after this change - The nixpkgs Niv package is named
nixpkgs
. These two points are necessary for Niv to name the tarballnixpkgs-src
- The branch of the nixpkgs Niv package points to the nixpkgs channel you wish to use. This ensures that you don't update to unavailable commits
For a new project wanting to use the nixos-20.03
channel, this can be done with:
niv init
niv modify nixpkgs -b nixos-20.03
niv update nixpkgs
For regenerating the nix/sources.nix
in an existing project, you can run
rm nix/sources.nix
niv init
Finally, use the following command to check the tarballs name. It needs to end with nixpkgs-src
for the prefetched nixpkgs to apply:
nix-instantiate --eval -E '(import nix/sources.nix).nixpkgs.outPath
=> "/nix/store/r07cldfsnr8kvkr1kpsc6jf6bibfc1mg-nixpkgs-src"
If it ends with -source
, make sure to use a more recent Niv version.
To use this project, you need a Nix expression in your project that ideally exposes a single derivation as an attribute for installation. A convenient helper for this is pkgs.buildEnv
, which allows you to build a derivation that combines multiple other derivations into one. Here is an example default.nix
, showing how pkgs.buildEnv
can be used to create an environment with both pkgs.curl
and pkgs.cacert
in it:
let
# Without niv
pkgs = fetchTarball {
name = "nixpkgs-src";
url = "https://github.com/NixOS/nixpkgs/archive/<commit>.tar.gz";
sha256 = "<sha256>";
};
# With niv
pkgs = (import nix/sources.nix).nixpkgs;
in {
myEnv = pkgs.buildEnv {
name = "env";
paths = with pkgs; [
curl
cacert
];
};
}
The base images are made available under Niteo on DockerHub as niteo/nixpkgs-<channel>:<commit>
. With the Dockerfile being in the same directory as the projects default.nix
file, you can install any exposed attribute of that file with the following basic Dockerfile structure
FROM niteo/nixpkgs-<channel>:<commit> AS build
# Import the project source
COPY . src
RUN \
# Install the program to propagate to the final image
nix-env -f src -iA myEnv \
# Exports a root directory structure containing all dependencies
# installed with nix-env under /run/profile
&& export-profile /dist
# Second Docker stage, we start with a completely empty image
FROM scratch
# Copy the /dist root folder from the previous stage into this one
COPY --from=build /dist /
# Set PATH so Nix binaries can be found
ENV PATH=/run/profile/bin
The main idea of export-profile <root>
is to export the default nix-env
profile with all its dependencies into <root>
, such that the next build stage only needs to initialize its root directory with <root>
from the previous stage. In more details, the script currently does:
- Symlink to the default
nix-env
profile from<root>/run/profile
- If the profile contains an
etc
directory, it symlinks to it from<root>/etc
. This behavior mirrors NixOS, and allows for files like/etc/bashrc
to take effect - If the profile contains a
bin/env
(usually frompkgs.coreutils
) orbin/sh
(usually frompkgs.bashInteractive
), it symlinks to those from<root>/usr/bin/env
and<root>/bin/sh
respectively. These are standard POSIX executable paths. - All Nix store paths the profile depends on are copied to
<root>/nix/store
. This ensures that any previously established symlinks actually work.
If you require binaries like curl
in the final image, you need to make sure that they can find SSL root certificates. To do this:
- Install
pkgs.cacert
in thebuild
stage, either by adding it to the environment of the attribute you install, or with an additional nix-env command likenix-env -f '<nixpkgs>' -iA cacert
- Set the
NIX_SSL_CERT_FILE
environment variable as follows in the final stageENV NIX_SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt
Since the nixpkgs commit is embedded into the Dockerfile, it should be kept in sync with the nixpkgs of your Nix files to ensure it being as efficient as possible. So if you update your nixpkgs source to a newer channel commit, be sure to update it in the Dockerfile as well.
If you manage your nixpkgs source with niv
, this can be achieved automatically with the following commands:
niv update nixpkgs
channel=$(jq -r .nixpkgs.branch nix/sources.json)
rev=$(jq -r .nixpkgs.rev nix/sources.json)
sed -i "s#FROM.*AS build#FROM niteo/nixpkgs-$channel:$rev AS build#g" Dockerfile
This image has built-in helpers for setting up a tmate connection to the image, useful for debugging when running in CI:
start-tmate [maxIdle]
: Starts a tmate session, which is persisted untilmaxIdle
(by default 60) seconds pass without any connection. The command only exits once this has occured.bash-tmate
: A drop-in replacement for bash that runsstart-tmate
when the bash command fails. Useful as a shell for CI scripts, allowing debugging in case of failures.
This section is only intended for developers/contributors of this project. Feel free to contribute by opening a PR or open issues for enquiries.
A new channel can be added by editing the channel matrix in push.yml workflow to contain the one you want.
New tools for the base image can be added under Extra tools
in image.nix.
- A DockerHub account. Insert your username for
REGISTRY_USER
in the push.yml workflow, and set up the password as aREGISTRY_PASSWORD
secret for the repository. This is of course needed to update images on DockerHub. Other container registries could work too, but the code needs to be adjusted for that. - A Cachix cache for speeding up CI. Set the Cachix name under the
cachix-action
s in the push.yml workflow, and add the signing key as theCACHIX_SIGNING_KEY
secret in the repository.
- This project was originally forked from https://github.com/nix-community/docker-nixpkgs, but almost no code remains unchanged.
- The official Nix docker images at https://github.com/nixos/docker.
- Nixery is a pretty cool service that builds docker images from nixpkgs attributes on the fly.