docker: format

This commit is contained in:
Sandro Jäckel 2021-08-10 10:24:15 +02:00
parent daa36171c0
commit ceb417aaf1
No known key found for this signature in database
GPG key ID: 3AF5A43A3EECC2E5

View file

@ -1,49 +1,47 @@
{ { bashInteractive
bashInteractive, , buildPackages
buildPackages, , cacert
cacert, , callPackage
callPackage, , closureInfo
closureInfo, , coreutils
coreutils, , e2fsprogs
e2fsprogs, , fakeroot
fakeroot, , findutils
findutils, , go
go, , jq
jq, , jshon
jshon, , lib
lib, , makeWrapper
makeWrapper, , moreutils
moreutils, , nix
nix, , pigz
pigz, , pkgs
pkgs, , rsync
rsync, , runCommand
runCommand, , runtimeShell
runtimeShell, , shadow
shadow, , skopeo
skopeo, , storeDir ? builtins.storeDir
storeDir ? builtins.storeDir, , substituteAll
substituteAll, , symlinkJoin
symlinkJoin, , util-linux
util-linux, , vmTools
vmTools, , writeReferencesToFile
writeReferencesToFile, , writeScript
writeScript, , writeText
writeText, , writeTextDir
writeTextDir, , writePython3
writePython3, , system
system, # Note: This is the cross system we're compiling for , # Note: This is the cross system we're compiling for
}: }:
let let
inherit (lib) mkDbExtraCommand = contents:
optionals let
;
mkDbExtraCommand = contents: let
contentsList = if builtins.isList contents then contents else [ contents ]; contentsList = if builtins.isList contents then contents else [ contents ];
in '' in
''
echo "Generating the nix database..." echo "Generating the nix database..."
echo "Warning: only the database of the deepest Nix layer is loaded." echo "Warning: only the database of the deepest Nix layer is loaded."
echo " If you want to use nix commands in the container, it would" echo " If you want to use nix commands in the container, it would"
@ -70,12 +68,12 @@ let
in in
rec { rec {
examples = callPackage ./examples.nix { examples = callPackage ./examples.nix {
inherit buildImage buildLayeredImage fakeNss pullImage shadowSetup buildImageWithNixDb; inherit buildImage buildLayeredImage fakeNss pullImage shadowSetup buildImageWithNixDb;
}; };
pullImage = let pullImage =
let
fixName = name: builtins.replaceStrings [ "/" ":" ] [ "-" "-" ] name; fixName = name: builtins.replaceStrings [ "/" ":" ] [ "-" "-" ] name;
in in
{ imageName { imageName
@ -96,7 +94,8 @@ rec {
, name ? fixName "docker-image-${finalImageName}-${finalImageTag}.tar" , name ? fixName "docker-image-${finalImageName}-${finalImageTag}.tar"
}: }:
runCommand name { runCommand name
{
inherit imageDigest; inherit imageDigest;
imageName = finalImageName; imageName = finalImageName;
imageTag = finalImageTag; imageTag = finalImageTag;
@ -126,11 +125,12 @@ rec {
tarsum = pkgs.tarsum; tarsum = pkgs.tarsum;
# buildEnv creates symlinks to dirs, which is hard to edit inside the overlay VM # buildEnv creates symlinks to dirs, which is hard to edit inside the overlay VM
mergeDrvs = { mergeDrvs =
derivations, { derivations
onlyDeps ? false , onlyDeps ? false
}: }:
runCommand "merge-drvs" { runCommand "merge-drvs"
{
inherit derivations onlyDeps; inherit derivations onlyDeps;
} '' } ''
if [[ -n "$onlyDeps" ]]; then if [[ -n "$onlyDeps" ]]; then
@ -180,19 +180,20 @@ rec {
''; '';
# Run commands in a virtual machine. # Run commands in a virtual machine.
runWithOverlay = { runWithOverlay =
name, { name
fromImage ? null, , fromImage ? null
fromImageName ? null, , fromImageName ? null
fromImageTag ? null, , fromImageTag ? null
diskSize ? 1024, , diskSize ? 1024
preMount ? "", , preMount ? ""
postMount ? "", , postMount ? ""
postUmount ? "" , postUmount ? ""
}: }:
let let
result = vmTools.runInLinuxVM ( result = vmTools.runInLinuxVM (
runCommand name { runCommand name
{
preVM = vmTools.createEmptyImage { preVM = vmTools.createEmptyImage {
size = diskSize; size = diskSize;
fullName = "docker-run-disk"; fullName = "docker-run-disk";
@ -293,7 +294,6 @@ rec {
''; '';
}; };
# Create an executable shell script which has the coreutils in its # Create an executable shell script which has the coreutils in its
# PATH. Since root scripts are executed in a blank environment, even # PATH. Since root scripts are executed in a blank environment, even
# things like `ls` or `echo` will be missing. # things like `ls` or `echo` will be missing.
@ -306,21 +306,25 @@ rec {
''; '';
# Create a "layer" (set of files). # Create a "layer" (set of files).
mkPureLayer = { mkPureLayer =
{
# Name of the layer # Name of the layer
name, name
# JSON containing configuration and metadata for this layer. , # JSON containing configuration and metadata for this layer.
baseJson, baseJson
# Files to add to the layer. , # Files to add to the layer.
contents ? null, contents ? null
# When copying the contents into the image, preserve symlinks to , # When copying the contents into the image, preserve symlinks to
# directories (see `rsync -K`). Otherwise, transform those symlinks # directories (see `rsync -K`). Otherwise, transform those symlinks
# into directories. # into directories.
keepContentsDirlinks ? false, keepContentsDirlinks ? false
# Additional commands to run on the layer before it is tar'd up. , # Additional commands to run on the layer before it is tar'd up.
extraCommands ? "", uid ? 0, gid ? 0 extraCommands ? ""
, uid ? 0
, gid ? 0
}: }:
runCommand "docker-layer-${name}" { runCommand "docker-layer-${name}"
{
inherit baseJson contents extraCommands; inherit baseJson contents extraCommands;
nativeBuildInputs = [ jshon rsync tarsum ]; nativeBuildInputs = [ jshon rsync tarsum ];
} }
@ -360,35 +364,37 @@ rec {
# Make a "root" layer; required if we need to execute commands as a # Make a "root" layer; required if we need to execute commands as a
# privileged user on the image. The commands themselves will be # privileged user on the image. The commands themselves will be
# performed in a virtual machine sandbox. # performed in a virtual machine sandbox.
mkRootLayer = { mkRootLayer =
{
# Name of the image. # Name of the image.
name, name
# Script to run as root. Bash. , # Script to run as root. Bash.
runAsRoot, runAsRoot
# Files to add to the layer. If null, an empty layer will be created. , # Files to add to the layer. If null, an empty layer will be created.
contents ? null, contents ? null
# When copying the contents into the image, preserve symlinks to , # When copying the contents into the image, preserve symlinks to
# directories (see `rsync -K`). Otherwise, transform those symlinks # directories (see `rsync -K`). Otherwise, transform those symlinks
# into directories. # into directories.
keepContentsDirlinks ? false, keepContentsDirlinks ? false
# JSON containing configuration and metadata for this layer. , # JSON containing configuration and metadata for this layer.
baseJson, baseJson
# Existing image onto which to append the new layer. , # Existing image onto which to append the new layer.
fromImage ? null, fromImage ? null
# Name of the image we're appending onto. , # Name of the image we're appending onto.
fromImageName ? null, fromImageName ? null
# Tag of the image we're appending onto. , # Tag of the image we're appending onto.
fromImageTag ? null, fromImageTag ? null
# How much disk to allocate for the temporary virtual machine. , # How much disk to allocate for the temporary virtual machine.
diskSize ? 1024, diskSize ? 1024
# Commands (bash) to run on the layer; these do not require sudo. , # Commands (bash) to run on the layer; these do not require sudo.
extraCommands ? "" extraCommands ? ""
}: }:
# Generate an executable script from the `runAsRoot` text. # Generate an executable script from the `runAsRoot` text.
let let
runAsRootScript = shellScript "run-as-root.sh" runAsRoot; runAsRootScript = shellScript "run-as-root.sh" runAsRoot;
extraCommandsScript = shellScript "extra-commands.sh" extraCommands; extraCommandsScript = shellScript "extra-commands.sh" extraCommands;
in runWithOverlay { in
runWithOverlay {
name = "docker-layer-${name}"; name = "docker-layer-${name}";
inherit fromImage fromImageName fromImageTag diskSize; inherit fromImage fromImageName fromImageTag diskSize;
@ -449,7 +455,8 @@ rec {
let let
stream = streamLayeredImage args; stream = streamLayeredImage args;
in in
runCommand "${baseNameOf name}.tar.gz" { runCommand "${baseNameOf name}.tar.gz"
{
inherit (stream) imageName; inherit (stream) imageName;
passthru = { inherit (stream) imageTag; }; passthru = { inherit (stream) imageTag; };
nativeBuildInputs = [ pigz ]; nativeBuildInputs = [ pigz ];
@ -461,40 +468,45 @@ rec {
# 4. compute the layer id # 4. compute the layer id
# 5. put the layer in the image # 5. put the layer in the image
# 6. repack the image # 6. repack the image
buildImage = args@{ buildImage =
args@{
# Image name. # Image name.
name, name
# Image tag, when null then the nix output hash will be used. , # Image tag, when null then the nix output hash will be used.
tag ? null, tag ? null
# Parent image, to append to. , # Parent image, to append to.
fromImage ? null, fromImage ? null
# Name of the parent image; will be read from the image otherwise. , # Name of the parent image; will be read from the image otherwise.
fromImageName ? null, fromImageName ? null
# Tag of the parent image; will be read from the image otherwise. , # Tag of the parent image; will be read from the image otherwise.
fromImageTag ? null, fromImageTag ? null
# Files to put on the image (a nix store path or list of paths). , # Files to put on the image (a nix store path or list of paths).
contents ? null, contents ? null
# When copying the contents into the image, preserve symlinks to , # When copying the contents into the image, preserve symlinks to
# directories (see `rsync -K`). Otherwise, transform those symlinks # directories (see `rsync -K`). Otherwise, transform those symlinks
# into directories. # into directories.
keepContentsDirlinks ? false, keepContentsDirlinks ? false
# Docker config; e.g. what command to run on the container. , # Docker config; e.g. what command to run on the container.
config ? null, config ? null
# Optional bash script to run on the files prior to fixturizing the layer. , # Optional bash script to run on the files prior to fixturizing the layer.
extraCommands ? "", uid ? 0, gid ? 0, extraCommands ? ""
# Optional bash script to run as root on the image when provisioning. , uid ? 0
runAsRoot ? null, , gid ? 0
# Size of the virtual machine disk to provision when building the image. , # Optional bash script to run as root on the image when provisioning.
diskSize ? 1024, runAsRoot ? null
# Time of creation of the image. , # Size of the virtual machine disk to provision when building the image.
created ? "1970-01-01T00:00:01Z", diskSize ? 1024
, # Time of creation of the image.
created ? "1970-01-01T00:00:01Z"
,
}: }:
let let
baseName = baseNameOf name; baseName = baseNameOf name;
# Create a JSON blob of the configuration. Set the date to unix zero. # Create a JSON blob of the configuration. Set the date to unix zero.
baseJson = let baseJson =
let
pure = writeText "${baseName}-config.json" (builtins.toJSON { pure = writeText "${baseName}-config.json" (builtins.toJSON {
inherit created config; inherit created config;
architecture = defaultArch; architecture = defaultArch;
@ -505,20 +517,25 @@ rec {
'' ''
jq ".created = \"$(TZ=utc date --iso-8601="seconds")\"" ${pure} > $out jq ".created = \"$(TZ=utc date --iso-8601="seconds")\"" ${pure} > $out
''; '';
in if created == "now" then impure else pure; in
if created == "now" then impure else pure;
layer = layer =
if runAsRoot == null if runAsRoot == null
then mkPureLayer { then
mkPureLayer
{
name = baseName; name = baseName;
inherit baseJson contents keepContentsDirlinks extraCommands uid gid; inherit baseJson contents keepContentsDirlinks extraCommands uid gid;
} else mkRootLayer { } else
mkRootLayer {
name = baseName; name = baseName;
inherit baseJson fromImage fromImageName fromImageTag inherit baseJson fromImage fromImageName fromImageTag
contents keepContentsDirlinks runAsRoot diskSize contents keepContentsDirlinks runAsRoot diskSize
extraCommands; extraCommands;
}; };
result = runCommand "docker-image-${baseName}.tar.gz" { result = runCommand "docker-image-${baseName}.tar.gz"
{
nativeBuildInputs = [ jshon pigz coreutils findutils jq moreutils ]; nativeBuildInputs = [ jshon pigz coreutils findutils jq moreutils ];
# Image name must be lowercase # Image name must be lowercase
imageName = lib.toLower name; imageName = lib.toLower name;
@ -760,32 +777,34 @@ rec {
}) })
); );
streamLayeredImage = { streamLayeredImage =
{
# Image Name # Image Name
name, name
# Image tag, the Nix's output hash will be used if null , # Image tag, the Nix's output hash will be used if null
tag ? null, tag ? null
# Parent image, to append to. , # Parent image, to append to.
fromImage ? null, fromImage ? null
# Files to put on the image (a nix store path or list of paths). , # Files to put on the image (a nix store path or list of paths).
contents ? [], contents ? [ ]
# Docker config; e.g. what command to run on the container. , # Docker config; e.g. what command to run on the container.
config ? {}, config ? { }
# Time of creation of the image. Passing "now" will make the , # Time of creation of the image. Passing "now" will make the
# created date be the time of building. # created date be the time of building.
created ? "1970-01-01T00:00:01Z", created ? "1970-01-01T00:00:01Z"
# Optional bash script to run on the files prior to fixturizing the layer. , # Optional bash script to run on the files prior to fixturizing the layer.
extraCommands ? "", extraCommands ? ""
# Optional bash script to run inside fakeroot environment. , # Optional bash script to run inside fakeroot environment.
# Could be used for changing ownership of files in customisation layer. # Could be used for changing ownership of files in customisation layer.
fakeRootCommands ? "", fakeRootCommands ? ""
# We pick 100 to ensure there is plenty of room for extension. I , # We pick 100 to ensure there is plenty of room for extension. I
# believe the actual maximum is 128. # believe the actual maximum is 128.
maxLayers ? 100, maxLayers ? 100
# Whether to include store paths in the image. You generally want to leave , # Whether to include store paths in the image. You generally want to leave
# this on, but tooling may disable this to insert the store paths more # this on, but tooling may disable this to insert the store paths more
# efficiently via other means, such as bind mounting the host store. # efficiently via other means, such as bind mounting the host store.
includeStorePaths ? true, includeStorePaths ? true
,
}: }:
assert assert
(lib.assertMsg (maxLayers > 1) (lib.assertMsg (maxLayers > 1)
@ -833,7 +852,7 @@ rec {
''; '';
}; };
closureRoots = optionals includeStorePaths /* normally true */ ( closureRoots = lib.optionals includeStorePaths /* normally true */ (
[ baseJson ] ++ contentsList [ baseJson ] ++ contentsList
); );
overallClosure = writeText "closure" (lib.concatStringsSep " " closureRoots); overallClosure = writeText "closure" (lib.concatStringsSep " " closureRoots);
@ -842,7 +861,8 @@ rec {
# so they'll be excluded from the created images. # so they'll be excluded from the created images.
unnecessaryDrvs = [ baseJson overallClosure ]; unnecessaryDrvs = [ baseJson overallClosure ];
conf = runCommand "${baseName}-conf.json" { conf = runCommand "${baseName}-conf.json"
{
inherit fromImage maxLayers created; inherit fromImage maxLayers created;
imageName = lib.toLower name; imageName = lib.toLower name;
passthru.imageTag = passthru.imageTag =
@ -931,7 +951,8 @@ rec {
--arg created "$created" | --arg created "$created" |
tee $out tee $out
''; '';
result = runCommand "stream-${baseName}" { result = runCommand "stream-${baseName}"
{
inherit (conf) imageName; inherit (conf) imageName;
passthru = { passthru = {
inherit (conf) imageTag; inherit (conf) imageTag;
@ -944,5 +965,6 @@ rec {
} '' } ''
makeWrapper ${streamScript} $out --add-flags ${conf} makeWrapper ${streamScript} $out --add-flags ${conf}
''; '';
in result; in
result;
} }