Skip to content

Instantly share code, notes, and snippets.

@datakurre
Last active December 29, 2022 10:29
Show Gist options
  • Save datakurre/a5d95794ce73c28f6d2f to your computer and use it in GitHub Desktop.
Save datakurre/a5d95794ce73c28f6d2f to your computer and use it in GitHub Desktop.
Minimal Nix Docker
*.tar.gz
.sentinel.*

Minimal Nix Docker

This gist creates such a minimal (yet opinionated) Nix image for Docker that the image will mostly the files included in the Nix installer and a copy of the latest Nixpkgs.

Bootstrapping

Build a Docker image named nix using the provided Docker based build chain:

$ git clone https://gist.github.com/datakurre/a5d95794ce73c28f6d2f
$ cd a5d95794ce73c28f6d2f
$ IMAGE_NAME=nix IMAGE_TAG=latest make

Create a Docker data container named nix to use shared persistent /nix for all run containers.

$ docker create --name nix -v /nix nix sh

To know more about where the nix data gets stored with this setup, please, read Docker documentation about managing data in containers.

Examples of use

Running a Python interpreter with some packages:

$ docker run --rm --volumes-from=nix -ti nix \
         nix-shell -p pythonPackages.pillow --run python

Running a Haskell Jupyter notebook with mounted context:

$ mkdir .jupyter
$ echo "c.NotebookApp.ip = '*'" > .jupyter/jupyter_notebook_config.py
$ docker run --rm --volumes-from=nix -ti \
         -v $PWD:/mnt -w /mnt -e HOME=/mnt -p 8888 nix \
         nix-shell -p ihaskell --run "ihaskell-notebook"

Building a docker image by using Nix docker tools based expression:

$ docker run --rm --volumes-from=nix -v $PWD:/build:ro -w /build nix \
         bash -c "cat \`nix-build release.nix -A image --no-out-link \`" \
         | docker load

Adding --help for nix-commands:

$ docker run --rm --volumes-from=nix nix nix-env -i man
$ docker run --rm --volumes-from=nix nix nix-env --help

Purging nix-store cache:

$ docker run --rm --volumes-from=nix nix nix-collect-garbage -d

Some technical details

  • Nixpkgs is stored at /var/nixpkgs so you can override it with your own local version with -v /local/path/to/my/nixpkgs:/var/nixpkgs.

  • By default nix-env operates on the default profile at /nix/var/nix/profiles/default, which is conveniently symlinked into /usr/local.

  • For convenience, the image also contains:

    • Bash build at /nix/var/nix/profiles/bash symlinked into /bin.
    • All the other binaries from Nix-installer are symlinked into /usr/bin.
    • CACerts build at /nix/var/nix/profiles/cacert.

    All the above are simple symlinks to the packages at Nix store provided by the Nix installer. They are included in the default PATH, but only after the default profile.

Of course, all the above could be customized simply by forking this recipe.

