Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
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 (finalAttrs: prevAttrs: {
623 # A unique `hello` to make sure that it isn't included via another mechanism by accident.
624 configureFlags = prevAttrs.configureFlags or [] ++ [ " --program-prefix=layeredImageWithFakeRootCommands-" ];
625 doCheck = false;
626 versionCheckProgram = "${builtins.placeholder "out"}/bin/${finalAttrs.meta.mainProgram}";
627 meta = prevAttrs.meta // {
628 mainProgram = "layeredImageWithFakeRootCommands-hello";
629 };
630 })} ./hello
631 '';
632 };
633
634 # tarball consisting of both bash and redis images
635 mergedBashAndRedis = pkgs.dockerTools.mergeImages [
636 bash
637 redis
638 ];
639
640 # tarball consisting of bash (without tag) and redis images
641 mergedBashNoTagAndRedis = pkgs.dockerTools.mergeImages [
642 bashNoTag
643 redis
644 ];
645
646 # tarball consisting of bash and layered image with different owner of the
647 # /home/alice directory
648 mergedBashFakeRoot = pkgs.dockerTools.mergeImages [
649 bash
650 layeredImageWithFakeRootCommands
651 ];
652
653 mergeVaryingCompressor = pkgs.dockerTools.mergeImages [
654 redis
655 bashUncompressed
656 bashZstdCompressed
657 ];
658
659 helloOnRoot = pkgs.dockerTools.streamLayeredImage {
660 name = "hello";
661 tag = "latest";
662 contents = [
663 (pkgs.buildEnv {
664 name = "hello-root";
665 paths = [ pkgs.hello ];
666 })
667 ];
668 config.Cmd = [ "hello" ];
669 };
670
671 helloOnRootNoStore = pkgs.dockerTools.streamLayeredImage {
672 name = "hello";
673 tag = "latest";
674 contents = [
675 (pkgs.buildEnv {
676 name = "hello-root";
677 paths = [ pkgs.hello ];
678 })
679 ];
680 config.Cmd = [ "hello" ];
681 includeStorePaths = false;
682 };
683
684 helloOnRootNoStoreFakechroot = pkgs.dockerTools.streamLayeredImage {
685 name = "hello";
686 tag = "latest";
687 contents = [
688 (pkgs.buildEnv {
689 name = "hello-root";
690 paths = [ pkgs.hello ];
691 })
692 ];
693 config.Cmd = [ "hello" ];
694 includeStorePaths = false;
695 enableFakechroot = true;
696 };
697
698 etc =
699 let
700 inherit (pkgs) lib;
701 nixosCore = (evalMinimalConfig ({ config, ... }: {
702 imports = [
703 pkgs.pkgsModule
704 ../../../nixos/modules/system/etc/etc.nix
705 ];
706 environment.etc."some-config-file" = {
707 text = ''
708 127.0.0.1 localhost
709 ::1 localhost
710 '';
711 # For executables:
712 # mode = "0755";
713 };
714 }));
715 in pkgs.dockerTools.streamLayeredImage {
716 name = "etc";
717 tag = "latest";
718 enableFakechroot = true;
719 fakeRootCommands = ''
720 mkdir -p /etc
721 ${nixosCore.config.system.build.etcActivationCommands}
722 '';
723 config.Cmd = pkgs.writeScript "etc-cmd" ''
724 #!${pkgs.busybox}/bin/sh
725 ${pkgs.busybox}/bin/cat /etc/some-config-file
726 '';
727 };
728
729 # Example export of the bash image
730 exportBash = pkgs.dockerTools.exportImage { fromImage = bash; };
731
732 imageViaFakeChroot = pkgs.dockerTools.streamLayeredImage {
733 name = "image-via-fake-chroot";
734 tag = "latest";
735 config.Cmd = [ "hello" ];
736 enableFakechroot = true;
737 # Crucially, instead of a relative path, this creates /bin, which is
738 # intercepted by fakechroot.
739 # This functionality is not available on darwin as of 2021.
740 fakeRootCommands = ''
741 mkdir /bin
742 ln -s ${pkgs.hello}/bin/hello /bin/hello
743 '';
744 };
745
746 build-image-with-path = buildImage {
747 name = "build-image-with-path";
748 tag = "latest";
749 # Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
750 copyToRoot = [ pkgs.bashInteractive ./test-dummy ];
751 };
752
753 layered-image-with-path = pkgs.dockerTools.streamLayeredImage {
754 name = "layered-image-with-path";
755 tag = "latest";
756 contents = [ pkgs.bashInteractive ./test-dummy ];
757 };
758
759 build-image-with-architecture = buildImage {
760 name = "build-image-with-architecture";
761 tag = "latest";
762 architecture = "arm64";
763 # Not recommended. Use `buildEnv` between copy and packages to avoid file duplication.
764 copyToRoot = [ pkgs.bashInteractive ./test-dummy ];
765 };
766
767 layered-image-with-architecture = pkgs.dockerTools.streamLayeredImage {
768 name = "layered-image-with-architecture";
769 tag = "latest";
770 architecture = "arm64";
771 contents = [ pkgs.bashInteractive ./test-dummy ];
772 };
773
774 # ensure that caCertificates builds
775 image-with-certs = buildImage {
776 name = "image-with-certs";
777 tag = "latest";
778
779 copyToRoot = pkgs.buildEnv {
780 name = "image-with-certs-root";
781 paths = [
782 pkgs.coreutils
783 pkgs.dockerTools.caCertificates
784 ];
785 };
786
787 config = {
788 };
789 };
790
791 nix-shell-basic = streamNixShellImage {
792 name = "nix-shell-basic";
793 tag = "latest";
794 drv = pkgs.hello;
795 };
796
797 nix-shell-hook = streamNixShellImage {
798 name = "nix-shell-hook";
799 tag = "latest";
800 drv = pkgs.mkShell {
801 shellHook = ''
802 echo "This is the shell hook!"
803 exit
804 '';
805 };
806 };
807
808 nix-shell-inputs = streamNixShellImage {
809 name = "nix-shell-inputs";
810 tag = "latest";
811 drv = pkgs.mkShell {
812 nativeBuildInputs = [
813 pkgs.hello
814 ];
815 };
816 command = ''
817 hello
818 '';
819 };
820
821 nix-shell-pass-as-file = streamNixShellImage {
822 name = "nix-shell-pass-as-file";
823 tag = "latest";
824 drv = pkgs.mkShell {
825 str = "this is a string";
826 passAsFile = [ "str" ];
827 };
828 command = ''
829 cat "$strPath"
830 '';
831 };
832
833 nix-shell-run = streamNixShellImage {
834 name = "nix-shell-run";
835 tag = "latest";
836 drv = pkgs.mkShell {};
837 run = ''
838 case "$-" in
839 *i*) echo This shell is interactive ;;
840 *) echo This shell is not interactive ;;
841 esac
842 '';
843 };
844
845 nix-shell-command = streamNixShellImage {
846 name = "nix-shell-command";
847 tag = "latest";
848 drv = pkgs.mkShell {};
849 command = ''
850 case "$-" in
851 *i*) echo This shell is interactive ;;
852 *) echo This shell is not interactive ;;
853 esac
854 '';
855 };
856
857 nix-shell-writable-home = streamNixShellImage {
858 name = "nix-shell-writable-home";
859 tag = "latest";
860 drv = pkgs.mkShell {};
861 run = ''
862 if [[ "$HOME" != "$(eval "echo ~$(whoami)")" ]]; then
863 echo "\$HOME ($HOME) is not the same as ~\$(whoami) ($(eval "echo ~$(whoami)"))"
864 exit 1
865 fi
866
867 if ! touch $HOME/test-file; then
868 echo "home directory is not writable"
869 exit 1
870 fi
871 echo "home directory is writable"
872 '';
873 };
874
875 nix-shell-nonexistent-home = streamNixShellImage {
876 name = "nix-shell-nonexistent-home";
877 tag = "latest";
878 drv = pkgs.mkShell {};
879 homeDirectory = "/homeless-shelter";
880 run = ''
881 if [[ "$HOME" != "$(eval "echo ~$(whoami)")" ]]; then
882 echo "\$HOME ($HOME) is not the same as ~\$(whoami) ($(eval "echo ~$(whoami)"))"
883 exit 1
884 fi
885
886 if -e $HOME; then
887 echo "home directory exists"
888 exit 1
889 fi
890 echo "home directory doesn't exist"
891 '';
892 };
893
894 nix-shell-build-derivation = streamNixShellImage {
895 name = "nix-shell-build-derivation";
896 tag = "latest";
897 drv = pkgs.hello;
898 run = ''
899 buildDerivation
900 $out/bin/hello
901 '';
902 };
903
904 nix-layered = pkgs.dockerTools.streamLayeredImage {
905 name = "nix-layered";
906 tag = "latest";
907 contents = [ pkgs.nix pkgs.bash ];
908 includeNixDB = true;
909 config = {
910 Env = [
911 "NIX_PAGER=cat"
912 ];
913 };
914 };
915
916}