From 4abe579250242512973f3e32ae7560a7dd3b9656 Mon Sep 17 00:00:00 2001 From: Allen Nelson Date: Tue, 27 Sep 2016 23:42:05 +0000 Subject: [PATCH 1/3] add docs to docker build functions bring back ls_tar replace goPackages with go don't hardcode /nix/store in vmTools more docs --- pkgs/build-support/docker/default.nix | 448 +++++++++++++++++--------- pkgs/build-support/vm/default.nix | 23 +- 2 files changed, 313 insertions(+), 158 deletions(-) diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix index dd5c523b91b5..4cd7df2b0ed7 100644 --- a/pkgs/build-support/docker/default.nix +++ b/pkgs/build-support/docker/default.nix @@ -1,12 +1,30 @@ -{ stdenv, lib, callPackage, runCommand, writeReferencesToFile, writeText, vmTools, writeScript -, docker, shadow, utillinux, coreutils, jshon, e2fsprogs, go, pigz, findutils }: +{ + callPackage, + coreutils, + docker, + e2fsprogs, + findutils, + go, + jshon, + lib, + pigz, + runCommand, + shadow, + stdenv, + storeDir ? builtins.storeDir, + utillinux, + vmTools, + writeReferencesToFile, + writeScript, + writeText, +}: # WARNING: this API is unstable and may be subject to backwards-incompatible changes in the future. - + rec { pullImage = callPackage ./pull.nix {}; - + # We need to sum layer.tar, not a directory, hence tarsum instead of nix-hash. # And we cannot untar it, because then we cannot preserve permissions ecc. tarsum = runCommand "tarsum" { @@ -23,110 +41,138 @@ rec { cp tarsum $out ''; - + # buildEnv creates symlinks to dirs, which is hard to edit inside the overlay VM - mergeDrvs = { drvs, onlyDeps ? false }: + mergeDrvs = { + derivations, + onlyDeps ? false + }: runCommand "merge-drvs" { - inherit drvs onlyDeps; + inherit derivations onlyDeps; } '' - if [ -n "$onlyDeps" ]; then - echo $drvs > $out + if [[ -n "$onlyDeps" ]]; then + echo $derivations > $out exit 0 fi - + mkdir $out - for drv in $drvs; do - echo Merging $drv - if [ -d "$drv" ]; then - cp -drf --preserve=mode -f $drv/* $out/ + for derivation in $derivations; do + echo "Merging $derivation..." + if [[ -d "$derivation" ]]; then + # If it's a directory, copy all of its contents into $out. + cp -drf --preserve=mode -f $derivation/* $out/ else + # Otherwise treat the derivation as a tarball and extract it + # into $out. tar -C $out -xpf $drv || true fi done ''; - - shellScript = text: - writeScript "script.sh" '' - #!${stdenv.shell} - set -e - export PATH=${coreutils}/bin:/bin - - ${text} - ''; + # Helper for setting up the base files for managing users and + # groups, only if such files don't exist already. It is suitable for + # being used in a runAsRoot script. shadowSetup = '' export PATH=${shadow}/bin:$PATH mkdir -p /etc/pam.d - if [ ! -f /etc/passwd ]; then + if [[ ! -f /etc/passwd ]]; then echo "root:x:0:0::/root:/bin/sh" > /etc/passwd echo "root:!x:::::::" > /etc/shadow fi - if [ ! -f /etc/group ]; then + if [[ ! -f /etc/group ]]; then echo "root:x:0:" > /etc/group echo "root:x::" > /etc/gshadow fi - if [ ! -f /etc/pam.d/other ]; then + if [[ ! -f /etc/pam.d/other ]]; then cat > /etc/pam.d/other </dev/null || true)) + parentID=$(cat image/$parentID/json \ + | (jshon -e parent -u 2>/dev/null || true)) done mkdir work mkdir layer mkdir mnt - ${preMount} + ${lib.optionalString (preMount != "") '' + # Execute pre-mount steps + echo "Executing pre-mount steps..." + ${preMount} + ''} if [ -n "$lowerdir" ]; then mount -t overlay overlay -olowerdir=$lowerdir,workdir=work,upperdir=layer mnt @@ -134,13 +180,19 @@ EOF mount --bind layer mnt fi - ${postMount} - + ${lib.optionalString (postMount != "") '' + # Execute post-mount steps + echo "Executing post-mount steps..." + ${postMount} + ''} + umount mnt - pushd layer - find . -type c -exec bash -c 'name="$(basename {})"; touch "$(dirname {})/.wh.$name"; rm "{}"' \; - popd + ( + cd layer + cmd='name="$(basename {})"; touch "$(dirname {})/.wh.$name"; rm "{}"' + find . -type c -exec bash -c "$cmd" \; + ) ${postUmount} ''); @@ -150,76 +202,150 @@ EOF inherit name fromImage fromImageName fromImageTag diskSize; postMount = '' - echo Packing raw image + echo "Packing raw image..." tar -C mnt --mtime=0 -cf $out . ''; }; - - mkPureLayer = { baseJson, contents ? null, extraCommands ? "" }: - runCommand "docker-layer" { + + + # Create an executable shell script which has the coreutils in its + # PATH. Since root scripts are executed in a blank environment, even + # things like `ls` or `echo` will be missing. + shellScript = name: text: + writeScript name '' + #!${stdenv.shell} + set -e + export PATH=${coreutils}/bin:/bin + ${text} + ''; + + # Create a "layer" (set of files). + mkPureLayer = { + # Name of the layer + name, + # JSON containing configuration and metadata for this layer. + baseJson, + # Files to add to the layer. + contents ? null, + # Additional commands to run on the layer before it is tar'd up. + extraCommands ? "" + }: + runCommand "docker-layer-${name}" { inherit baseJson contents extraCommands; buildInputs = [ jshon ]; - } '' + } + '' mkdir layer - if [ -n "$contents" ]; then - echo Adding contents - for c in $contents; do - cp -drf $c/* layer/ - chmod -R ug+w layer/ + if [[ -n "$contents" ]]; then + echo "Adding contents..." + for item in $contents; do + echo "Adding $item" + cp -drf $item/* layer/ done + chmod -R ug+w layer/ + else + echo "No contents to add to layer." fi - pushd layer - ${extraCommands} - popd - - echo Packing layer + if [[ -n $extraCommands ]]; then + (cd layer; eval "$extraCommands") + fi + + # Tar up the layer and throw it into 'layer.tar'. + echo "Packing layer..." mkdir $out tar -C layer --mtime=0 -cf $out/layer.tar . - ts=$(${tarsum} < $out/layer.tar) - cat ${baseJson} | jshon -s "$ts" -i checksum > $out/json + + # Compute a checksum of the tarball. + echo "Computing layer checksum..." + tarsum=$(${tarsum} < $out/layer.tar) + + # Add a 'checksum' field to the JSON, with the value set to the + # checksum of the tarball. + cat ${baseJson} | jshon -s "$tarsum" -i checksum > $out/json + + # Indicate to docker that we're using schema version 1.0. echo -n "1.0" > $out/VERSION + + echo "Finished building layer '${name}'" ''; - mkRootLayer = { runAsRoot, baseJson, fromImage ? null, fromImageName ? null, fromImageTag ? null - , diskSize ? 1024, contents ? null, extraCommands ? "" }: - let runAsRootScript = writeScript "run-as-root.sh" runAsRoot; + # Make a "root" layer; required if we need to execute commands as a + # privileged user on the image. The commands themselves will be + # performed in a virtual machine sandbox. + mkRootLayer = { + # Name of the image. + name, + # Script to run as root. Bash. + runAsRoot, + # Files to add to the layer. If null, an empty layer will be created. + contents ? null, + # JSON containing configuration and metadata for this layer. + baseJson, + # Existing image onto which to append the new layer. + fromImage ? null, + # Name of the image we're appending onto. + fromImageName ? null, + # Tag of the image we're appending onto. + fromImageTag ? null, + # How much disk to allocate for the temporary virtual machine. + diskSize ? 1024, + # Commands (bash) to run on the layer; these do not require sudo. + extraCommands ? "" + }: + # Generate an executable script from the `runAsRoot` text. + let runAsRootScript = shellScript "run-as-root.sh" runAsRoot; in runWithOverlay { - name = "docker-layer"; - + name = "docker-layer-${name}"; + inherit fromImage fromImageName fromImageTag diskSize; - preMount = lib.optionalString (contents != null) '' - echo Adding contents - for c in ${builtins.toString contents}; do - cp -drf $c/* layer/ - chmod -R ug+w layer/ + preMount = lib.optionalString (contents != null && contents != []) '' + echo "Adding contents..." + for item in ${toString contents}; do + echo "Adding $item..." + cp -drf $item/* layer/ done + chmod -R ug+w layer/ ''; postMount = '' - mkdir -p mnt/{dev,proc,sys,nix/store} + mkdir -p mnt/{dev,proc,sys} mnt${storeDir} + + # Mount /dev, /sys and the nix store as shared folders. mount --rbind /dev mnt/dev mount --rbind /sys mnt/sys - mount --rbind /nix/store mnt/nix/store + mount --rbind ${storeDir} mnt${storeDir} + # Execute the run as root script. See 'man unshare' for + # details on what's going on here; basically this command + # means that the runAsRootScript will be executed in a nearly + # completely isolated environment. unshare -imnpuf --mount-proc chroot mnt ${runAsRootScript} - umount -R mnt/dev mnt/sys mnt/nix/store - rmdir --ignore-fail-on-non-empty mnt/dev mnt/proc mnt/sys mnt/nix/store mnt/nix - ''; - - postUmount = '' - pushd layer - ${extraCommands} - popd - echo Packing layer + # Unmount directories and remove them. + umount -R mnt/dev mnt/sys mnt${storeDir} + rmdir --ignore-fail-on-non-empty \ + mnt/dev mnt/proc mnt/sys mnt${storeDir} \ + mnt$(dirname ${storeDir}) + ''; + + postUmount = '' + (cd layer; eval "${extraCommands}") + + echo "Packing layer..." mkdir $out tar -C layer --mtime=0 -cf $out/layer.tar . + + # Compute the tar checksum and add it to the output json. + echo "Computing checksum..." ts=$(${tarsum} < $out/layer.tar) cat ${baseJson} | jshon -s "$ts" -i checksum > $out/json + # Indicate to docker that we're using schema version 1.0. echo -n "1.0" > $out/VERSION + + echo "Finished building layer '${name}'" ''; }; @@ -229,116 +355,144 @@ EOF # 4. compute the layer id # 5. put the layer in the image # 6. repack the image - buildImage = args@{ name, tag ? "latest" - , fromImage ? null, fromImageName ? null, fromImageTag ? null - , contents ? null, config ? null, runAsRoot ? null - , diskSize ? 1024, extraCommands ? "" }: + buildImage = args@{ + # Image name. + name, + # Image tag. + tag ? "latest", + # Parent image, to append to. + fromImage ? null, + # Name of the parent image; will be read from the image otherwise. + fromImageName ? null, + # Tag of the parent image; will be read from the image otherwise. + fromImageTag ? null, + # Files to put on the image (a nix store path or list of paths). + contents ? null, + # 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 ? "", + # 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, + }: let - baseName = baseNameOf name; + # 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"; - architecture = "amd64"; - os = "linux"; - config = config; + created = "1970-01-01T00:00:01Z"; + architecture = "amd64"; + os = "linux"; + config = config; }); - layer = (if runAsRoot == null - then mkPureLayer { inherit baseJson contents extraCommands; } - else mkRootLayer { inherit baseJson fromImage fromImageName fromImageTag contents runAsRoot diskSize extraCommands; }); - result = runCommand "${baseName}.tar.gz" { + layer = + if runAsRoot == null + then mkPureLayer { inherit name baseJson contents extraCommands; } + else mkRootLayer { inherit name baseJson fromImage fromImageName + fromImageTag contents runAsRoot diskSize + extraCommands; }; + result = runCommand "docker-image-${baseName}.tar.gz" { buildInputs = [ jshon pigz coreutils findutils ]; - imageName = name; imageTag = tag; inherit fromImage baseJson; - layerClosure = writeReferencesToFile layer; - - passthru = { - buildArgs = args; - }; + passthru.buildArgs = args; + passthru.layer = layer; } '' # Print tar contents: # 1: Interpreted as relative to the root directory # 2: With no trailing slashes on directories - # This is useful for ensuring that the output matches the values generated by the "find" command + # This is useful for ensuring that the output matches the + # values generated by the "find" command ls_tar() { - for f in $(tar -tf $1 | xargs realpath -ms --relative-to=.); do - if [ "$f" != "." ]; then - echo "/$f" - fi - done + for f in $(tar -tf $1 | xargs realpath -ms --relative-to=.); do + if [[ "$f" != "." ]]; then + echo "/$f" + fi + done } - + mkdir image touch baseFiles - if [ -n "$fromImage" ]; then - echo Unpacking base image + if [[ -n "$fromImage" ]]; then + echo "Unpacking base image..." tar -C image -xpf "$fromImage" - - if [ -z "$fromImageName" ]; then + + if [[ -z "$fromImageName" ]]; then fromImageName=$(jshon -k < image/repositories|head -n1) fi - if [ -z "$fromImageTag" ]; then - fromImageTag=$(jshon -e $fromImageName -k < image/repositories|head -n1) + if [[ -z "$fromImageTag" ]]; then + fromImageTag=$(jshon -e $fromImageName -k \ + < image/repositories|head -n1) fi - parentID=$(jshon -e $fromImageName -e $fromImageTag -u < image/repositories) - + parentID=$(jshon -e $fromImageName -e $fromImageTag -u \ + < image/repositories) + for l in image/*/layer.tar; do - ls_tar $l >> baseFiles + ls_tar image/*/layer.tar >> baseFiles done fi chmod -R ug+rw image - + mkdir temp cp ${layer}/* temp/ chmod ug+w temp/* + echo "$(dirname ${storeDir})" >> layerFiles + echo '${storeDir}' >> layerFiles for dep in $(cat $layerClosure); do - find $dep -path "${layer}" -prune -o -print >> layerFiles + find $dep >> layerFiles done - if [ -s layerFiles ]; then - # FIXME: might not be /nix/store - echo '/nix' >> layerFiles - echo '/nix/store' >> layerFiles - fi - - echo Adding layer + echo "Adding layer..." + # Record the contents of the tarball with ls_tar. ls_tar temp/layer.tar >> baseFiles - comm <(sort -u baseFiles) <(sort -u layerFiles) -1 -3 > newFiles - tar -rpf temp/layer.tar --mtime=0 --no-recursion --files-from newFiles 2>/dev/null || true - echo Adding meta - - if [ -n "$parentID" ]; then + # Get the files in the new layer which were *not* present in + # the old layer, and record them as newFiles. + comm <(sort -n baseFiles|uniq) \ + <(sort -n layerFiles|uniq|grep -v ${layer}) -1 -3 > newFiles + # Append the new files to the layer. + tar -rpf temp/layer.tar --mtime=0 --no-recursion --files-from newFiles + + echo "Adding meta..." + + # If we have a parentID, add it to the json metadata. + if [[ -n "$parentID" ]]; then cat temp/json | jshon -s "$parentID" -i parent > tmpjson mv tmpjson temp/json fi - + + # Take the sha256 sum of the generated json and use it as the layer ID. + # Compute the size and add it to the json under the 'Size' field. layerID=$(sha256sum temp/json|cut -d ' ' -f 1) size=$(stat --printf="%s" temp/layer.tar) cat temp/json | jshon -s "$layerID" -i id -n $size -i Size > tmpjson mv tmpjson temp/json + # Use the temp folder we've been working on to create a new image. mv temp image/$layerID - + + # Store the json under the name image/repositories. jshon -n object \ -n object -s "$layerID" -i "$imageTag" \ -i "$imageName" > image/repositories + # Make the image read-only. chmod -R a-w image - echo Cooking the image + echo "Cooking the image..." tar -C image --mtime=0 -c . | pigz -nT > $out + + echo "Finished." ''; in - - result; - + result; } diff --git a/pkgs/build-support/vm/default.nix b/pkgs/build-support/vm/default.nix index 245d0bebb45d..f96416b288f1 100644 --- a/pkgs/build-support/vm/default.nix +++ b/pkgs/build-support/vm/default.nix @@ -1,6 +1,7 @@ { pkgs , kernel ? pkgs.linux , img ? "bzImage" +, storeDir ? builtins.storeDir , rootModules ? [ "virtio_pci" "virtio_blk" "virtio_balloon" "virtio_rng" "ext4" "unix" "9p" "9pnet_virtio" "rtc_cmos" ] }: @@ -128,8 +129,8 @@ rec { mount -t devpts none /fs/dev/pts echo "mounting Nix store..." - mkdir -p /fs/nix/store - mount -t 9p store /fs/nix/store -o trans=virtio,version=9p2000.L,cache=loose + mkdir -p /fs${storeDir} + mount -t 9p store /fs${storeDir} -o trans=virtio,version=9p2000.L,cache=loose mkdir -p /fs/tmp /fs/run /fs/var mount -t tmpfs -o "mode=1777" none /fs/tmp @@ -172,7 +173,7 @@ rec { # apparent KVM > 1.5.2 bug. ${pkgs.utillinux}/bin/hwclock -s - export NIX_STORE=/nix/store + export NIX_STORE=${storeDir} export NIX_BUILD_TOP=/tmp export TMPDIR=/tmp export PATH=/empty @@ -220,7 +221,7 @@ rec { ${lib.optionalString (pkgs.stdenv.system == "x86_64-linux") "-cpu kvm64"} \ -nographic -no-reboot \ -device virtio-rng-pci \ - -virtfs local,path=/nix/store,security_model=none,mount_tag=store \ + -virtfs local,path=${storeDir},security_model=none,mount_tag=store \ -virtfs local,path=$TMPDIR/xchg,security_model=none,mount_tag=xchg \ -drive file=$diskImage,if=virtio,cache=unsafe,werror=report \ -kernel ${kernel}/${img} \ @@ -298,7 +299,7 @@ rec { /* Run a derivation in a Linux virtual machine (using Qemu/KVM). By default, there is no disk image; the root filesystem is a tmpfs, - and /nix/store is shared with the host (via the 9P protocol). + and the nix store is shared with the host (via the 9P protocol). Thus, any pure Nix derivation should run unmodified, e.g. the call @@ -434,8 +435,8 @@ rec { chroot=$(type -tP chroot) # Make the Nix store available in /mnt, because that's where the RPMs live. - mkdir -p /mnt/nix/store - ${utillinux}/bin/mount -o bind /nix/store /mnt/nix/store + mkdir -p /mnt${storeDir} + ${utillinux}/bin/mount -o bind ${storeDir} /mnt${storeDir} # Newer distributions like Fedora 18 require /lib etc. to be # symlinked to /usr. @@ -474,7 +475,7 @@ rec { rm /mnt/.debug - ${utillinux}/bin/umount /mnt/nix/store /mnt/tmp ${lib.optionalString unifiedSystemDir "/mnt/proc"} + ${utillinux}/bin/umount /mnt${storeDir} /mnt/tmp ${lib.optionalString unifiedSystemDir "/mnt/proc"} ${utillinux}/bin/umount /mnt ''; @@ -605,8 +606,8 @@ rec { done # Make the Nix store available in /mnt, because that's where the .debs live. - mkdir -p /mnt/inst/nix/store - ${utillinux}/bin/mount -o bind /nix/store /mnt/inst/nix/store + mkdir -p /mnt/inst${storeDir} + ${utillinux}/bin/mount -o bind ${storeDir} /mnt/inst${storeDir} ${utillinux}/bin/mount -o bind /proc /mnt/proc ${utillinux}/bin/mount -o bind /dev /mnt/dev @@ -654,7 +655,7 @@ rec { rm /mnt/.debug - ${utillinux}/bin/umount /mnt/inst/nix/store + ${utillinux}/bin/umount /mnt/inst${storeDir} ${utillinux}/bin/umount /mnt/proc ${utillinux}/bin/umount /mnt/dev ${utillinux}/bin/umount /mnt From b9007c8d83f91e7e8614559af292de4950c616c1 Mon Sep 17 00:00:00 2001 From: Allen Nelson Date: Mon, 3 Oct 2016 12:07:33 -0500 Subject: [PATCH 2/3] add examples file --- pkgs/build-support/docker/default.nix | 5 ++ pkgs/build-support/docker/examples.nix | 104 +++++++++++++++++++++++++ 2 files changed, 109 insertions(+) create mode 100644 pkgs/build-support/docker/examples.nix diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix index 4cd7df2b0ed7..578025c11138 100644 --- a/pkgs/build-support/docker/default.nix +++ b/pkgs/build-support/docker/default.nix @@ -7,6 +7,7 @@ go, jshon, lib, + pkgs, pigz, runCommand, shadow, @@ -23,6 +24,10 @@ rec { + examples = import ./examples.nix { + inherit pkgs buildImage pullImage shadowSetup; + }; + pullImage = callPackage ./pull.nix {}; # We need to sum layer.tar, not a directory, hence tarsum instead of nix-hash. diff --git a/pkgs/build-support/docker/examples.nix b/pkgs/build-support/docker/examples.nix new file mode 100644 index 000000000000..cce8f53834e4 --- /dev/null +++ b/pkgs/build-support/docker/examples.nix @@ -0,0 +1,104 @@ +# 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 '' -A dockerTools.examples.redis +# $ docker load < result + +{ pkgs, buildImage, pullImage, shadowSetup }: + +rec { + # 1. basic example + bash = buildImage { + name = "bash"; + 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" '' +

Hello from NGINX

+ ''; + in + buildImage { + name = "nginx-container"; + 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 + debian = pullImage { + imageName = "debian"; + imageTag = "jessie"; + # this hash will need change if the tag is updated at docker hub + sha256 = "18kd495lc2k35h03bpcbdjnix17nlqbwf6nmq3sb161blf0dk14q"; + }; + + # 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 + ]; + }; +} From 940aafcbcc849a0a90219299626672085a9fe18b Mon Sep 17 00:00:00 2001 From: Allen Nelson Date: Mon, 3 Oct 2016 15:12:29 -0500 Subject: [PATCH 3/3] use rsync, comment out pulls --- pkgs/build-support/docker/default.nix | 11 +++++------ pkgs/build-support/docker/examples.nix | 16 ++++++++++------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/pkgs/build-support/docker/default.nix b/pkgs/build-support/docker/default.nix index 578025c11138..b3db68a665dc 100644 --- a/pkgs/build-support/docker/default.nix +++ b/pkgs/build-support/docker/default.nix @@ -10,6 +10,7 @@ pkgs, pigz, runCommand, + rsync, shadow, stdenv, storeDir ? builtins.storeDir, @@ -120,7 +121,7 @@ rec { }; inherit fromImage fromImageName fromImageTag; - buildInputs = [ utillinux e2fsprogs jshon ]; + buildInputs = [ utillinux e2fsprogs jshon rsync ]; } '' rm -rf $out @@ -238,7 +239,7 @@ rec { runCommand "docker-layer-${name}" { inherit baseJson contents extraCommands; - buildInputs = [ jshon ]; + buildInputs = [ jshon rsync ]; } '' mkdir layer @@ -246,9 +247,8 @@ rec { echo "Adding contents..." for item in $contents; do echo "Adding $item" - cp -drf $item/* layer/ + rsync -a $item/ layer/ done - chmod -R ug+w layer/ else echo "No contents to add to layer." fi @@ -310,9 +310,8 @@ rec { echo "Adding contents..." for item in ${toString contents}; do echo "Adding $item..." - cp -drf $item/* layer/ + rsync -a $item/ layer/ done - chmod -R ug+w layer/ ''; postMount = '' diff --git a/pkgs/build-support/docker/examples.nix b/pkgs/build-support/docker/examples.nix index cce8f53834e4..05b4a9b4f2d2 100644 --- a/pkgs/build-support/docker/examples.nix +++ b/pkgs/build-support/docker/examples.nix @@ -83,12 +83,16 @@ rec { }; # 4. example of pulling an image. could be used as a base for other images - debian = pullImage { - imageName = "debian"; - imageTag = "jessie"; - # this hash will need change if the tag is updated at docker hub - sha256 = "18kd495lc2k35h03bpcbdjnix17nlqbwf6nmq3sb161blf0dk14q"; - }; + # + # ***** Currently broken, getting 404s. Perhaps the docker API has changed? + # + # + # debian = pullImage { + # imageName = "debian"; + # imageTag = "jessie"; + # # this hash will need change if the tag is updated at docker hub + # sha256 = "18kd495lc2k35h03bpcbdjnix17nlqbwf6nmq3sb161blf0dk14q"; + # }; # 5. example of multiple contents, emacs and vi happily coexisting editors = buildImage {