#!/bin/sh
VERSION=1.11.2
BASEURL=http://nixos.org/releases/nix
BASENAME=nix-$VERSION-x86_64-linux
FILENAME=$BASENAME.tar.bz2
# Download and unpack
wget -O- $BASEURL/nix-$VERSION/$FILENAME | bzcat - | tar xf -
# Prepare build directory
mkdir -p build/etc/nix build/nix/var/nix/profiles \
build/tmp build/bin build/usr/bin build/var build/root
cat > build/etc/passwd << EOF
root:*:0:0:::
nixbld1:*:30001:30000:::
nixbld2:*:30002:30000:::
nixbld3:*:30003:30000:::
nixbld4:*:30004:30000:::
nixbld5:*:30005:30000:::
nixbld6:*:30006:30000:::
nixbld7:*:30007:30000:::
nixbld8:*:30008:30000:::
nixbld9:*:30009:30000:::
nixbld10:*:30010:30000:::
EOF
cat > build/etc/group<< EOF
nixbld:x:30000:nixbld1,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9,nixbld10
EOF
# Symlink the default profile to /usr/local
ln -s /nix/var/nix/profiles/default build/usr/local
ln -s /nix/var/nix/profiles/default build/root/.nix-profile
# Move Nix store into build directory
mv $BASENAME/store build/nix
mv $BASENAME/.reginfo build/nix/store
# Symlink bash binaries into /bin
BASH=`find build -name "*-bash-*"|grep -o "/.*"`
ln -s $BASH/bin/bash build/bin
ln -s $BASH/bin/sh build/bin
# Symlink channel to be
mkdir -p build/var/nixpkgs build/root/.nix-defexpr
# Configure nixpkgs
mkdir -p build/root/.nixpkgs
echo "{ allowBroken = true; }" > build/root/.nixpkgs/config.nix
# Fix permissions
find build -type d -print0 |xargs -0 chmod 0555
find build -type f -print0 |xargs -0 chmod ugo-ws
find build/nix/var -type d -print0 |xargs -0 chmod 0755
chmod 0755 build/nix/store
chmod 0777 build/tmp
chmod -R 0700 build/root
# Create tarball
tar cz . -C build
FROM scratch
ADD nix.tar.gz /
ENV HOME="/root" TERM="linux" \
PATH="/usr/local/bin:/usr/bin:/bin" \
SSL_CERT_FILE="/usr/local/etc/ssl/certs/ca-bundle.crt" \
SYSTEM_CERTIFICATE_PATH="/usr/local/etc/ssl/certs/ca-bundle.crt" \
NIX_PATH="nixpkgs=/root/.nix-defexpr/channels/nixpkgs"
RUN /nix/store/*-nix-*/bin/nix-store --init && \
/nix/store/*-nix-*/bin/nix-store --load-db < /nix/store/.reginfo && \
/nix/store/*-nix-*/bin/nix-env -i \
/nix/store/*-nix-* /nix/store/*-coreutils-* \
/nix/store/*-curl-* /nix/store/*-cacert-* /nix/store/*-gnutar-* \
/nix/store/*-xz-* /nix/store/*-gzip-* /nix/store/*-bzip2-* && \
nix-channel --add https://nixos.org/channels/nixos-unstable nixpkgs && \
nix-channel --update && \
nix-env -i bash-interactive iana-etc which && \
ln -sf /usr/local/bin/env /usr/bin && \
ln -sf /usr/local/bin/bash /bin && \
ln -sf /usr/local/bin/sh /bin && \
ln -sf /usr/local/etc/* /etc && \
nix-collect-garbage -d
RUN chown 0:0 -R /bin /etc /usr /var /tmp
IMAGE_NAME ?= docker.kopla.jyu.fi/tools/nix
IMAGE_TAG ?= $(CI_BUILD_REF_NAME)
# Defaults to current git tag, or branch if no tag
CI_BUILD_REF_NAME ?= $(shell git describe --tags --exact-match 2>/dev/null || git name-rev --name-only HEAD)
all: build
build: Dockerfile nix.tar.gz
docker build --rm -t "$(IMAGE_NAME):$(IMAGE_TAG)" .
dist: build
docker build --rm -t "$(IMAGE_NAME):$(IMAGE_TAG)" .
push:
docker push "$(IMAGE_NAME):$(IMAGE_TAG)"
clean:
rm -f nix.tar.gz
clean-image:
docker rmi "$(IMAGE_NAME):$(IMAGE_TAG)" || true
###
.PHONY: all build dist push clean clean-image
nix.tar.gz: bootstrap.sh
cat bootstrap.sh | docker run --rm -i busybox sh > nix.tar.gz
@jafonsor
Copy link

Thanks a lot for sharing this. Great work!

@zopieux
Copy link

zopieux commented Feb 15, 2020

Nix is now distributed in tar.xz files, making bootstrap.sh obsolete. My fork should work for Nix 2.3.2 (latest stable as of today).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment