nix-container-images
nix-container-images copied to clipboard
Write container images as NixOS machines
Declarative container images with Nix
warning: this project is no longer maintained
With this project you can
- make your image composable (thanks to the NixOS modules system)
- integrate the s6 init system in your images
- reuse some NixOS modules in a container... without relying on systemd
- make a Nix a Docker image, built by Nix
Getting started
To build a Docker image named hello
that runs hello
.
lib.makeImage (
{ pkgs, ... }: {
config.image = {
name = "hello";
entryPoint = [ "${pkgs.hello}/bin/hello" ];
};
})
-
To build an empty image from CLI,
nix-build -E 'with import ./default.nix{}; lib.makeImage{ config.image.name = "empty"; }'
-
To use
lib.makeImage
in your project, addoverlay.nix
to your nixpkgs overlay list.
The image
module section for more information.
Use s6 as init system to run services
The s6 module can be used to build an image with an init
system. The s6 init system is
used to run defined s6.services
.
lib.makeImage ({ pkgs, ... }: {
config = {
image.name = "s6";
s6.services.nginx = {
execStart = ''${pkgs.nginx}/bin/nginx -g "daemon off;"'';
};
};
})
Some goals of using an init system in a container are
- Proper PID 1 (no zombie processes)
- Run several services in one container
- Processes debugging (if the process is killed or died, the container is not necessarily killed)
- Execute initialization tasks
See s6 module for details.
(Re)Use NixOS modules
Some NixOS modules can be used, such as users
, etc
.
lib.makeImage ({ pkgs, ... }: {
config = {
image.name = "nixos";
environment.systemPackages = [ pkgs.coreutils ];
users.users.alice = {
isNormalUser = true;
};
};
})
See also supported NixOS modules.
Systemd support for NixOS modules :/
It is possible to run some NixOS modules defining systemd services thanks to a partial systemd implementation with s6.
Note this implementation is fragile, experimental and partial!
lib.makeImage ({ pkgs, ... }: {
config = {
image.name = "nginx";
# Yeah! It is the NixOS module!
services.nginx.enable = true;
};
})
Predefined images
- nix: basic single user installation
These images can be built with nix-build -A dockerImages
.
More configurations and images are also available in the tests directory.
Module image
The image
module defines common Docker image attributes, such as the
image name, the environment variables, etc. Please refer to
the image
options documentation.
Module s6
This module allows you to easily create services, managed by the s6 init system. Three types of services can be defined:
-
oneshot-pre
services are exectued sequentially at container start time and must terminate. They can be ordered thanks to theafter
option. -
long-run
services are for daemons and are managed bys6
. There is no notion of dependency forlong-run
services. -
oneshot-post
services are executed sequentially once alllong-run
services have been started. They can also be ordered (after
option). They are generally used to provision started services.
Options are described in this
generated s6
options documentation.
How/when s6 main process is terminated
By default, if a s6 service fails, the s6-svcscan
(PID 1 in a
container) process is terminated. A long-run
service can set the
restartOnFailure
option to true
to restart the service when it
fails.
If the S6_DONT_TERMINATE_ON_ERROR
environment variable is set,
s6-svscan
is not terminated on service failure. This can be used to
debug a failing service interactively.
Supported NixOS modules
-
users
: create users and groups -
nix
: configure Nix -
environment.etc
: create files in/etc
-
systemd
: a small subset of the systemd module is implemented with s6 -
nginx
: see its test
Important: only a small subset of NixOS modules is supported. See the tests directory for supported (and tested) features.
Tests
- s6: s6 tests executed in the Nix build environment (fast to run but limited)
- dockerImages: tests on Docker images executed in a NixOS VM.
Implementation of the NixOS systemd service interface
A subset of the NixOS systemd services interface is supported and implemented with the s6 init system.
There are several differences with the NixOS systemd implementation. The main one is the service dependency model:
- Services of type
simple
becomelong-run
s6 services and dependencies are ignored. - Services of type
oneshot
becomeonehost-pre
s6 services except if they have anafter
dependency to asimple
service. In this case, they becomeoneshot-post
. Dependencies between oneshot services are respected.
Tips
- To generate and run the container init script as user
nix-build -A dockerImages.example-systemd.init ./result S6-STATE-DIR
- To get the image used by a test
nix-build -A tests.dockerImages.nginx.image
- The NixOS config of an image
nix-instantiate --eval -A tests.dockerImages.nginx.image.config
- The NixOS config of an s6 test
nix-instantiate --eval -A tests.s6.path.config.systemd
Related projects
Contributing
Contributions to nix-container-images through PRs are always welcome. All PRs will be automatically tested by the Hydra CI server.