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