2016-10-03 19:07:33 +02:00
|
|
|
# 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
|
|
|
|
|
2017-08-25 11:47:28 +02:00
|
|
|
{ pkgs, buildImage, pullImage, shadowSetup, buildImageWithNixDb }:
|
2016-10-03 19:07:33 +02:00
|
|
|
|
|
|
|
rec {
|
|
|
|
# 1. basic example
|
|
|
|
bash = buildImage {
|
|
|
|
name = "bash";
|
2018-07-06 16:31:59 +02:00
|
|
|
tag = "latest";
|
2016-10-03 19:07:33 +02:00
|
|
|
contents = pkgs.bashInteractive;
|
|
|
|
};
|
|
|
|
|
|
|
|
# 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;
|
|
|
|
|
|
|
|
contents = pkgs.redis;
|
|
|
|
runAsRoot = ''
|
|
|
|
mkdir -p /data
|
|
|
|
'';
|
|
|
|
|
|
|
|
config = {
|
|
|
|
Cmd = [ "/bin/redis-server" ];
|
|
|
|
WorkingDir = "/data";
|
|
|
|
Volumes = {
|
|
|
|
"/data" = {};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
# 3. another service example
|
|
|
|
nginx = let
|
|
|
|
nginxPort = "80";
|
|
|
|
nginxConf = pkgs.writeText "nginx.conf" ''
|
|
|
|
user nginx nginx;
|
|
|
|
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
|
|
|
|
buildImage {
|
|
|
|
name = "nginx-container";
|
2018-07-06 16:31:59 +02:00
|
|
|
tag = "latest";
|
2016-10-03 19:07:33 +02:00
|
|
|
contents = pkgs.nginx;
|
|
|
|
|
|
|
|
runAsRoot = ''
|
|
|
|
#!${pkgs.stdenv.shell}
|
|
|
|
${shadowSetup}
|
|
|
|
groupadd --system nginx
|
|
|
|
useradd --system --gid nginx nginx
|
|
|
|
'';
|
|
|
|
|
|
|
|
config = {
|
|
|
|
Cmd = [ "nginx" "-c" nginxConf ];
|
|
|
|
ExposedPorts = {
|
|
|
|
"${nginxPort}/tcp" = {};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
# 4. example of pulling an image. could be used as a base for other images
|
2017-08-25 11:47:28 +02:00
|
|
|
nixFromDockerHub = pullImage {
|
2017-05-26 18:06:24 +02:00
|
|
|
imageName = "nixos/nix";
|
2019-03-06 09:18:35 +01:00
|
|
|
imageDigest = "sha256:85299d86263a3059cf19f419f9d286cc9f06d3c13146a8ebbb21b3437f598357";
|
2019-03-26 10:35:21 +01:00
|
|
|
sha256 = "07q9y9r7fsd18sy95ybrvclpkhlal12d30ybnf089hq7v1hgxbi7";
|
2019-03-06 09:18:35 +01:00
|
|
|
finalImageTag = "2.2.1";
|
2019-03-26 10:35:21 +01:00
|
|
|
finalImageName = "nix";
|
2017-05-26 18:06:24 +02:00
|
|
|
};
|
2016-10-03 19:07:33 +02:00
|
|
|
|
|
|
|
# 5. example of multiple contents, emacs and vi happily coexisting
|
|
|
|
editors = buildImage {
|
|
|
|
name = "editors";
|
|
|
|
contents = [
|
|
|
|
pkgs.coreutils
|
|
|
|
pkgs.bash
|
|
|
|
pkgs.emacs
|
|
|
|
pkgs.vim
|
|
|
|
pkgs.nano
|
|
|
|
];
|
|
|
|
};
|
2017-08-25 11:47:28 +02:00
|
|
|
|
2018-01-01 09:13:40 +01:00
|
|
|
# 6. nix example to play with the container nix store
|
2017-08-25 11:47:28 +02:00
|
|
|
# docker run -it --rm nix nix-store -qR $(nix-build '<nixpkgs>' -A nix)
|
|
|
|
nix = buildImageWithNixDb {
|
|
|
|
name = "nix";
|
2018-07-06 16:31:59 +02:00
|
|
|
tag = "latest";
|
2017-08-25 11:47:28 +02:00
|
|
|
contents = [
|
2017-09-25 09:39:15 +02:00
|
|
|
# nix-store uses cat program to display results as specified by
|
|
|
|
# the image env variable NIX_PAGER.
|
|
|
|
pkgs.coreutils
|
2017-08-25 11:47:28 +02:00
|
|
|
pkgs.nix
|
|
|
|
];
|
2017-09-25 09:39:15 +02:00
|
|
|
config = {
|
2019-12-05 09:45:51 +01:00
|
|
|
Env = [
|
|
|
|
"NIX_PAGER=cat"
|
|
|
|
# A user is required by nix
|
|
|
|
# https://github.com/NixOS/nix/blob/9348f9291e5d9e4ba3c4347ea1b235640f54fd79/src/libutil/util.cc#L478
|
|
|
|
"USER=nobody"
|
|
|
|
];
|
2017-09-25 09:39:15 +02:00
|
|
|
};
|
2017-08-25 11:47:28 +02:00
|
|
|
};
|
2018-02-01 16:13:05 +01:00
|
|
|
|
|
|
|
# 7. example of adding something on top of an image pull by our
|
|
|
|
# dockerTools chain.
|
|
|
|
onTopOfPulledImage = buildImage {
|
|
|
|
name = "onTopOfPulledImage";
|
2018-07-06 16:31:59 +02:00
|
|
|
tag = "latest";
|
2018-02-01 16:13:05 +01:00
|
|
|
fromImage = nixFromDockerHub;
|
|
|
|
contents = [ pkgs.hello ];
|
|
|
|
};
|
2018-05-23 02:25:04 +02:00
|
|
|
|
|
|
|
# 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";
|
2018-07-06 16:31:59 +02:00
|
|
|
tag = "latest";
|
2018-05-23 02:25:04 +02:00
|
|
|
contents = [ 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'';
|
|
|
|
};
|
2018-09-20 19:02:22 +02:00
|
|
|
|
|
|
|
# 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";
|
|
|
|
contents = [ pkgs.coreutils ];
|
|
|
|
created = "now";
|
|
|
|
};
|
2018-09-27 20:16:23 +02:00
|
|
|
|
|
|
|
# 10. Create a layered image
|
|
|
|
layered-image = pkgs.dockerTools.buildLayeredImage {
|
|
|
|
name = "layered-image";
|
|
|
|
tag = "latest";
|
2018-12-25 23:04:16 +01:00
|
|
|
extraCommands = ''echo "(extraCommand)" > extraCommands'';
|
2018-09-27 20:16:23 +02:00
|
|
|
config.Cmd = [ "${pkgs.hello}/bin/hello" ];
|
dockerTools.buildImage: support using a layered image in fromImage
Docker images used to be, essentially, a linked list of layers. Each
layer would have a tarball and a json document pointing to its parent,
and the image pointed to the top layer:
imageA ----> layerA
|
v
layerB
|
v
layerC
The current image spec changed this format to where the Image defined
the order and set of layers:
imageA ---> layerA
|--> layerB
`--> layerC
For backwards compatibility, docker produces images which follow both
specs: layers point to parents, and images also point to the entire
list:
imageA ---> layerA
| |
| v
|--> layerB
| |
| v
`--> layerC
This is nice for tooling which supported the older version and never
updated to support the newer format.
Our `buildImage` code only supported the old version, so in order for
`buildImage` to properly generate an image based on another image
with `fromImage`, the parent image's layers must fully support the old
mechanism.
This is not a problem in general, but is a problem with
`buildLayeredImage`.
`buildLayeredImage` creates images with newer image spec, because
individual store paths don't have a guaranteed parent layer. Including
a specific parent ID in the layer's json makes the output less likely
to cache hit when published or pulled.
This means until now, `buildLayeredImage` could not be the input to
`buildImage`.
The changes in this PR change `buildImage` to only use the layer's
manifest when locating parent IDs. This does break buildImage on
extremely old Docker images, though I do wonder how many of these
exist.
This work has been sponsored by Target.
2018-12-04 18:18:06 +01:00
|
|
|
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"
|
|
|
|
];
|
|
|
|
};
|
2018-09-27 20:16:23 +02:00
|
|
|
};
|
2018-12-27 11:10:53 +01:00
|
|
|
|
|
|
|
# 12. 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;
|
|
|
|
};
|
2019-04-30 00:46:00 +02:00
|
|
|
|
|
|
|
# 13. 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";
|
|
|
|
contents = [ pkgs.coreutils ];
|
|
|
|
extraCommands = ''
|
|
|
|
mkdir -p tmp
|
|
|
|
echo layer3 > tmp/layer3
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2019-06-06 10:39:50 +02:00
|
|
|
# 14. 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" ];
|
|
|
|
};
|
|
|
|
|
2020-01-30 10:42:13 +01:00
|
|
|
# 15. 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;
|
|
|
|
};
|
2016-10-03 19:07:33 +02:00
|
|
|
}
|