Merge branch 'master' into docker-dirlinks

This commit is contained in:
Ryan Trinkle
2017-11-03 10:53:00 -04:00
committed by GitHub
8350 changed files with 251021 additions and 185547 deletions
+89 -14
View File
@@ -6,9 +6,12 @@
findutils,
go,
jshon,
jq,
lib,
pkgs,
pigz,
nixUnstable,
perl,
runCommand,
rsync,
shadow,
@@ -26,7 +29,7 @@
rec {
examples = import ./examples.nix {
inherit pkgs buildImage pullImage shadowSetup;
inherit pkgs buildImage pullImage shadowSetup buildImageWithNixDb;
};
pullImage = callPackage ./pull.nix {};
@@ -42,7 +45,7 @@ rec {
cp ${./tarsum.go} tarsum.go
export GOPATH=$(pwd)
mkdir src
ln -sT ${docker.src}/pkg/tarsum src/tarsum
ln -sT ${docker.src}/components/engine/pkg/tarsum src/tarsum
go build
cp tarsum $out
@@ -82,7 +85,7 @@ rec {
export PATH=${shadow}/bin:$PATH
mkdir -p /etc/pam.d
if [[ ! -f /etc/passwd ]]; then
echo "root:x:0:0::/root:/bin/sh" > /etc/passwd
echo "root:x:0:0::/root:${stdenv.shell}" > /etc/passwd
echo "root:!x:::::::" > /etc/shadow
fi
if [[ ! -f /etc/group ]]; then
@@ -225,6 +228,19 @@ rec {
${text}
'';
nixRegistration = contents: runCommand "nix-registration" {
buildInputs = [ nixUnstable perl ];
# For obtaining the closure of `contents'.
exportReferencesGraph =
let contentsList = if builtins.isList contents then contents else [ contents ];
in map (x: [("closure-" + baseNameOf x) x]) contentsList;
}
''
mkdir $out
printRegistration=1 perl ${pkgs.pathsFromGraph} closure-* > $out/db.dump
perl ${pkgs.pathsFromGraph} closure-* > $out/storePaths
'';
# Create a "layer" (set of files).
mkPureLayer = {
# Name of the layer
@@ -238,11 +254,10 @@ rec {
# into directories.
keepContentsDirlinks ? false,
# Additional commands to run on the layer before it is tar'd up.
extraCommands ? ""
extraCommands ? "", uid ? 0, gid ? 0
}:
runCommand "docker-layer-${name}" {
inherit baseJson contents extraCommands;
buildInputs = [ jshon rsync ];
}
''
@@ -257,6 +272,8 @@ rec {
echo "No contents to add to layer."
fi
chmod ug+w layer
if [[ -n $extraCommands ]]; then
(cd layer; eval "$extraCommands")
fi
@@ -264,7 +281,7 @@ rec {
# Tar up the layer and throw it into 'layer.tar'.
echo "Packing layer..."
mkdir $out
tar -C layer --mtime="@$SOURCE_DATE_EPOCH" -cf $out/layer.tar .
tar -C layer --mtime="@$SOURCE_DATE_EPOCH" --owner=${toString uid} --group=${toString gid} -cf $out/layer.tar .
# Compute a checksum of the tarball.
echo "Computing layer checksum..."
@@ -320,6 +337,8 @@ rec {
echo "Adding $item..."
rsync -a${if keepContentsDirlinks then "K" else "k"} --chown=0:0 $item/ layer/
done
chmod ug+w layer
'';
postMount = ''
@@ -387,11 +406,13 @@ rec {
# Docker config; e.g. what command to run on the container.
config ? null,
# Optional bash script to run on the files prior to fixturizing the layer.
extraCommands ? "",
extraCommands ? "", uid ? 0, gid ? 0,
# Optional bash script to run as root on the image when provisioning.
runAsRoot ? null,
# Size of the virtual machine disk to provision when building the image.
diskSize ? 1024,
# Time of creation of the image.
created ? "1970-01-01T00:00:01Z",
}:
let
@@ -399,17 +420,16 @@ rec {
# Create a JSON blob of the configuration. Set the date to unix zero.
baseJson = writeText "${baseName}-config.json" (builtins.toJSON {
created = "1970-01-01T00:00:01Z";
inherit created config;
architecture = "amd64";
os = "linux";
config = config;
});
layer =
if runAsRoot == null
then mkPureLayer {
name = baseName;
inherit baseJson contents keepContentsDirlinks extraCommands;
inherit baseJson contents keepContentsDirlinks extraCommands uid gid;
} else mkRootLayer {
name = baseName;
inherit baseJson fromImage fromImageName fromImageTag
@@ -417,9 +437,10 @@ rec {
extraCommands;
};
result = runCommand "docker-image-${baseName}.tar.gz" {
buildInputs = [ jshon pigz coreutils findutils ];
imageName = name;
imageTag = tag;
buildInputs = [ jshon pigz coreutils findutils jq ];
# Image name and tag must be lowercase
imageName = lib.toLower name;
imageTag = lib.toLower tag;
inherit fromImage baseJson;
layerClosure = writeReferencesToFile layer;
passthru.buildArgs = args;
@@ -443,6 +464,9 @@ rec {
if [[ -n "$fromImage" ]]; then
echo "Unpacking base image..."
tar -C image -xpf "$fromImage"
# Do not import the base image configuration and manifest
chmod a+w image image/*.json
rm -f image/*.json
if [[ -z "$fromImageName" ]]; then
fromImageName=$(jshon -k < image/repositories|head -n1)
@@ -501,6 +525,24 @@ rec {
# Use the temp folder we've been working on to create a new image.
mv temp image/$layerID
# Create image json and image manifest
imageJson=$(cat ${baseJson} | jq ". + {\"rootfs\": {\"diff_ids\": [], \"type\": \"layers\"}}")
manifestJson=$(jq -n "[{\"RepoTags\":[\"$imageName:$imageTag\"]}]")
currentID=$layerID
while [[ -n "$currentID" ]]; do
layerChecksum=$(sha256sum image/$currentID/layer.tar | cut -d ' ' -f1)
imageJson=$(echo "$imageJson" | jq ".history |= [{\"created\": \"${created}\"}] + .")
imageJson=$(echo "$imageJson" | jq ".rootfs.diff_ids |= [\"sha256:$layerChecksum\"] + .")
manifestJson=$(echo "$manifestJson" | jq ".[0].Layers |= [\"$currentID/layer.tar\"] + .")
currentID=$(cat image/$currentID/json | (jshon -e parent -u 2>/dev/null || true))
done
imageJsonChecksum=$(echo "$imageJson" | sha256sum | cut -d ' ' -f1)
echo "$imageJson" > "image/$imageJsonChecksum.json"
manifestJson=$(echo "$manifestJson" | jq ".[0].Config = \"$imageJsonChecksum.json\"")
echo "$manifestJson" > image/manifest.json
# Store the json under the name image/repositories.
jshon -n object \
-n object -s "$layerID" -i "$imageTag" \
@@ -510,11 +552,44 @@ rec {
chmod -R a-w image
echo "Cooking the image..."
tar -C image --mtime="@$SOURCE_DATE_EPOCH" -c . | pigz -nT > $out
tar -C image --mtime="@$SOURCE_DATE_EPOCH" --owner=0 --group=0 --xform s:'./':: -c . | pigz -nT > $out
echo "Finished."
'';
in
result;
# Build an image and populate its nix database with the provided
# contents. The main purpose is to be able to use nix commands in
# the container.
# Be careful since this doesn't work well with multilayer.
buildImageWithNixDb = args@{ contents ? null, extraCommands ? "", ... }:
buildImage (args // {
extraCommands = ''
echo "Generating the nix database..."
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 " be better to only have one layer that contains a nix store."
# This requires Nix 1.12 or higher
export NIX_REMOTE=local?root=$PWD
${nixUnstable}/bin/nix-store --load-db < ${nixRegistration contents}/db.dump
# We fill the store in order to run the 'verify' command that
# generates hash and size of output paths.
# Note when Nix 1.12 is be the stable one, the database dump
# generated by the exportReferencesGraph function will
# contains sha and size. See
# https://github.com/NixOS/nix/commit/c2b0d8749f7e77afc1c4b3e8dd36b7ee9720af4a
storePaths=$(cat ${nixRegistration contents}/storePaths)
echo "Copying everything to /nix/store (will take a while)..."
cp -prd $storePaths nix/store/
${nixUnstable}/bin/nix-store --verify --check-contents
mkdir -p nix/var/nix/gcroots/docker/
for i in ${lib.concatStringsSep " " contents}; do
ln -s $i nix/var/nix/gcroots/docker/$(basename $i)
done;
'' + extraCommands;
});
}