Go to file
2024-01-04 21:59:33 -05:00
.gitea/workflows CI: Clean up tests 2024-01-01 22:59:04 -05:00
.envrc Initial commit 2023-07-15 16:37:59 -04:00
.gitignore Place /etc/passwd file inside the container for root user 2023-12-29 12:03:48 -05:00
channels.scm channels.scm: Update guix channel 2023-12-31 14:34:06 -05:00
Dockerfile Dockerfile: Adjust file permissions; add comments; tidy formatting 2024-01-01 23:18:40 -05:00
Makefile Makefile: Do not mount /etc/ssl when running 2024-01-04 21:41:32 -05:00
manifest-dev.scm manifest-dev.scm: Add gzip to development manifest 2024-01-01 22:58:31 -05:00
manifest.scm manifest.scm: Add utf8 glibc-locals for US and CA 2023-12-31 14:15:34 -05:00
README.org README.org: Add section about local image usage; cleanup 2024-01-04 21:59:33 -05:00
shell.sh Initial commit 2023-07-15 16:37:59 -04:00

Guix Builder

This repository defines a minimal OCI container containing guix and a few other tools useful for CI/CD jobs. The container is expected to be run from a system that already has the guix-daemon installed and running, and is most useful in the context of existing CI/CD tools that already use an existing OCI container runtime (eg. docker, podman, etc..).

Prerequisites

  • guix-daemon installed and running on the host
  • dockerd to build and run the produced image
  • direnv (optional)

Repository Structure

channels.scm
Guix Channel File.
Dockerfile
From scratch image that uses guix pack tar.gz output.
Makefile
Various make targets to build and run the guix-builder OCI image.
manifest-dev.scm
Packages required for development.
manifest.scm
Packages to be installed in the OCI image.
.gitignore
Files ignored by git.
README.org
Org-mode1 documentation.
shell.sh
Launch a containerized development shell.

Guix Channel File

Guix channels2 allow for Guix to be customized and extended. They are also critical for replicating a Guix system3. To ensure reproducibility, a channels.scm file is provided in this repository that is expected to be used during deployment. It pins external guix channels to specific versions.

Setup development environment

direnv is the preferred and optimal way to enter a development environment. Use direnv allow.

Alternatively, ./shell.sh can be invoked directly

Building the image

  make [build]

build is optional, as its the default target.

Testing and using the image locally

The easiest way to use and test the guix-builder container image is to use the provide make target.

  make run

Or, if you want to run in a container with no guix store mounted.

  make run-no-store

Using the image

Now that the OCI image has been produced, some care must be taken when running it. Namely, the following volumes are expected to be mounted.

/var/guix/daemon-socket/socket
the guix-daemon socket
/gnu/store
The hosts guix store

Additionally, for guix to function appropriately, the HOME environment variable must be set. This allows guix to store its cache (mandatory for many operations, eg guix pull). Depending on use-case, it is sometimes useful to retain the guix cache between container invocations. To do so, mount a volume to $HOME/.cache/guix (replacing $HOME with what it will be set to within the container).

SSL certificates are included and configured for use in the container (via the nss-certs package). Its not supported to use your hosts certificates, as they may be incompatible with openssl inside of the container.

A complete example is given below, where the aforementioned volumes are mounted, HOME is set to /tmp, and a volume for retaining the guix cache between invocations is put in place. The working directory within the container is also set with the -w option, however this is not required.

  docker run --rm -it \
   -v /var/guix/daemon-socket/socket:/var/guix/daemon-socket/socket \
   -v /gnu/store:/gnu/store:ro \
   -v /var/lib/ci/guix-cache:/tmp/.cache/guix \
   -e HOME=/tmp \
   -w /tmp \
   guix-builder:latest

Using the image with Gitea/Forgejo actions or DroneCI/WoodpeckerCI

The primary use-case for the image produced by this repository is for ci/cd jobs (mandatorily on a host that is running guix-daemon itself). This allows for the hosts guix store to be reused, allowing for a node-local caching layer, and enabling optimal ci/cd build/deploy times.

Any ci/cd tool that can run OCI containers should be compatible with this image, though the optimal setup assumes it provides a mechanism to mount volumes and set environment variables (by an administrator). Both DroneCI and WoodpeckerCI allow for this, using DRONE_RUNNER_VOLUMES and WOODPECKER_BACKEND_DOCKER_VOLUMES respectively. Gitea/Forgejo actions allow it via the container.options configuration value.

Note, in WoodpeckerCI, this functionality has not yet made it into a release (see PR).

FAQ

Why not produce this image with guix pack -f docker ... directly?

One may ask, why not simply produce a OCI container using guix pack directly? Eg.

  guix pack -f docker -S /bin=bin --entry-point=bin/guix -m manifest.scm

Well, I'm glad you asked! This produces a container that has the guix store in its default location /gnu/store. Using the same method as described in Using the image with DroneCI / WoodpeckerCI, this container image works, however it has an implicit constraint: all store items used within the pack must also exist in the hosts guix store. This is because the guix store is volume mounted into the container at runtime, shadowing the already existing /gnu/store directory put in place via guix pack. There are ways one could work around this constraint, however the best solution would be to have a guix container that is independent of the host (as described in this repository).

What about running a guix-daemon within a container (so that builds can be completely isolated)?

This currently is not possible … TBD (more detail)

Footnotes