1# Examples of using the docker tools to build packages.
2#
3# This file defines several docker images. In order to use an image,
4# build its derivation with `nix-build`, and then load the result with
5# `docker load`. For example:
6#
7# $ nix-build '<nixpkgs>' -A dockerTools.examples.redis
8# $ docker load < result
9
10{ pkgs, buildImage, buildLayeredImage, fakeNss, pullImage, shadowSetup, buildImageWithNixDb, pkgsCross, streamNixShellImage }:
11
12let
13 nixosLib = import ../../../nixos/lib {
14 # Experimental features need testing too, but there's no point in warning
15 # about it, so we enable the feature flag.
16 featureFlags.minimalModules = {};
17 };
18 evalMinimalConfig = module: nixosLib.evalModules { modules = [ module ]; };
19
20in
21
22rec {
23 # 1. basic example
24 bash = buildImage {
25 name = "bash";
26 tag = "latest";
27 copyToRoot = pkgs.buildEnv {
28 name = "image-root";
29 paths = [ pkgs.bashInteractive ];
30 pathsToLink = [ "/bin" ];
31 };
32 };
33
34 # 2. service example, layered on another image
35 redis = buildImage {
36 name = "redis";
37 tag = "latest";
38
39 # for example's sake, we can layer redis on top of bash or debian
40 fromImage = bash;
41 # fromImage = debian;
42
43 copyToRoot = pkgs.buildEnv {
44 name = "image-root";
45 paths = [ pkgs.redis ];
46 pathsToLink = [ "/bin" ];
47 };
48
49 runAsRoot = ''
50 mkdir -p /data
51 '';
52
53 config = {
54 Cmd = [ "/bin/redis-server" ];
55 WorkingDir = "/data";
56 Volumes = {
57 "/data" = {};
58 };
59 };
60 };
61
62 # 3. another service example
63 nginx = let
64 nginxPort = "80";
65 nginxConf = pkgs.writeText "nginx.conf" ''
66 user nobody nobody;
67 daemon off;
68 error_log /dev/stdout info;
69 pid /dev/null;
70 events {}
71 http {
72 access_log /dev/stdout;
73 server {
74 listen ${nginxPort};
75 index index.html;
76 location / {
77 root ${nginxWebRoot};
78 }
79 }
80 }
81 '';
82 nginxWebRoot = pkgs.writeTextDir "index.html" ''
83 <html><body><h1>Hello from NGINX</h1></body></html>
84 '';
85 in
86 buildLayeredImage {
87 name = "nginx-container";
88 tag = "latest";
89 contents = [
90 fakeNss
91 pkgs.nginx
92 ];
93
94 extraCommands = ''
95 mkdir -p tmp/nginx_client_body
96
97 # nginx still tries to read this directory even if error_log
98 # directive is specifying another file :/
99 mkdir -p var/log/nginx
100 '';
101
102 config = {
103 Cmd = [ "nginx" "-c" nginxConf ];
104 ExposedPorts = {
105 "${nginxPort}/tcp" = {};
106 };
107 };
108 };
109
110 # 4. example of pulling an image. could be used as a base for other images
111 nixFromDockerHub = pullImage {
112 imageName = "nixos/nix";
113 imageDigest = "sha256:85299d86263a3059cf19f419f9d286cc9f06d3c13146a8ebbb21b3437f598357";
114 sha256 = "19fw0n3wmddahzr20mhdqv6jkjn1kanh6n2mrr08ai53dr8ph5n7";
115 finalImageTag = "2.2.1";
116 finalImageName = "nix";
117 };
118 # Same example, but re-fetches every time the fetcher implementation changes.
119 # NOTE: Only use this for testing, or you'd be wasting a lot of time, network and space.
120 testNixFromDockerHub = pkgs.testers.invalidateFetcherByDrvHash pullImage {
121 imageName = "nixos/nix";
122 imageDigest = "sha256:85299d86263a3059cf19f419f9d286cc9f06d3c13146a8ebbb21b3437f598357";
123 sha256 = "19fw0n3wmddahzr20mhdqv6jkjn1kanh6n2mrr08ai53dr8ph5n7";
124 finalImageTag = "2.2.1";
125 finalImageName = "nix";
126 };
127
128 # 5. example of multiple contents, emacs and vi happily coexisting
129 editors = buildImage {
130 name = "editors";
131 copyToRoot = pkgs.buildEnv {
132 name = "image-root";
133 pathsToLink = [ "/bin" ];
134 paths = [
135 pkgs.coreutils
136 pkgs.bash
137 pkgs.emacs
138 pkgs.vim
139 pkgs.nano
140 ];
141 };
142 };
143
144 # 6. nix example to play with the container nix store
145 # docker run -it --rm nix nix-store -qR $(nix-build '<nixpkgs>' -A nix)
146 nix = buildImageWithNixDb {
147 name = "nix";
148 tag = "latest";
149 copyToRoot = pkgs.buildEnv {
150 name = "image-root";
151 pathsToLink = [ "/bin" ];
152 paths = [
153 # nix-store uses cat program to display results as specified by
154 # the image env variable NIX_PAGER.
155 pkgs.coreutils
156 pkgs.nix
157 pkgs.bash
158 ];
159 };
160 config = {
161 Env = [
162 "NIX_PAGER=cat"
163 # A user is required by nix
164 # https://github.com/NixOS/nix/blob/9348f9291e5d9e4ba3c4347ea1b235640f54fd79/src/libutil/util.cc#L478
165 "USER=nobody"
166 ];
167 };
168 };
169
170 # 7. example of adding something on top of an image pull by our
171 # dockerTools chain.
172 onTopOfPulledImage = buildImage {
173 name = "onTopOfPulledImage";
174 tag = "latest";
175 fromImage = nixFromDockerHub;
176 copyToRoot = pkgs.buildEnv {
177 name = "image-root";
178 pathsToLink = [ "/bin" ];
179 paths = [ pkgs.hello ];
180 };
181 };
182
183 # 8. regression test for erroneous use of eval and string expansion.
184 # See issue #34779 and PR #40947 for details.
185 runAsRootExtraCommands = pkgs.dockerTools.buildImage {
186 name = "runAsRootExtraCommands";
187 tag = "latest";
188 copyToRoot = pkgs.buildEnv {
189 name = "image-root";
190 pathsToLink = [ "/bin" ];
191 paths = [ pkgs.coreutils ];
192 };
193 # The parens here are to create problematic bash to embed and eval. In case
194 # this is *embedded* into the script (with nix expansion) the initial quotes
195 # will close the string and the following parens are unexpected
196 runAsRoot = ''echo "(runAsRoot)" > runAsRoot'';
197 extraCommands = ''echo "(extraCommand)" > extraCommands'';
198 };
199
200 # 9. Ensure that setting created to now results in a date which
201 # isn't the epoch + 1
202 unstableDate = pkgs.dockerTools.buildImage {
203 name = "unstable-date";
204 tag = "latest";
205 copyToRoot = pkgs.buildEnv {
206 name = "image-root";
207 pathsToLink = [ "/bin" ];
208 paths = [ pkgs.coreutils ];
209 };
210 created = "now";
211 };
212
213 # 10. Create a layered image
214 layered-image = pkgs.dockerTools.buildLayeredImage {
215 name = "layered-image";
216 tag = "latest";
217 extraCommands = ''echo "(extraCommand)" > extraCommands'';
218 config.Cmd = [ "${pkgs.hello}/bin/hello" ];
219 contents = [ pkgs.hello pkgs.bash pkgs.coreutils ];
220 };
221
222 # 11. Create an image on top of a layered image
223 layered-on-top = pkgs.dockerTools.buildImage {
224 name = "layered-on-top";
225 tag = "latest";
226 fromImage = layered-image;
227 extraCommands = ''
228 mkdir ./example-output
229 chmod 777 ./example-output
230 '';
231 config = {
232 Env = [ "PATH=${pkgs.coreutils}/bin/" ];
233 WorkingDir = "/example-output";
234 Cmd = [
235 "${pkgs.bash}/bin/bash" "-c" "echo hello > foo; cat foo"
236 ];
237 };
238 };
239
240 # 12 Create a layered image on top of a layered image
241 layered-on-top-layered = pkgs.dockerTools.buildLayeredImage {
242 name = "layered-on-top-layered";
243 tag = "latest";
244 fromImage = layered-image;
245 extraCommands = ''
246 mkdir ./example-output
247 chmod 777 ./example-output
248 '';
249 config = {
250 Env = [ "PATH=${pkgs.coreutils}/bin/" ];
251 WorkingDir = "/example-output";
252 Cmd = [
253 "${pkgs.bash}/bin/bash" "-c" "echo hello > foo; cat foo"
254 ];
255 };
256 };
257
258 # 13. example of running something as root on top of a parent image
259 # Regression test related to PR #52109
260 runAsRootParentImage = buildImage {
261 name = "runAsRootParentImage";
262 tag = "latest";
263 runAsRoot = "touch /example-file";
264 fromImage = bash;
265 };
266
267 # 14. example of 3 layers images This image is used to verify the
268 # order of layers is correct.
269 # It allows to validate
270 # - the layer of parent are below
271 # - the order of parent layer is preserved at image build time
272 # (this is why there are 3 images)
273 layersOrder = let
274 l1 = pkgs.dockerTools.buildImage {
275 name = "l1";
276 tag = "latest";
277 extraCommands = ''
278 mkdir -p tmp
279 echo layer1 > tmp/layer1
280 echo layer1 > tmp/layer2
281 echo layer1 > tmp/layer3
282 '';
283 };
284 l2 = pkgs.dockerTools.buildImage {
285 name = "l2";
286 fromImage = l1;
287 tag = "latest";
288 extraCommands = ''
289 mkdir -p tmp
290 echo layer2 > tmp/layer2
291 echo layer2 > tmp/layer3
292 '';
293 };
294 in pkgs.dockerTools.buildImage {
295 name = "l3";
296 fromImage = l2;
297 tag = "latest";
298 copyToRoot = pkgs.buildEnv {
299 name = "image-root";
300 pathsToLink = [ "/bin" ];
301 paths = [ pkgs.coreutils ];
302 };
303 extraCommands = ''
304 mkdir -p tmp
305 echo layer3 > tmp/layer3
306 '';
307 };
308
309 # 15. Environment variable inheritance.
310 # Child image should inherit parents environment variables,
311 # optionally overriding them.
312 environmentVariablesParent = pkgs.dockerTools.buildImage {
313 name = "parent";
314 tag = "latest";
315 config = {
316 Env = [
317 "FROM_PARENT=true"
318 "LAST_LAYER=parent"
319 ];
320 };
321 };
322
323 environmentVariables = pkgs.dockerTools.buildImage {
324 name = "child";
325 fromImage = environmentVariablesParent;
326 tag = "latest";
327 copyToRoot = pkgs.buildEnv {
328 name = "image-root";
329 pathsToLink = [ "/bin" ];
330 paths = [ pkgs.coreutils ];
331 };
332 config = {
333 Env = [
334 "FROM_CHILD=true"
335 "LAST_LAYER=child"
336 ];
337 };
338 };
339
340 environmentVariablesLayered = pkgs.dockerTools.buildLayeredImage {
341 name = "child";
342 fromImage = environmentVariablesParent;
343 tag = "latest";
344 contents = [ pkgs.coreutils ];
345 config = {
346 Env = [
347 "FROM_CHILD=true"
348 "LAST_LAYER=child"
349 ];
350 };
351 };
352
353 # 16. Create another layered image, for comparing layers with image 10.
354 another-layered-image = pkgs.dockerTools.buildLayeredImage {
355 name = "another-layered-image";
356 tag = "latest";
357 config.Cmd = [ "${pkgs.hello}/bin/hello" ];
358 };
359
360 # 17. Create a layered image with only 2 layers
361 two-layered-image = pkgs.dockerTools.buildLayeredImage {
362 name = "two-layered-image";
363 tag = "latest";
364 config.Cmd = [ "${pkgs.hello}/bin/hello" ];
365 contents = [ pkgs.bash pkgs.hello ];
366 maxLayers = 2;
367 };
368
369 # 18. Create a layered image with more packages than max layers.
370 # coreutils and hello are part of the same layer
371 bulk-layer = pkgs.dockerTools.buildLayeredImage {
372 name = "bulk-layer";
373 tag = "latest";
374 contents = with pkgs; [
375 coreutils hello
376 ];
377 maxLayers = 2;
378 };
379
380 # 19. Create a layered image with a base image and more packages than max
381 # layers. coreutils and hello are part of the same layer
382 layered-bulk-layer = pkgs.dockerTools.buildLayeredImage {
383 name = "layered-bulk-layer";
384 tag = "latest";
385 fromImage = two-layered-image;
386 contents = with pkgs; [
387 coreutils hello
388 ];
389 maxLayers = 4;
390 };
391
392 # 20. Create a "layered" image without nix store layers. This is not
393 # recommended, but can be useful for base images in rare cases.
394 no-store-paths = pkgs.dockerTools.buildLayeredImage {
395 name = "no-store-paths";
396 tag = "latest";
397 extraCommands = ''
398 # This removes sharing of busybox and is not recommended. We do this
399 # to make the example suitable as a test case with working binaries.
400 cp -r ${pkgs.pkgsStatic.busybox}/* .
401
402 # This is a "build" dependency that will not appear in the image
403 ${pkgs.hello}/bin/hello
404 '';
405 };
406
407 nixLayered = pkgs.dockerTools.buildLayeredImageWithNixDb {
408 name = "nix-layered";
409 tag = "latest";
410 contents = [
411 # nix-store uses cat program to display results as specified by
412 # the image env variable NIX_PAGER.
413 pkgs.coreutils
414 pkgs.nix
415 pkgs.bash
416 ];
417 config = {
418 Env = [
419 "NIX_PAGER=cat"
420 # A user is required by nix
421 # https://github.com/NixOS/nix/blob/9348f9291e5d9e4ba3c4347ea1b235640f54fd79/src/libutil/util.cc#L478
422 "USER=nobody"
423 ];
424 };
425 };
426
427 # 21. Support files in the store on buildLayeredImage
428 # See: https://github.com/NixOS/nixpkgs/pull/91084#issuecomment-653496223
429 filesInStore = pkgs.dockerTools.buildLayeredImageWithNixDb {
430 name = "file-in-store";
431 tag = "latest";
432 contents = [
433 pkgs.coreutils
434 pkgs.nix
435 (pkgs.writeScriptBin "myscript" ''
436 #!${pkgs.runtimeShell}
437 cat ${pkgs.writeText "somefile" "some data"}
438 '')
439 ];
440 config = {
441 Cmd = [ "myscript" ];
442 # For some reason 'nix-store --verify' requires this environment variable
443 Env = [ "USER=root" ];
444 };
445 };
446
447 # 22. Ensure that setting created to now results in a date which
448 # isn't the epoch + 1 for layered images.
449 unstableDateLayered = pkgs.dockerTools.buildLayeredImage {
450 name = "unstable-date-layered";
451 tag = "latest";
452 contents = [ pkgs.coreutils ];
453 created = "now";
454 };
455
456 # 23. Ensure that layers are unpacked in the correct order before the
457 # runAsRoot script is executed.
458 layersUnpackOrder =
459 let
460 layerOnTopOf = parent: layerName:
461 pkgs.dockerTools.buildImage {
462 name = "layers-unpack-order-${layerName}";
463 tag = "latest";
464 fromImage = parent;
465 copyToRoot = pkgs.buildEnv {
466 name = "image-root";
467 pathsToLink = [ "/bin" ];
468 paths = [ pkgs.coreutils ];
469 };
470 runAsRoot = ''
471 #!${pkgs.runtimeShell}
472 echo -n "${layerName}" >> /layer-order
473 '';
474 };
475 # When executing the runAsRoot script when building layer C, if layer B is
476 # not unpacked on top of layer A, the contents of /layer-order will not be
477 # "ABC".
478 layerA = layerOnTopOf null "a";
479 layerB = layerOnTopOf layerA "b";
480 layerC = layerOnTopOf layerB "c";
481 in layerC;
482
483 bashUncompressed = pkgs.dockerTools.buildImage {
484 name = "bash-uncompressed";
485 tag = "latest";
486 compressor = "none";
487 # Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
488 copyToRoot = pkgs.bashInteractive;
489 };
490
491 bashZstdCompressed = pkgs.dockerTools.buildImage {
492 name = "bash-zstd";
493 tag = "latest";
494 compressor = "zstd";
495 # Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
496 copyToRoot = pkgs.bashInteractive;
497 };
498
499 # buildImage without explicit tag
500 bashNoTag = pkgs.dockerTools.buildImage {
501 name = "bash-no-tag";
502 # Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
503 copyToRoot = pkgs.bashInteractive;
504 };
505
506 # buildLayeredImage without explicit tag
507 bashNoTagLayered = pkgs.dockerTools.buildLayeredImage {
508 name = "bash-no-tag-layered";
509 contents = pkgs.bashInteractive;
510 };
511
512 # buildLayeredImage without compression
513 bashLayeredUncompressed = pkgs.dockerTools.buildLayeredImage {
514 name = "bash-layered-uncompressed";
515 tag = "latest";
516 compressor = "none";
517 contents = pkgs.bashInteractive;
518 };
519
520 # buildLayeredImage with zstd compression
521 bashLayeredZstdCompressed = pkgs.dockerTools.buildLayeredImage {
522 name = "bash-layered-zstd";
523 tag = "latest";
524 compressor = "zstd";
525 contents = pkgs.bashInteractive;
526 };
527
528 # streamLayeredImage without explicit tag
529 bashNoTagStreamLayered = pkgs.dockerTools.streamLayeredImage {
530 name = "bash-no-tag-stream-layered";
531 contents = pkgs.bashInteractive;
532 };
533
534 # buildLayeredImage with non-root user
535 bashLayeredWithUser =
536 let
537 nonRootShadowSetup = { user, uid, gid ? uid }: with pkgs; [
538 (
539 writeTextDir "etc/shadow" ''
540 root:!x:::::::
541 ${user}:!:::::::
542 ''
543 )
544 (
545 writeTextDir "etc/passwd" ''
546 root:x:0:0::/root:${runtimeShell}
547 ${user}:x:${toString uid}:${toString gid}::/home/${user}:
548 ''
549 )
550 (
551 writeTextDir "etc/group" ''
552 root:x:0:
553 ${user}:x:${toString gid}:
554 ''
555 )
556 (
557 writeTextDir "etc/gshadow" ''
558 root:x::
559 ${user}:x::
560 ''
561 )
562 ];
563 in
564 pkgs.dockerTools.buildLayeredImage {
565 name = "bash-layered-with-user";
566 tag = "latest";
567 contents = [ pkgs.bash pkgs.coreutils ] ++ nonRootShadowSetup { uid = 999; user = "somebody"; };
568 };
569
570 # basic example, with cross compilation
571 cross = let
572 # Cross compile for x86_64 if on aarch64
573 crossPkgs =
574 if pkgs.stdenv.hostPlatform.system == "aarch64-linux" then pkgsCross.gnu64
575 else pkgsCross.aarch64-multiplatform;
576 in crossPkgs.dockerTools.buildImage {
577 name = "hello-cross";
578 tag = "latest";
579 copyToRoot = pkgs.buildEnv {
580 name = "image-root";
581 pathsToLink = [ "/bin" ];
582 paths = [ crossPkgs.hello ];
583 };
584 };
585
586 # layered image where a store path is itself a symlink
587 layeredStoreSymlink =
588 let
589 target = pkgs.writeTextDir "dir/target" "Content doesn't matter.";
590 symlink = pkgs.runCommand "symlink" {} "ln -s ${target} $out";
591 in
592 pkgs.dockerTools.buildLayeredImage {
593 name = "layeredstoresymlink";
594 tag = "latest";
595 contents = [ pkgs.bash symlink ];
596 } // { passthru = { inherit symlink; }; };
597
598 # image with registry/ prefix
599 prefixedImage = pkgs.dockerTools.buildImage {
600 name = "registry-1.docker.io/image";
601 tag = "latest";
602 config.Cmd = [ "${pkgs.hello}/bin/hello" ];
603 };
604
605 # layered image with registry/ prefix
606 prefixedLayeredImage = pkgs.dockerTools.buildLayeredImage {
607 name = "registry-1.docker.io/layered-image";
608 tag = "latest";
609 config.Cmd = [ "${pkgs.hello}/bin/hello" ];
610 };
611
612 # layered image with files owned by a user other than root
613 layeredImageWithFakeRootCommands = pkgs.dockerTools.buildLayeredImage {
614 name = "layered-image-with-fake-root-commands";
615 tag = "latest";
616 contents = [
617 pkgs.pkgsStatic.busybox
618 ];
619 fakeRootCommands = ''
620 mkdir -p ./home/alice
621 chown 1000 ./home/alice
622 ln -s ${pkgs.hello.overrideAttrs (o: {
623 # A unique `hello` to make sure that it isn't included via another mechanism by accident.
624 configureFlags = o.configureFlags or [] ++ [ " --program-prefix=layeredImageWithFakeRootCommands-" ];
625 doCheck = false;
626 })} ./hello
627 '';
628 };
629
630 # tarball consisting of both bash and redis images
631 mergedBashAndRedis = pkgs.dockerTools.mergeImages [
632 bash
633 redis
634 ];
635
636 # tarball consisting of bash (without tag) and redis images
637 mergedBashNoTagAndRedis = pkgs.dockerTools.mergeImages [
638 bashNoTag
639 redis
640 ];
641
642 # tarball consisting of bash and layered image with different owner of the
643 # /home/alice directory
644 mergedBashFakeRoot = pkgs.dockerTools.mergeImages [
645 bash
646 layeredImageWithFakeRootCommands
647 ];
648
649 mergeVaryingCompressor = pkgs.dockerTools.mergeImages [
650 redis
651 bashUncompressed
652 bashZstdCompressed
653 ];
654
655 helloOnRoot = pkgs.dockerTools.streamLayeredImage {
656 name = "hello";
657 tag = "latest";
658 contents = [
659 (pkgs.buildEnv {
660 name = "hello-root";
661 paths = [ pkgs.hello ];
662 })
663 ];
664 config.Cmd = [ "hello" ];
665 };
666
667 helloOnRootNoStore = pkgs.dockerTools.streamLayeredImage {
668 name = "hello";
669 tag = "latest";
670 contents = [
671 (pkgs.buildEnv {
672 name = "hello-root";
673 paths = [ pkgs.hello ];
674 })
675 ];
676 config.Cmd = [ "hello" ];
677 includeStorePaths = false;
678 };
679
680 helloOnRootNoStoreFakechroot = pkgs.dockerTools.streamLayeredImage {
681 name = "hello";
682 tag = "latest";
683 contents = [
684 (pkgs.buildEnv {
685 name = "hello-root";
686 paths = [ pkgs.hello ];
687 })
688 ];
689 config.Cmd = [ "hello" ];
690 includeStorePaths = false;
691 enableFakechroot = true;
692 };
693
694 etc =
695 let
696 inherit (pkgs) lib;
697 nixosCore = (evalMinimalConfig ({ config, ... }: {
698 imports = [
699 pkgs.pkgsModule
700 ../../../nixos/modules/system/etc/etc.nix
701 ];
702 environment.etc."some-config-file" = {
703 text = ''
704 127.0.0.1 localhost
705 ::1 localhost
706 '';
707 # For executables:
708 # mode = "0755";
709 };
710 }));
711 in pkgs.dockerTools.streamLayeredImage {
712 name = "etc";
713 tag = "latest";
714 enableFakechroot = true;
715 fakeRootCommands = ''
716 mkdir -p /etc
717 ${nixosCore.config.system.build.etcActivationCommands}
718 '';
719 config.Cmd = pkgs.writeScript "etc-cmd" ''
720 #!${pkgs.busybox}/bin/sh
721 ${pkgs.busybox}/bin/cat /etc/some-config-file
722 '';
723 };
724
725 # Example export of the bash image
726 exportBash = pkgs.dockerTools.exportImage { fromImage = bash; };
727
728 imageViaFakeChroot = pkgs.dockerTools.streamLayeredImage {
729 name = "image-via-fake-chroot";
730 tag = "latest";
731 config.Cmd = [ "hello" ];
732 enableFakechroot = true;
733 # Crucially, instead of a relative path, this creates /bin, which is
734 # intercepted by fakechroot.
735 # This functionality is not available on darwin as of 2021.
736 fakeRootCommands = ''
737 mkdir /bin
738 ln -s ${pkgs.hello}/bin/hello /bin/hello
739 '';
740 };
741
742 build-image-with-path = buildImage {
743 name = "build-image-with-path";
744 tag = "latest";
745 # Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
746 copyToRoot = [ pkgs.bashInteractive ./test-dummy ];
747 };
748
749 layered-image-with-path = pkgs.dockerTools.streamLayeredImage {
750 name = "layered-image-with-path";
751 tag = "latest";
752 contents = [ pkgs.bashInteractive ./test-dummy ];
753 };
754
755 build-image-with-architecture = buildImage {
756 name = "build-image-with-architecture";
757 tag = "latest";
758 architecture = "arm64";
759 # Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
760 copyToRoot = [ pkgs.bashInteractive ./test-dummy ];
761 };
762
763 layered-image-with-architecture = pkgs.dockerTools.streamLayeredImage {
764 name = "layered-image-with-architecture";
765 tag = "latest";
766 architecture = "arm64";
767 contents = [ pkgs.bashInteractive ./test-dummy ];
768 };
769
770 # ensure that caCertificates builds
771 image-with-certs = buildImage {
772 name = "image-with-certs";
773 tag = "latest";
774
775 copyToRoot = pkgs.buildEnv {
776 name = "image-with-certs-root";
777 paths = [
778 pkgs.coreutils
779 pkgs.dockerTools.caCertificates
780 ];
781 };
782
783 config = {
784 };
785 };
786
787 nix-shell-basic = streamNixShellImage {
788 name = "nix-shell-basic";
789 tag = "latest";
790 drv = pkgs.hello;
791 };
792
793 nix-shell-hook = streamNixShellImage {
794 name = "nix-shell-hook";
795 tag = "latest";
796 drv = pkgs.mkShell {
797 shellHook = ''
798 echo "This is the shell hook!"
799 exit
800 '';
801 };
802 };
803
804 nix-shell-inputs = streamNixShellImage {
805 name = "nix-shell-inputs";
806 tag = "latest";
807 drv = pkgs.mkShell {
808 nativeBuildInputs = [
809 pkgs.hello
810 ];
811 };
812 command = ''
813 hello
814 '';
815 };
816
817 nix-shell-pass-as-file = streamNixShellImage {
818 name = "nix-shell-pass-as-file";
819 tag = "latest";
820 drv = pkgs.mkShell {
821 str = "this is a string";
822 passAsFile = [ "str" ];
823 };
824 command = ''
825 cat "$strPath"
826 '';
827 };
828
829 nix-shell-run = streamNixShellImage {
830 name = "nix-shell-run";
831 tag = "latest";
832 drv = pkgs.mkShell {};
833 run = ''
834 case "$-" in
835 *i*) echo This shell is interactive ;;
836 *) echo This shell is not interactive ;;
837 esac
838 '';
839 };
840
841 nix-shell-command = streamNixShellImage {
842 name = "nix-shell-command";
843 tag = "latest";
844 drv = pkgs.mkShell {};
845 command = ''
846 case "$-" in
847 *i*) echo This shell is interactive ;;
848 *) echo This shell is not interactive ;;
849 esac
850 '';
851 };
852
853 nix-shell-writable-home = streamNixShellImage {
854 name = "nix-shell-writable-home";
855 tag = "latest";
856 drv = pkgs.mkShell {};
857 run = ''
858 if [[ "$HOME" != "$(eval "echo ~$(whoami)")" ]]; then
859 echo "\$HOME ($HOME) is not the same as ~\$(whoami) ($(eval "echo ~$(whoami)"))"
860 exit 1
861 fi
862
863 if ! touch $HOME/test-file; then
864 echo "home directory is not writable"
865 exit 1
866 fi
867 echo "home directory is writable"
868 '';
869 };
870
871 nix-shell-nonexistent-home = streamNixShellImage {
872 name = "nix-shell-nonexistent-home";
873 tag = "latest";
874 drv = pkgs.mkShell {};
875 homeDirectory = "/homeless-shelter";
876 run = ''
877 if [[ "$HOME" != "$(eval "echo ~$(whoami)")" ]]; then
878 echo "\$HOME ($HOME) is not the same as ~\$(whoami) ($(eval "echo ~$(whoami)"))"
879 exit 1
880 fi
881
882 if -e $HOME; then
883 echo "home directory exists"
884 exit 1
885 fi
886 echo "home directory doesn't exist"
887 '';
888 };
889
890 nix-shell-build-derivation = streamNixShellImage {
891 name = "nix-shell-build-derivation";
892 tag = "latest";
893 drv = pkgs.hello;
894 run = ''
895 buildDerivation
896 $out/bin/hello
897 '';
898 };
899
900}