
Closes #259770 Closes #207050 The motivation for the former is to not execute the container as root, so you don't have to `sudo -i` to perform podman management tasks. The idea behind healthchecks is to be able to keep the unit in the activating state until the container is healthy, only then then unit is marked as active. The following changes were necessary: * Move the ctr-id into `/run/${containerName}` to make podman can actually write to it since it's now in its RuntimeDirectory. * Make `sdnotify` option configurable (`healthy` for healthchecks that must pass, default remains `conmon`). * Set Delegate=yes for `sdnotify=healthy` to make sure a rootless container can actually talk to sd_notify[1]. * Add a warning that lingering must be enabled to have a `systemd --user` instance running which is required for the cgroup support to work properly. * Added a testcase for rootless containers with both conmon and healthchecks. [1] https://github.com/containers/podman/discussions/20573#discussioncomment-7612481
1017 lines
26 KiB
Nix
1017 lines
26 KiB
Nix
# Examples of using the docker tools to build packages.
|
|
#
|
|
# This file defines several docker images. In order to use an image,
|
|
# build its derivation with `nix-build`, and then load the result with
|
|
# `docker load`. For example:
|
|
#
|
|
# $ nix-build '<nixpkgs>' -A dockerTools.examples.redis
|
|
# $ docker load < result
|
|
|
|
{
|
|
pkgs,
|
|
buildImage,
|
|
buildLayeredImage,
|
|
fakeNss,
|
|
pullImage,
|
|
shadowSetup,
|
|
buildImageWithNixDb,
|
|
pkgsCross,
|
|
streamNixShellImage,
|
|
}:
|
|
|
|
let
|
|
nixosLib = import ../../../nixos/lib {
|
|
# Experimental features need testing too, but there's no point in warning
|
|
# about it, so we enable the feature flag.
|
|
featureFlags.minimalModules = { };
|
|
};
|
|
evalMinimalConfig = module: nixosLib.evalModules { modules = [ module ]; };
|
|
|
|
nginxArguments =
|
|
let
|
|
nginxPort = "80";
|
|
nginxConf = pkgs.writeText "nginx.conf" ''
|
|
user nobody nobody;
|
|
daemon off;
|
|
error_log /dev/stdout info;
|
|
pid /dev/null;
|
|
events {}
|
|
http {
|
|
access_log /dev/stdout;
|
|
server {
|
|
listen ${nginxPort};
|
|
index index.html;
|
|
location / {
|
|
root ${nginxWebRoot};
|
|
}
|
|
}
|
|
}
|
|
'';
|
|
nginxWebRoot = pkgs.writeTextDir "index.html" ''
|
|
<html><body><h1>Hello from NGINX</h1></body></html>
|
|
'';
|
|
in
|
|
{
|
|
name = "nginx-container";
|
|
tag = "latest";
|
|
contents = [
|
|
fakeNss
|
|
pkgs.nginx
|
|
];
|
|
|
|
extraCommands = ''
|
|
mkdir -p tmp/nginx_client_body
|
|
|
|
# nginx still tries to read this directory even if error_log
|
|
# directive is specifying another file :/
|
|
mkdir -p var/log/nginx
|
|
'';
|
|
|
|
config = {
|
|
Cmd = [
|
|
"nginx"
|
|
"-c"
|
|
nginxConf
|
|
];
|
|
ExposedPorts = {
|
|
"${nginxPort}/tcp" = { };
|
|
};
|
|
};
|
|
};
|
|
|
|
in
|
|
|
|
rec {
|
|
# 1. basic example
|
|
bash = buildImage {
|
|
name = "bash";
|
|
tag = "latest";
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
paths = [ pkgs.bashInteractive ];
|
|
pathsToLink = [ "/bin" ];
|
|
};
|
|
};
|
|
|
|
# 2. service example, layered on another image
|
|
redis = buildImage {
|
|
name = "redis";
|
|
tag = "latest";
|
|
|
|
# for example's sake, we can layer redis on top of bash or debian
|
|
fromImage = bash;
|
|
# fromImage = debian;
|
|
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
paths = [ pkgs.redis ];
|
|
pathsToLink = [ "/bin" ];
|
|
};
|
|
|
|
runAsRoot = ''
|
|
mkdir -p /data
|
|
cat >/bin/healthcheck <<-'EOF'
|
|
set -x
|
|
probe="$(/bin/redis-cli ping)"
|
|
echo "$probe"
|
|
if [ "$probe" = 'PONG' ]; then
|
|
exit 0
|
|
fi
|
|
exit 1
|
|
EOF
|
|
chmod +x /bin/healthcheck
|
|
'';
|
|
|
|
config = {
|
|
Cmd = [ "/bin/redis-server" ];
|
|
WorkingDir = "/data";
|
|
Volumes = {
|
|
"/data" = { };
|
|
};
|
|
Healthcheck = {
|
|
Test = [
|
|
"CMD-SHELL"
|
|
"/bin/healthcheck"
|
|
];
|
|
Interval = 30000000000;
|
|
Timeout = 10000000000;
|
|
Retries = 3;
|
|
};
|
|
};
|
|
};
|
|
|
|
# 3. another service example
|
|
nginx = buildLayeredImage nginxArguments;
|
|
|
|
# Used to demonstrate how virtualisation.oci-containers.imageStream works
|
|
nginxStream = pkgs.dockerTools.streamLayeredImage nginxArguments;
|
|
|
|
# 4. example of pulling an image. could be used as a base for other images
|
|
nixFromDockerHub = pullImage {
|
|
imageName = "nixos/nix";
|
|
imageDigest = "sha256:85299d86263a3059cf19f419f9d286cc9f06d3c13146a8ebbb21b3437f598357";
|
|
hash = "sha256-xxZ4UW6jRIVAzlVYA62awcopzcYNViDyh6q1yocF3KU=";
|
|
finalImageTag = "2.2.1";
|
|
finalImageName = "nix";
|
|
};
|
|
# Same example, but re-fetches every time the fetcher implementation changes.
|
|
# NOTE: Only use this for testing, or you'd be wasting a lot of time, network and space.
|
|
testNixFromDockerHub = pkgs.testers.invalidateFetcherByDrvHash pullImage {
|
|
imageName = "nixos/nix";
|
|
imageDigest = "sha256:85299d86263a3059cf19f419f9d286cc9f06d3c13146a8ebbb21b3437f598357";
|
|
hash = "sha256-xxZ4UW6jRIVAzlVYA62awcopzcYNViDyh6q1yocF3KU=";
|
|
finalImageTag = "2.2.1";
|
|
finalImageName = "nix";
|
|
};
|
|
|
|
# 5. example of multiple contents, emacs and vi happily coexisting
|
|
editors = buildImage {
|
|
name = "editors";
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
pathsToLink = [ "/bin" ];
|
|
paths = [
|
|
pkgs.coreutils
|
|
pkgs.bash
|
|
pkgs.emacs
|
|
pkgs.vim
|
|
pkgs.nano
|
|
];
|
|
};
|
|
};
|
|
|
|
# 6. nix example to play with the container nix store
|
|
# docker run -it --rm nix nix-store -qR $(nix-build '<nixpkgs>' -A nix)
|
|
nix = buildImageWithNixDb {
|
|
name = "nix";
|
|
tag = "latest";
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
pathsToLink = [ "/bin" ];
|
|
paths = [
|
|
# nix-store uses cat program to display results as specified by
|
|
# the image env variable NIX_PAGER.
|
|
pkgs.coreutils
|
|
pkgs.nix
|
|
pkgs.bash
|
|
];
|
|
};
|
|
config = {
|
|
Env = [
|
|
"NIX_PAGER=cat"
|
|
# A user is required by nix
|
|
# https://github.com/NixOS/nix/blob/9348f9291e5d9e4ba3c4347ea1b235640f54fd79/src/libutil/util.cc#L478
|
|
"USER=nobody"
|
|
];
|
|
};
|
|
};
|
|
|
|
# 7. example of adding something on top of an image pull by our
|
|
# dockerTools chain.
|
|
onTopOfPulledImage = buildImage {
|
|
name = "onTopOfPulledImage";
|
|
tag = "latest";
|
|
fromImage = nixFromDockerHub;
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
pathsToLink = [ "/bin" ];
|
|
paths = [ pkgs.hello ];
|
|
};
|
|
};
|
|
|
|
# 8. regression test for erroneous use of eval and string expansion.
|
|
# See issue #34779 and PR #40947 for details.
|
|
runAsRootExtraCommands = pkgs.dockerTools.buildImage {
|
|
name = "runAsRootExtraCommands";
|
|
tag = "latest";
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
pathsToLink = [ "/bin" ];
|
|
paths = [ pkgs.coreutils ];
|
|
};
|
|
# The parens here are to create problematic bash to embed and eval. In case
|
|
# this is *embedded* into the script (with nix expansion) the initial quotes
|
|
# will close the string and the following parens are unexpected
|
|
runAsRoot = ''echo "(runAsRoot)" > runAsRoot'';
|
|
extraCommands = ''echo "(extraCommand)" > extraCommands'';
|
|
};
|
|
|
|
# 9. Ensure that setting created to now results in a date which
|
|
# isn't the epoch + 1
|
|
unstableDate = pkgs.dockerTools.buildImage {
|
|
name = "unstable-date";
|
|
tag = "latest";
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
pathsToLink = [ "/bin" ];
|
|
paths = [ pkgs.coreutils ];
|
|
};
|
|
created = "now";
|
|
};
|
|
|
|
# 10. Create a layered image
|
|
layered-image = pkgs.dockerTools.buildLayeredImage {
|
|
name = "layered-image";
|
|
tag = "latest";
|
|
extraCommands = ''echo "(extraCommand)" > extraCommands'';
|
|
config.Cmd = [ "${pkgs.hello}/bin/hello" ];
|
|
contents = [
|
|
pkgs.hello
|
|
pkgs.bash
|
|
pkgs.coreutils
|
|
];
|
|
};
|
|
|
|
# 11. Create an image on top of a layered image
|
|
layered-on-top = pkgs.dockerTools.buildImage {
|
|
name = "layered-on-top";
|
|
tag = "latest";
|
|
fromImage = layered-image;
|
|
extraCommands = ''
|
|
mkdir ./example-output
|
|
chmod 777 ./example-output
|
|
'';
|
|
config = {
|
|
Env = [ "PATH=${pkgs.coreutils}/bin/" ];
|
|
WorkingDir = "/example-output";
|
|
Cmd = [
|
|
"${pkgs.bash}/bin/bash"
|
|
"-c"
|
|
"echo hello > foo; cat foo"
|
|
];
|
|
};
|
|
};
|
|
|
|
# 12 Create a layered image on top of a layered image
|
|
layered-on-top-layered = pkgs.dockerTools.buildLayeredImage {
|
|
name = "layered-on-top-layered";
|
|
tag = "latest";
|
|
fromImage = layered-image;
|
|
extraCommands = ''
|
|
mkdir ./example-output
|
|
chmod 777 ./example-output
|
|
'';
|
|
config = {
|
|
Env = [ "PATH=${pkgs.coreutils}/bin/" ];
|
|
WorkingDir = "/example-output";
|
|
Cmd = [
|
|
"${pkgs.bash}/bin/bash"
|
|
"-c"
|
|
"echo hello > foo; cat foo"
|
|
];
|
|
};
|
|
};
|
|
|
|
# 13. example of running something as root on top of a parent image
|
|
# Regression test related to PR #52109
|
|
runAsRootParentImage = buildImage {
|
|
name = "runAsRootParentImage";
|
|
tag = "latest";
|
|
runAsRoot = "touch /example-file";
|
|
fromImage = bash;
|
|
};
|
|
|
|
# 14. example of 3 layers images This image is used to verify the
|
|
# order of layers is correct.
|
|
# It allows to validate
|
|
# - the layer of parent are below
|
|
# - the order of parent layer is preserved at image build time
|
|
# (this is why there are 3 images)
|
|
layersOrder =
|
|
let
|
|
l1 = pkgs.dockerTools.buildImage {
|
|
name = "l1";
|
|
tag = "latest";
|
|
extraCommands = ''
|
|
mkdir -p tmp
|
|
echo layer1 > tmp/layer1
|
|
echo layer1 > tmp/layer2
|
|
echo layer1 > tmp/layer3
|
|
'';
|
|
};
|
|
l2 = pkgs.dockerTools.buildImage {
|
|
name = "l2";
|
|
fromImage = l1;
|
|
tag = "latest";
|
|
extraCommands = ''
|
|
mkdir -p tmp
|
|
echo layer2 > tmp/layer2
|
|
echo layer2 > tmp/layer3
|
|
'';
|
|
};
|
|
in
|
|
pkgs.dockerTools.buildImage {
|
|
name = "l3";
|
|
fromImage = l2;
|
|
tag = "latest";
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
pathsToLink = [ "/bin" ];
|
|
paths = [ pkgs.coreutils ];
|
|
};
|
|
extraCommands = ''
|
|
mkdir -p tmp
|
|
echo layer3 > tmp/layer3
|
|
'';
|
|
};
|
|
|
|
# 15. Environment variable inheritance.
|
|
# Child image should inherit parents environment variables,
|
|
# optionally overriding them.
|
|
environmentVariablesParent = pkgs.dockerTools.buildImage {
|
|
name = "parent";
|
|
tag = "latest";
|
|
config = {
|
|
Env = [
|
|
"FROM_PARENT=true"
|
|
"LAST_LAYER=parent"
|
|
];
|
|
};
|
|
};
|
|
|
|
environmentVariables = pkgs.dockerTools.buildImage {
|
|
name = "child";
|
|
fromImage = environmentVariablesParent;
|
|
tag = "latest";
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
pathsToLink = [ "/bin" ];
|
|
paths = [ pkgs.coreutils ];
|
|
};
|
|
config = {
|
|
Env = [
|
|
"FROM_CHILD=true"
|
|
"LAST_LAYER=child"
|
|
];
|
|
};
|
|
};
|
|
|
|
environmentVariablesLayered = pkgs.dockerTools.buildLayeredImage {
|
|
name = "child";
|
|
fromImage = environmentVariablesParent;
|
|
tag = "latest";
|
|
contents = [ pkgs.coreutils ];
|
|
config = {
|
|
Env = [
|
|
"FROM_CHILD=true"
|
|
"LAST_LAYER=child"
|
|
];
|
|
};
|
|
};
|
|
|
|
# 16. Create another layered image, for comparing layers with image 10.
|
|
another-layered-image = pkgs.dockerTools.buildLayeredImage {
|
|
name = "another-layered-image";
|
|
tag = "latest";
|
|
config.Cmd = [ "${pkgs.hello}/bin/hello" ];
|
|
};
|
|
|
|
# 17. Create a layered image with only 2 layers
|
|
two-layered-image = pkgs.dockerTools.buildLayeredImage {
|
|
name = "two-layered-image";
|
|
tag = "latest";
|
|
config.Cmd = [ "${pkgs.hello}/bin/hello" ];
|
|
contents = [
|
|
pkgs.bash
|
|
pkgs.hello
|
|
];
|
|
maxLayers = 2;
|
|
};
|
|
|
|
# 18. Create a layered image with more packages than max layers.
|
|
# coreutils and hello are part of the same layer
|
|
bulk-layer = pkgs.dockerTools.buildLayeredImage {
|
|
name = "bulk-layer";
|
|
tag = "latest";
|
|
contents = with pkgs; [
|
|
coreutils
|
|
hello
|
|
];
|
|
maxLayers = 2;
|
|
};
|
|
|
|
# 19. Create a layered image with a base image and more packages than max
|
|
# layers. coreutils and hello are part of the same layer
|
|
layered-bulk-layer = pkgs.dockerTools.buildLayeredImage {
|
|
name = "layered-bulk-layer";
|
|
tag = "latest";
|
|
fromImage = two-layered-image;
|
|
contents = with pkgs; [
|
|
coreutils
|
|
hello
|
|
];
|
|
maxLayers = 4;
|
|
};
|
|
|
|
# 20. Create a "layered" image without nix store layers. This is not
|
|
# recommended, but can be useful for base images in rare cases.
|
|
no-store-paths = pkgs.dockerTools.buildLayeredImage {
|
|
name = "no-store-paths";
|
|
tag = "latest";
|
|
extraCommands = ''
|
|
# This removes sharing of busybox and is not recommended. We do this
|
|
# to make the example suitable as a test case with working binaries.
|
|
cp -r ${pkgs.pkgsStatic.busybox}/* .
|
|
|
|
# This is a "build" dependency that will not appear in the image
|
|
${pkgs.hello}/bin/hello
|
|
'';
|
|
};
|
|
|
|
nixLayered = pkgs.dockerTools.buildLayeredImageWithNixDb {
|
|
name = "nix-layered";
|
|
tag = "latest";
|
|
contents = [
|
|
# nix-store uses cat program to display results as specified by
|
|
# the image env variable NIX_PAGER.
|
|
pkgs.coreutils
|
|
pkgs.nix
|
|
pkgs.bash
|
|
];
|
|
config = {
|
|
Env = [
|
|
"NIX_PAGER=cat"
|
|
# A user is required by nix
|
|
# https://github.com/NixOS/nix/blob/9348f9291e5d9e4ba3c4347ea1b235640f54fd79/src/libutil/util.cc#L478
|
|
"USER=nobody"
|
|
];
|
|
};
|
|
};
|
|
|
|
# 21. Support files in the store on buildLayeredImage
|
|
# See: https://github.com/NixOS/nixpkgs/pull/91084#issuecomment-653496223
|
|
filesInStore = pkgs.dockerTools.buildLayeredImageWithNixDb {
|
|
name = "file-in-store";
|
|
tag = "latest";
|
|
contents = [
|
|
pkgs.coreutils
|
|
pkgs.nix
|
|
(pkgs.writeScriptBin "myscript" ''
|
|
#!${pkgs.runtimeShell}
|
|
cat ${pkgs.writeText "somefile" "some data"}
|
|
'')
|
|
];
|
|
config = {
|
|
Cmd = [ "myscript" ];
|
|
# For some reason 'nix-store --verify' requires this environment variable
|
|
Env = [ "USER=root" ];
|
|
};
|
|
};
|
|
|
|
# 22. Ensure that setting created to now results in a date which
|
|
# isn't the epoch + 1 for layered images.
|
|
unstableDateLayered = pkgs.dockerTools.buildLayeredImage {
|
|
name = "unstable-date-layered";
|
|
tag = "latest";
|
|
contents = [ pkgs.coreutils ];
|
|
created = "now";
|
|
};
|
|
|
|
# 23. Ensure that layers are unpacked in the correct order before the
|
|
# runAsRoot script is executed.
|
|
layersUnpackOrder =
|
|
let
|
|
layerOnTopOf =
|
|
parent: layerName:
|
|
pkgs.dockerTools.buildImage {
|
|
name = "layers-unpack-order-${layerName}";
|
|
tag = "latest";
|
|
fromImage = parent;
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
pathsToLink = [ "/bin" ];
|
|
paths = [ pkgs.coreutils ];
|
|
};
|
|
runAsRoot = ''
|
|
#!${pkgs.runtimeShell}
|
|
echo -n "${layerName}" >> /layer-order
|
|
'';
|
|
};
|
|
# When executing the runAsRoot script when building layer C, if layer B is
|
|
# not unpacked on top of layer A, the contents of /layer-order will not be
|
|
# "ABC".
|
|
layerA = layerOnTopOf null "a";
|
|
layerB = layerOnTopOf layerA "b";
|
|
layerC = layerOnTopOf layerB "c";
|
|
in
|
|
layerC;
|
|
|
|
bashUncompressed = pkgs.dockerTools.buildImage {
|
|
name = "bash-uncompressed";
|
|
tag = "latest";
|
|
compressor = "none";
|
|
# Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
|
|
copyToRoot = pkgs.bashInteractive;
|
|
};
|
|
|
|
bashZstdCompressed = pkgs.dockerTools.buildImage {
|
|
name = "bash-zstd";
|
|
tag = "latest";
|
|
compressor = "zstd";
|
|
# Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
|
|
copyToRoot = pkgs.bashInteractive;
|
|
};
|
|
|
|
# buildImage without explicit tag
|
|
bashNoTag = pkgs.dockerTools.buildImage {
|
|
name = "bash-no-tag";
|
|
# Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
|
|
copyToRoot = pkgs.bashInteractive;
|
|
};
|
|
|
|
# buildLayeredImage without explicit tag
|
|
bashNoTagLayered = pkgs.dockerTools.buildLayeredImage {
|
|
name = "bash-no-tag-layered";
|
|
contents = pkgs.bashInteractive;
|
|
};
|
|
|
|
# buildLayeredImage without compression
|
|
bashLayeredUncompressed = pkgs.dockerTools.buildLayeredImage {
|
|
name = "bash-layered-uncompressed";
|
|
tag = "latest";
|
|
compressor = "none";
|
|
contents = pkgs.bashInteractive;
|
|
};
|
|
|
|
# buildLayeredImage with zstd compression
|
|
bashLayeredZstdCompressed = pkgs.dockerTools.buildLayeredImage {
|
|
name = "bash-layered-zstd";
|
|
tag = "latest";
|
|
compressor = "zstd";
|
|
contents = pkgs.bashInteractive;
|
|
};
|
|
|
|
# streamLayeredImage without explicit tag
|
|
bashNoTagStreamLayered = pkgs.dockerTools.streamLayeredImage {
|
|
name = "bash-no-tag-stream-layered";
|
|
contents = pkgs.bashInteractive;
|
|
};
|
|
|
|
# buildLayeredImage with non-root user
|
|
bashLayeredWithUser =
|
|
let
|
|
nonRootShadowSetup =
|
|
{
|
|
user,
|
|
uid,
|
|
gid ? uid,
|
|
}:
|
|
with pkgs;
|
|
[
|
|
(writeTextDir "etc/shadow" ''
|
|
root:!x:::::::
|
|
${user}:!:::::::
|
|
'')
|
|
(writeTextDir "etc/passwd" ''
|
|
root:x:0:0::/root:${runtimeShell}
|
|
${user}:x:${toString uid}:${toString gid}::/home/${user}:
|
|
'')
|
|
(writeTextDir "etc/group" ''
|
|
root:x:0:
|
|
${user}:x:${toString gid}:
|
|
'')
|
|
(writeTextDir "etc/gshadow" ''
|
|
root:x::
|
|
${user}:x::
|
|
'')
|
|
];
|
|
in
|
|
pkgs.dockerTools.buildLayeredImage {
|
|
name = "bash-layered-with-user";
|
|
tag = "latest";
|
|
contents =
|
|
[
|
|
pkgs.bash
|
|
pkgs.coreutils
|
|
]
|
|
++ nonRootShadowSetup {
|
|
uid = 999;
|
|
user = "somebody";
|
|
};
|
|
};
|
|
|
|
# basic example, with cross compilation
|
|
cross =
|
|
let
|
|
# Cross compile for x86_64 if on aarch64
|
|
crossPkgs =
|
|
if pkgs.stdenv.hostPlatform.system == "aarch64-linux" then
|
|
pkgsCross.gnu64
|
|
else
|
|
pkgsCross.aarch64-multiplatform;
|
|
in
|
|
crossPkgs.dockerTools.buildImage {
|
|
name = "hello-cross";
|
|
tag = "latest";
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-root";
|
|
pathsToLink = [ "/bin" ];
|
|
paths = [ crossPkgs.hello ];
|
|
};
|
|
};
|
|
|
|
# layered image where a store path is itself a symlink
|
|
layeredStoreSymlink =
|
|
let
|
|
target = pkgs.writeTextDir "dir/target" "Content doesn't matter.";
|
|
symlink = pkgs.runCommand "symlink" { } "ln -s ${target} $out";
|
|
in
|
|
pkgs.dockerTools.buildLayeredImage {
|
|
name = "layeredstoresymlink";
|
|
tag = "latest";
|
|
contents = [
|
|
pkgs.bash
|
|
symlink
|
|
];
|
|
}
|
|
// {
|
|
passthru = { inherit symlink; };
|
|
};
|
|
|
|
# image with registry/ prefix
|
|
prefixedImage = pkgs.dockerTools.buildImage {
|
|
name = "registry-1.docker.io/image";
|
|
tag = "latest";
|
|
config.Cmd = [ "${pkgs.hello}/bin/hello" ];
|
|
};
|
|
|
|
# layered image with registry/ prefix
|
|
prefixedLayeredImage = pkgs.dockerTools.buildLayeredImage {
|
|
name = "registry-1.docker.io/layered-image";
|
|
tag = "latest";
|
|
config.Cmd = [ "${pkgs.hello}/bin/hello" ];
|
|
};
|
|
|
|
# layered image with files owned by a user other than root
|
|
layeredImageWithFakeRootCommands = pkgs.dockerTools.buildLayeredImage {
|
|
name = "layered-image-with-fake-root-commands";
|
|
tag = "latest";
|
|
contents = [
|
|
pkgs.pkgsStatic.busybox
|
|
];
|
|
fakeRootCommands = ''
|
|
mkdir -p ./home/alice
|
|
chown 1000 ./home/alice
|
|
ln -s ${
|
|
pkgs.hello.overrideAttrs (
|
|
finalAttrs: prevAttrs: {
|
|
# A unique `hello` to make sure that it isn't included via another mechanism by accident.
|
|
configureFlags = prevAttrs.configureFlags or [ ] ++ [
|
|
" --program-prefix=layeredImageWithFakeRootCommands-"
|
|
];
|
|
doCheck = false;
|
|
versionCheckProgram = "${builtins.placeholder "out"}/bin/${finalAttrs.meta.mainProgram}";
|
|
meta = prevAttrs.meta // {
|
|
mainProgram = "layeredImageWithFakeRootCommands-hello";
|
|
};
|
|
}
|
|
)
|
|
} ./hello
|
|
'';
|
|
};
|
|
|
|
# tarball consisting of both bash and redis images
|
|
mergedBashAndRedis = pkgs.dockerTools.mergeImages [
|
|
bash
|
|
redis
|
|
];
|
|
|
|
# tarball consisting of bash (without tag) and redis images
|
|
mergedBashNoTagAndRedis = pkgs.dockerTools.mergeImages [
|
|
bashNoTag
|
|
redis
|
|
];
|
|
|
|
# tarball consisting of bash and layered image with different owner of the
|
|
# /home/alice directory
|
|
mergedBashFakeRoot = pkgs.dockerTools.mergeImages [
|
|
bash
|
|
layeredImageWithFakeRootCommands
|
|
];
|
|
|
|
mergeVaryingCompressor = pkgs.dockerTools.mergeImages [
|
|
redis
|
|
bashUncompressed
|
|
bashZstdCompressed
|
|
];
|
|
|
|
helloOnRoot = pkgs.dockerTools.streamLayeredImage {
|
|
name = "hello";
|
|
tag = "latest";
|
|
contents = [
|
|
(pkgs.buildEnv {
|
|
name = "hello-root";
|
|
paths = [ pkgs.hello ];
|
|
})
|
|
];
|
|
config.Cmd = [ "hello" ];
|
|
};
|
|
|
|
helloOnRootNoStore = pkgs.dockerTools.streamLayeredImage {
|
|
name = "hello";
|
|
tag = "latest";
|
|
contents = [
|
|
(pkgs.buildEnv {
|
|
name = "hello-root";
|
|
paths = [ pkgs.hello ];
|
|
})
|
|
];
|
|
config.Cmd = [ "hello" ];
|
|
includeStorePaths = false;
|
|
};
|
|
|
|
helloOnRootNoStoreFakechroot = pkgs.dockerTools.streamLayeredImage {
|
|
name = "hello";
|
|
tag = "latest";
|
|
contents = [
|
|
(pkgs.buildEnv {
|
|
name = "hello-root";
|
|
paths = [ pkgs.hello ];
|
|
})
|
|
];
|
|
config.Cmd = [ "hello" ];
|
|
includeStorePaths = false;
|
|
enableFakechroot = true;
|
|
};
|
|
|
|
etc =
|
|
let
|
|
inherit (pkgs) lib;
|
|
nixosCore = (
|
|
evalMinimalConfig (
|
|
{ config, ... }:
|
|
{
|
|
imports = [
|
|
pkgs.pkgsModule
|
|
../../../nixos/modules/system/etc/etc.nix
|
|
];
|
|
environment.etc."some-config-file" = {
|
|
text = ''
|
|
127.0.0.1 localhost
|
|
::1 localhost
|
|
'';
|
|
# For executables:
|
|
# mode = "0755";
|
|
};
|
|
}
|
|
)
|
|
);
|
|
in
|
|
pkgs.dockerTools.streamLayeredImage {
|
|
name = "etc";
|
|
tag = "latest";
|
|
enableFakechroot = true;
|
|
fakeRootCommands = ''
|
|
mkdir -p /etc
|
|
${nixosCore.config.system.build.etcActivationCommands}
|
|
'';
|
|
config.Cmd = pkgs.writeScript "etc-cmd" ''
|
|
#!${pkgs.busybox}/bin/sh
|
|
${pkgs.busybox}/bin/cat /etc/some-config-file
|
|
'';
|
|
};
|
|
|
|
# Example export of the bash image
|
|
exportBash = pkgs.dockerTools.exportImage { fromImage = bash; };
|
|
|
|
imageViaFakeChroot = pkgs.dockerTools.streamLayeredImage {
|
|
name = "image-via-fake-chroot";
|
|
tag = "latest";
|
|
config.Cmd = [ "hello" ];
|
|
enableFakechroot = true;
|
|
# Crucially, instead of a relative path, this creates /bin, which is
|
|
# intercepted by fakechroot.
|
|
# This functionality is not available on darwin as of 2021.
|
|
fakeRootCommands = ''
|
|
mkdir /bin
|
|
ln -s ${pkgs.hello}/bin/hello /bin/hello
|
|
'';
|
|
};
|
|
|
|
build-image-with-path = buildImage {
|
|
name = "build-image-with-path";
|
|
tag = "latest";
|
|
# Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
|
|
copyToRoot = [
|
|
pkgs.bashInteractive
|
|
./test-dummy
|
|
];
|
|
};
|
|
|
|
layered-image-with-path = pkgs.dockerTools.streamLayeredImage {
|
|
name = "layered-image-with-path";
|
|
tag = "latest";
|
|
contents = [
|
|
pkgs.bashInteractive
|
|
./test-dummy
|
|
];
|
|
};
|
|
|
|
build-image-with-architecture = buildImage {
|
|
name = "build-image-with-architecture";
|
|
tag = "latest";
|
|
architecture = "arm64";
|
|
# Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
|
|
copyToRoot = [
|
|
pkgs.bashInteractive
|
|
./test-dummy
|
|
];
|
|
};
|
|
|
|
layered-image-with-architecture = pkgs.dockerTools.streamLayeredImage {
|
|
name = "layered-image-with-architecture";
|
|
tag = "latest";
|
|
architecture = "arm64";
|
|
contents = [
|
|
pkgs.bashInteractive
|
|
./test-dummy
|
|
];
|
|
};
|
|
|
|
# ensure that caCertificates builds
|
|
image-with-certs = buildImage {
|
|
name = "image-with-certs";
|
|
tag = "latest";
|
|
|
|
copyToRoot = pkgs.buildEnv {
|
|
name = "image-with-certs-root";
|
|
paths = [
|
|
pkgs.coreutils
|
|
pkgs.dockerTools.caCertificates
|
|
];
|
|
};
|
|
|
|
config = {
|
|
};
|
|
};
|
|
|
|
nix-shell-basic = streamNixShellImage {
|
|
name = "nix-shell-basic";
|
|
tag = "latest";
|
|
drv = pkgs.hello;
|
|
};
|
|
|
|
nix-shell-hook = streamNixShellImage {
|
|
name = "nix-shell-hook";
|
|
tag = "latest";
|
|
drv = pkgs.mkShell {
|
|
shellHook = ''
|
|
echo "This is the shell hook!"
|
|
exit
|
|
'';
|
|
};
|
|
};
|
|
|
|
nix-shell-inputs = streamNixShellImage {
|
|
name = "nix-shell-inputs";
|
|
tag = "latest";
|
|
drv = pkgs.mkShell {
|
|
nativeBuildInputs = [
|
|
pkgs.hello
|
|
];
|
|
};
|
|
command = ''
|
|
hello
|
|
'';
|
|
};
|
|
|
|
nix-shell-pass-as-file = streamNixShellImage {
|
|
name = "nix-shell-pass-as-file";
|
|
tag = "latest";
|
|
drv = pkgs.mkShell {
|
|
str = "this is a string";
|
|
passAsFile = [ "str" ];
|
|
};
|
|
command = ''
|
|
cat "$strPath"
|
|
'';
|
|
};
|
|
|
|
nix-shell-run = streamNixShellImage {
|
|
name = "nix-shell-run";
|
|
tag = "latest";
|
|
drv = pkgs.mkShell { };
|
|
run = ''
|
|
case "$-" in
|
|
*i*) echo This shell is interactive ;;
|
|
*) echo This shell is not interactive ;;
|
|
esac
|
|
'';
|
|
};
|
|
|
|
nix-shell-command = streamNixShellImage {
|
|
name = "nix-shell-command";
|
|
tag = "latest";
|
|
drv = pkgs.mkShell { };
|
|
command = ''
|
|
case "$-" in
|
|
*i*) echo This shell is interactive ;;
|
|
*) echo This shell is not interactive ;;
|
|
esac
|
|
'';
|
|
};
|
|
|
|
nix-shell-writable-home = streamNixShellImage {
|
|
name = "nix-shell-writable-home";
|
|
tag = "latest";
|
|
drv = pkgs.mkShell { };
|
|
run = ''
|
|
if [[ "$HOME" != "$(eval "echo ~$(whoami)")" ]]; then
|
|
echo "\$HOME ($HOME) is not the same as ~\$(whoami) ($(eval "echo ~$(whoami)"))"
|
|
exit 1
|
|
fi
|
|
|
|
if ! touch $HOME/test-file; then
|
|
echo "home directory is not writable"
|
|
exit 1
|
|
fi
|
|
echo "home directory is writable"
|
|
'';
|
|
};
|
|
|
|
nix-shell-nonexistent-home = streamNixShellImage {
|
|
name = "nix-shell-nonexistent-home";
|
|
tag = "latest";
|
|
drv = pkgs.mkShell { };
|
|
homeDirectory = "/homeless-shelter";
|
|
run = ''
|
|
if [[ "$HOME" != "$(eval "echo ~$(whoami)")" ]]; then
|
|
echo "\$HOME ($HOME) is not the same as ~\$(whoami) ($(eval "echo ~$(whoami)"))"
|
|
exit 1
|
|
fi
|
|
|
|
if -e $HOME; then
|
|
echo "home directory exists"
|
|
exit 1
|
|
fi
|
|
echo "home directory doesn't exist"
|
|
'';
|
|
};
|
|
|
|
nix-shell-build-derivation = streamNixShellImage {
|
|
name = "nix-shell-build-derivation";
|
|
tag = "latest";
|
|
drv = pkgs.hello;
|
|
run = ''
|
|
buildDerivation
|
|
$out/bin/hello
|
|
'';
|
|
};
|
|
|
|
nix-layered = pkgs.dockerTools.streamLayeredImage {
|
|
name = "nix-layered";
|
|
tag = "latest";
|
|
contents = [
|
|
pkgs.nix
|
|
pkgs.bash
|
|
];
|
|
includeNixDB = true;
|
|
config = {
|
|
Env = [
|
|
"NIX_PAGER=cat"
|
|
];
|
|
};
|
|
};
|
|
|
|
}
|