All Projects → nlewo → nix2container

nlewo / nix2container

Licence: Apache-2.0 license
An archive-less dockerTools.buildImage implementation

Programming Languages

go
31211 projects - #10 most used programming language
Nix
1067 projects

Projects that are alternatives of or similar to nix2container

nix-portable
Nix - Static, Permissionless, Installation-free, Pre-configured
Stars: ✭ 356 (+167.67%)
Mutual labels:  nix, nixos
dotfiles
Dotfiles
Stars: ✭ 25 (-81.2%)
Mutual labels:  nix, nixos
impermanence
Modules to help you handle persistent state on systems with ephemeral root storage [maintainer=@talyz]
Stars: ✭ 401 (+201.5%)
Mutual labels:  nix, nixos
nix-xdg
[WIP] Nix overlay for making programs xdg compliant
Stars: ✭ 18 (-86.47%)
Mutual labels:  nix, nixos
nixpkgs
Nix Packages collection used in Nubank
Stars: ✭ 24 (-81.95%)
Mutual labels:  nix, nixos
nix-config
A collection of my system configs and dotfiles
Stars: ✭ 35 (-73.68%)
Mutual labels:  nix, nixos
flake-utils-plus
Use Nix flakes without any fluff.
Stars: ✭ 280 (+110.53%)
Mutual labels:  nix, nixos
nixos-installer
Combining the power of Nix, Guile & Elm to install NixOS
Stars: ✭ 14 (-89.47%)
Mutual labels:  nix, nixos
nix-articles
Some articles about getting started with Nix programming & configuration
Stars: ✭ 134 (+0.75%)
Mutual labels:  nix, nixos
dotfiles-nix
Configuration files for my NixOS machine, declared by home-manager
Stars: ✭ 137 (+3.01%)
Mutual labels:  nix, nixos
elemental
Elemental, the component parts of a Nix/OS development system.
Stars: ✭ 44 (-66.92%)
Mutual labels:  nix, nixos
nix-home
A Nix Home Manager setup. I've now moved to a new configuration system at hugoreeves/elemental
Stars: ✭ 60 (-54.89%)
Mutual labels:  nix, nixos
nix-configs
My Nix{OS} configuration files
Stars: ✭ 54 (-59.4%)
Mutual labels:  nix, nixos
nixos-configuration
A repo for my nixos configuration files
Stars: ✭ 20 (-84.96%)
Mutual labels:  nix, nixos
dns.nix
A Nix DSL for DNS zone files
Stars: ✭ 69 (-48.12%)
Mutual labels:  nix, nixos
crane
A Nix library for building cargo projects. Never build twice thanks to incremental artifact caching.
Stars: ✭ 348 (+161.65%)
Mutual labels:  nix, nixos
nix-gaming
Gaming on Nix
Stars: ✭ 142 (+6.77%)
Mutual labels:  nix, nixos
comma
Comma runs software without installing it. [maintainers=@Artturin,@burke,@DavHau]
Stars: ✭ 626 (+370.68%)
Mutual labels:  nix, nixos
nixvim
Configure Neovim with Nix!
Stars: ✭ 120 (-9.77%)
Mutual labels:  nix, nixos
presentations
Presentations at the Tokyo Nixos Meetup
Stars: ✭ 57 (-57.14%)
Mutual labels:  nix, nixos

nix2container

warning: nix2container is in early development stages and interfaces are not stable

nix2container provides an efficient container development workflow with images built by Nix: it doesn't write tarballs to the Nix store and allows to skip already pushed layers (without having to rebuild them).

This is based on ideas developped in this blog post.

Getting started

{
  inputs.nix2container.url = "github:nlewo/nix2container";

  outputs = { self, nixpkgs, nix2container }: let
    pkgs = import nixpkgs { system = "x86_64-linux"; };
    nix2containerPkgs = nix2container.packages.x86_64-linux;
  in {
    packages.x86_64-linux.hello = nix2containerPkgs.nix2container.buildImage {
      name = "hello";
      config = {
        entrypoint = ["${pkgs.hello}/bin/hello"];
      };
    };
  };
}

This image can then be loaded into Docker with

$ nix run .#hello.copyToDockerDaemon
$ docker run hello:latest
Hello, world!

More Examples

To load and run the bash example image into Podman:

$ nix run github:nlewo/nix2container#examples.bash.copyToPodman
$ podman run -it bash

Functions documentation

nix2container.buildImage

Function arguments are:

  • name (required): the name of the image.

  • tag (defaults to the image output hash): the tag of the image.

  • config (defaults to {}): an attribute set describing an image configuration as defined in the OCI image specification.

  • copyToRoot (defaults to null): a derivation (or list of derivations) copied in the image root directory (store path prefixes /nix/store/hash-path are removed, in order to relocate them at the image /).

    pkgs.buildEnv can be used to build a derivation which has to be copied to the image root. For instance, to get bash and coreutils in the image /bin:

    copyToRoot = pkgs.buildEnv {
      name = "root";
      paths = [ pkgs.bashInteractive pkgs.coreutils ];
      pathsToLink = [ "/bin" ];
    };
    
  • fromImage (defaults to null): an image that is used as base image of this image.

  • maxLayers (defaults to 1): the maximum number of layers to create. This is based on the store path "popularity" as described in this blog post. Note this is applied on the image layers and not on layers added with the buildImage.layers attribute.

  • perms (defaults to []): a list of file permisssions which are set when the tar layer is created: these permissions are not written to the Nix store.

    Each element of this permission list is a dict such as

    { path = "a store path";
      regex = ".*";
      mode = "0664";
    }
    

    The mode is applied on a specific path. In this path subtree, the mode is then applied on all files matching the regex.

  • initializeNixDatabase (defaults to false): to initialize the Nix database with all store paths added into the image. Note this is only useful to run nix commands from the image, for instance to build an image used by a CI to run Nix builds.

  • layers (defaults to []): a list of layers built with the buildLayer function: if a store path in deps or contents belongs to one of these layers, this store path is skipped. This is pretty useful to isolate store paths that are often updated from more stable store paths, to speed up build and push time.

