at 24.11-pre 900 lines 25 kB view raw
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}