nix2container.pullImage

Function arguments are:

  • imageName (required): the name of the image to pull.

  • imageDigest (required): the digest of the image to pull.

  • sha256 (required): the sha256 of the resulting fixed output derivation.

  • os (defaults to linux)

  • arch (defaults to x86_64)

  • tlsVerify (defaults to true)

nix2container.buildLayer

For most use cases, this function is not required. However, it could be useful to explicitly isolate some parts of the image in dedicated layers, for caching (see the "Isolate dependencies in dedicated layers" section) or non reproducibility (see the reproducible argument) purposes.

Function arguments are:

  • deps (defaults to []): a list of store paths to include in the layer.

  • copyToRoot (defaults to null): a derivation (or list of derivations) copied in the image root directory (store path prefixes /nix/store/hash-path are removed, in order to relocate them at the image /).

    pkgs.buildEnv can be used to build a derivation which has to be copied to the image root. For instance, to get bash and coreutils in the image /bin:

    copyToRoot = pkgs.buildEnv {
      name = "root";
      paths = [ pkgs.bashInteractive pkgs.coreutils ];
      pathsToLink = [ "/bin" ];
    };
    
  • reproducible (defaults to true): If false, the layer tarball is stored in the store path. This is useful when the layer dependencies are not bit reproducible: it allows to have the layer tarball and its hash in the same store path.

  • maxLayers (defaults to 1): the maximum number of layers to create. This is based on the store path "popularity" as described in this blog post. Note this is applied on the image layers and not on layers added with the buildLayer.layers attribute.

  • perms (defaults to []): a list of file permisssions which are set when the tar layer is created: these permissions are not written to the Nix store.

    Each element of this permission list is a dict such as

    { path = "a store path";
      regex = ".*";
      mode = "0664";
    }
    

    The mode is applied on a specific path. In this path subtree, the mode is then applied on all files matching the regex.

  • layers (defaults to []): a list of layers built with the buildLayer function: if a store path in deps or contents belongs to one of these layers, this store path is skipped. This is pretty useful to isolate store paths that are often updated from more stable store paths, to speed up build and push time.

  • ignore (defaults to null): a store path to ignore when building the layer. This is mainly useful to ignore the configuration file from the container layer.

Isolate dependencies in dedicated layers

It is possible to isolate application dependencies in a dedicated layer. This layer is built by its own derivation: if storepaths composing this layer don't change, the layer is not rebuilt. Moreover, Skopeo can avoid to push this layer if it has already been pushed.

Let's consider an application printing a conversation. This script depends on bash and the hello binary. Because most of the changes concern the script itself, it would be nice to isolate scripts dependencies in a dedicated layer: when we modify the script, we only need to rebuild and push the layer containing the script. The layer containing dependencies won't be rebuilt and pushed.

As shown below, the buildImage.layers attribute allows to explicitly specify a set of dependencies to isolate.

{ pkgs }:
let
  application = pkgs.writeScript "conversation" ''
    ${pkgs.hello}/bin/hello
    echo "Haaa aa... I'm dying!!!"
  '';
in
pkgs.nix2container.buildImage {
  name = "hello";
  config = {
    entrypoint = ["${pkgs.bash}/bin/bash" application];
  };
  layers = [
    (pkgs.nix2container.buildLayer { deps = [pkgs.bash pkgs.hello]; })
  ];
}

This image contains 2 layers: a layer with bash and hello closures and a second layer containing the script only.

In real life, the isolated layer can contains a Python environment or Node modules.

Quick and dirty benchmarks

The main goal of nix2container is to provide fast rebuild/push container cycles. In the following, we provide an order of magnitude of rebuild and repush time, for the uwsgi image.

warning: this is quick and dirty benchmarks which only provide an order of magnitude

We build the container and push the container. We then made a small change in the hello.py file to trigger a rebuild and a push.

Method Rebuild/repush time Executed command
nix2container.buildImage ~1.8s nix run .#example.uwsgi.copyToRegistry
dockerTools.streamLayeredImage ~7.5s nix build .#example.uwsgi | docker load
dockerTools.buildImage ~10s nix build .#example.uwsgi; skopeo copy docker-archive://./result docker://localhost:5000/uwsgi:latest

Note we could not compare the same distribution mechanisms because

  • Skopeo is not able to skip already loaded layers by the Docker daemon and
  • Skopeo failed to push to the registry an image streamed to stdin.

Run the tests

nix run .#tests.all

This builds several example images with Nix, loads them with Skopeo, runs them with Podman, and test output logs.

Not that, unfortunately, these tests are not executed in the Nix sandbox because it is currently not possible to run a container in the Nix sandbox.

It is also possible to run a specific test:

nix run .#tests.basic

The nix2container Go library

This library is currently used by the Skopeo nix transport available in this branch.

For more information, refer to the Go documentation.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].