packages feed

arion-compose 0.1.2.0 → 0.1.3.0

raw patch · 14 files changed

+193/−70 lines, 14 filesdep ~basePVP ok

version bump matches the API change (PVP)

Dependency ranges changed: base

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,32 @@ # Revision history for Arion +## 0.1.3.0 -- 2020-05-03++### Changed++* `useHostStore` now uses an image derived from the `image.*` options. You may+  need to enable `enableRecommendedContents` because with this change, files+  like `/bin/sh` aren't added by default anymore.++* Drop obsolete NixOS 19.03, 19.09 and 20.03 from CI.++### Added++* NixOS-based containers can now run on Podman when it is configured to provide a docker socket. See the [installation docs](https://docs.hercules-ci.com/arion/#_nixos).++* Support `service.dns`, for overriding the DNS servers used by containers.++* Support `service.labels`, which is useful for autodiscovery among other things.++* Add a tested example for Traefik with label-based routing.++* Add a `flake.nix` and an experimental flake example++* Add a warning when systemd `DynamicUser` is used but not available to the+  container.++* CI with NixOS 21.05+ ## 0.1.2.0 -- 2020-03-05  * Support use of prebuilt `docker-compose.yaml`.@@ -26,3 +53,4 @@ ## 0.1.0.0 -- 2019-10-04  * First released version. Released on an unsuspecting world.+
arion-compose.cabal view
@@ -1,7 +1,7 @@ cabal-version:       2.4  name:                arion-compose-version: 0.1.2.0+version: 0.1.3.0 synopsis:            Run docker-compose with help from Nix/NixOS description:         Arion is a tool for building and running applications that consist of multiple docker containers using NixOS modules. It has special support for docker images that are built with Nix, for a smooth development experience and improved performance. homepage:            https://github.com/hercules-ci/arion#readme
src/haskell/lib/Arion/Images.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveAnyClass #-} {-# LANGUAGE OverloadedStrings #-}-module Arion.Images +module Arion.Images   ( loadImages   ) where @@ -22,24 +22,28 @@   loaded <- getDockerImages    let-    isNew i = (imageName i <> ":" <> imageTag i) `notElem` loaded+    isNew i =+      -- On docker, the image name is unmodified+      (imageName i <> ":" <> imageTag i) `notElem` loaded+      -- -- On podman, you automatically get a localhost prefix+        && ("localhost/" <> imageName i <> ":" <> imageTag i) `notElem` loaded    traverse_ loadImage . filter isNew $ requestedImages  loadImage :: Image -> IO ()-loadImage (Image { image = Just imgPath, imageName = name }) =+loadImage Image { image = Just imgPath, imageName = name } =   withFile (toS imgPath) ReadMode $ \fileHandle -> do   let procSpec = (Process.proc "docker" [ "load" ]) {           Process.std_in = Process.UseHandle fileHandle         }   Process.withCreateProcess procSpec $ \_in _out _err procHandle -> do-    e <- Process.waitForProcess procHandle +    e <- Process.waitForProcess procHandle     case e of       ExitSuccess -> pass       ExitFailure code ->         panic $ "docker load failed with exit code " <> show code <> " for image " <> name <> " from path " <> imgPath -loadImage (Image { imageExe = Just imgExe, imageName = name }) = do+loadImage Image { imageExe = Just imgExe, imageName = name } = do   let loadSpec = (Process.proc "docker" [ "load" ]) { Process.std_in = Process.CreatePipe }   Process.withCreateProcess loadSpec $ \(Just inHandle) _out _err loadProcHandle -> do     let streamSpec = Process.proc (toS imgExe) []@@ -57,11 +61,11 @@             _ -> pass           pass -loadImage (Image { imageName = name }) = do+loadImage Image { imageName = name } = do   panic $ "image " <> name <> " doesn't specify an image file or imageExe executable"   getDockerImages :: IO [TaggedImage] getDockerImages = do   let procSpec = Process.proc "docker" [ "images",  "--filter", "dangling=false", "--format", "{{.Repository}}:{{.Tag}}" ]-  (map toS . T.lines . toS) <$> Process.readCreateProcess procSpec ""+  map toS . T.lines . toS <$> Process.readCreateProcess procSpec ""
src/haskell/testdata/Arion/NixSpec/arion-compose.json view
@@ -2,14 +2,14 @@     "services": {         "webserver": {             "command": [-                "/nix/store/b9w61w4g8sqgrm3rid6ca22krslqghb3-nixos-system-unnamed-19.03.173100.e726e8291b2/init"+                "/usr/sbin/init"             ],             "environment": {                 "NIX_REMOTE": "",                 "PATH": "/usr/bin:/run/current-system/sw/bin/",                 "container": "docker"             },-            "image": "arion-base:<HASH>",+            "image": "webserver:<HASH>",             "ports": [                 "8000:80"             ],@@ -23,8 +23,7 @@             "tty": true,             "volumes": [                 "/sys/fs/cgroup:/sys/fs/cgroup:ro",-                "/nix/store:/nix/store:ro",-                "/nix/store/pssdmhzjnhflawv7rwk1yw39350iv40g-container-system-env:/run/system:ro"+                "/nix/store:/nix/store:ro"             ]         }     },@@ -32,8 +31,8 @@     "x-arion": {         "images": [             {-                "image": "<STOREPATH>",-                "imageName": "arion-base",+                "imageExe": "<STOREPATH>",+                "imageName": "webserver",                 "imageTag": "<HASH>"             }         ],
src/nix/modules.nix view
@@ -3,6 +3,5 @@     ./modules/composition/host-environment.nix     ./modules/composition/images.nix     ./modules/composition/service-info.nix-    ./modules/composition/arion-base-image.nix     ./modules/composition/composition.nix ]
− src/nix/modules/composition/arion-base-image.nix
@@ -1,41 +0,0 @@---# This module is subject to change.-# In particular, arion-base should use a generic non-service image building system--{ config, lib, pkgs, ... }: --let--  tag = lib.head (lib.strings.splitString "-" (baseNameOf builtImage.outPath));-  name = "arion-base";--  builtImage = pkgs.dockerTools.buildImage {-    inherit name;-    contents = pkgs.runCommand "minimal-contents" {} ''-        mkdir -p $out/bin $out/usr/bin-        ln -s /run/system/bin/sh $out/bin/sh-        ln -s /run/system/usr/bin/env $out/usr/bin/env-      '';-    config = {};-  };--in--{--  options = {-    arionBaseImage = lib.mkOption {-      type = lib.types.str;-      description = "Image to use when using useHostStore. Don't use this option yourself. It's going away.";-      internal = true;-    };-  };--  config = {-    arionBaseImage = "${name}:${tag}";-    build.imagesToLoad = lib.mkIf (lib.any (s: s.service.useHostStore) (lib.attrValues config.services)) [-      { image = builtImage; imageName = name; imageTag = tag; }-    ];  -  };-}
src/nix/modules/lib/assert.nix view
@@ -3,14 +3,15 @@ # based on nixpkgs/nixos/modules/system/activation/top-level.nix  let-  inherit (lib) filter concatStringsSep types mkOption;--  # lib.showWarnings since 19.09-  showWarnings = warnings: res: lib.fold (w: x: lib.warn w x) res warnings;-  warn = msg: builtins.trace "[1;31mwarning: ${msg}[0m";+  inherit (lib)+    concatStringsSep+    filter+    mkOption+    showWarnings+    types+    ;    # Handle assertions and warnings-   failedAssertions = map (x: x.message) (filter (x: !x.assertion) config.assertions);    assertWarn = if failedAssertions != []
src/nix/modules/service/all-modules.nix view
@@ -5,7 +5,9 @@   ./host-store.nix   ./context.nix   ./image.nix+  ./image-recommended.nix   ./nixos.nix   ./nixos-init.nix   ../lib/assert.nix+  ./check-sys_admin.nix ]
+ src/nix/modules/service/check-sys_admin.nix view
@@ -0,0 +1,30 @@+{ config, lib, name, ... }:+let+  inherit (lib)+    concatStringsSep+    optional+    ;++  dynamicUserServices = lib.attrNames (+    lib.filterAttrs+      (k: v:+        v.enable &&+        v.serviceConfig.DynamicUser or false)+      config.nixos.evaluatedConfig.systemd.services+    );++  +in+{+  config = {+    warnings = +      optional (config.nixos.useSystemd && !(config.service.capabilities.SYS_ADMIN or false) && dynamicUserServices != []) (+        ''In service ${name}, the following units require `SYS_ADMIN` capability+          because of DynamicUser.+          ${concatStringsSep "\n" (map (srv: "    - services.${name}.nixos.configuration.systemd.services.${srv}") dynamicUserServices)}+          You can avoid DynamicUser or use+              services.${name}.service.capabilities.SYS_ADMIN = true;+        ''+      );+  };+}
src/nix/modules/service/docker-compose-service.nix view
@@ -115,6 +115,23 @@         ${dockerComposeRef "devices"}       '';     };+    service.dns = mkOption {+      type = listOf str;+      default = [];+      example = [ "8.8.8.8" "8.8.4.4" ];+      description = dockerComposeRef "dns";+    };+    service.labels = mkOption {+      type = attrsOf str;+      default = {};+      example = {+        "com.example.foo" = "bar";+        "traefik.enable" = "true";+        "traefik.http.routers.my-service.rule" = "Host(`my-service.localhost`)";+        "traefik.http.routers.my-service.entrypoints" = "web";+      };+      description = dockerComposeRef "labels";+    };     service.links = mkOption {       type = listOf str;       default = [];@@ -247,6 +264,10 @@     inherit (config.service) extra_hosts;   } // lib.optionalAttrs (config.service.hostname != null) {     inherit (config.service) hostname;+  } // lib.optionalAttrs (config.service.dns != []) {+    inherit (config.service) dns;+  } // lib.optionalAttrs (config.service.labels != {}) {+    inherit (config.service) labels;   } // lib.optionalAttrs (config.service.links != []) {     inherit (config.service) links;   } // lib.optionalAttrs (config.service.ports != []) {
src/nix/modules/service/host-store.nix view
@@ -29,12 +29,10 @@     };   };   config = mkIf config.service.useHostStore {-    image.nixBuild = false; # no need to build and load-    service.image = config.composition.arionBaseImage;+    image.includeStorePaths = false;     service.environment.NIX_REMOTE = lib.optionalString config.service.useHostNixDaemon "daemon";     service.volumes = [       "${config.host.nixStorePrefix}/nix/store:/nix/store${lib.optionalString config.service.hostStoreAsReadOnly ":ro"}"-      "${config.host.nixStorePrefix}${pkgs.buildEnv { name = "container-system-env"; paths = [ pkgs.bashInteractive pkgs.coreutils ]; }}:/run/system${lib.optionalString config.service.hostStoreAsReadOnly ":ro"}"       ] ++ lib.optional config.service.useHostNixDaemon "/nix/var/nix/daemon-socket:/nix/var/nix/daemon-socket";     service.command = lib.mkDefault (map escape (config.image.rawConfig.Cmd or []));   };
+ src/nix/modules/service/image-recommended.nix view
@@ -0,0 +1,36 @@+{ config, lib, pkgs, ... }:+let+  inherit (lib)+    mkIf+    mkOption+    types+    ;+  inherit (types)+    bool+    ;++  recommendedContents = { runCommand, bash, coreutils }:+    runCommand "recommended-contents" {} ''+      mkdir -p $out/bin $out/usr/bin $out/var/empty+      ln -s ${bash}/bin/sh $out/bin/sh+      ln -s ${coreutils}/bin/env $out/usr/bin/env+    '';+in+{+  options = {+    image.enableRecommendedContents = mkOption {+      type = bool;+      default = false;+      description = ''+        Add the `/bin/sh` and `/usr/bin/env` symlinks and some lightweight+        files.+      '';+    };+  };++  config = {+    image.contents = mkIf config.image.enableRecommendedContents [+      (pkgs.callPackage recommendedContents {})+    ];+  };+}
src/nix/modules/service/image.nix view
@@ -1,6 +1,15 @@ { pkgs, lib, config, options, ... }: let-  inherit (lib) types mkOption;+  inherit (lib)+    functionArgs+    mkOption+    optionalAttrs+    types+    warn+    ;+  inherit (pkgs)+    dockerTools+    ;   inherit (types) attrsOf listOf nullOr package str unspecified bool;    # TODO: dummy-config is a useless layer. Nix 2.3 will let us inspect@@ -9,15 +18,37 @@     (pkgs.writeText "dummy-config.json" (builtins.toJSON config.image.rawConfig))   ]; +  includeStorePathsWarningAndDefault = lib.warn ''+    You're using a version of Nixpkgs that doesn't support the includeStorePaths+    parameter in dockerTools.streamLayeredImage. Without this, Arion's+    useHostStore does not achieve the intended speedup.+  '' {};+   buildOrStreamLayeredImage = args:-    if pkgs.dockerTools?streamLayeredImage-    then pkgs.dockerTools.streamLayeredImage args // { isExe = true; }-    else pkgs.dockerTools.buildLayeredImage args;+    let+      args_base = builtins.intersectAttrs+        {+          name = null; tag = null; contents = null; config = null;+          created = null; extraCommands = null; maxLayers = null;+        }+        args;+      acceptedArgs = functionArgs dockerTools.streamLayeredImage;+      args_no_store = lib.optionalAttrs (!(args.includeStorePaths or true)) (+        if acceptedArgs ? includeStorePaths+        then { inherit (args) includeStorePaths; }+        else includeStorePathsWarningAndDefault+      );+      args_streamLayered = args_base // args_no_store;+    in+      if dockerTools?streamLayeredImage+      then dockerTools.streamLayeredImage args_streamLayered // { isExe = true; }+      else dockerTools.buildLayeredImage args_base;    builtImage = buildOrStreamLayeredImage {     inherit (config.image)       name       contents+      includeStorePaths       ;     config = config.image.rawConfig;     maxLayers = 100;@@ -87,6 +118,15 @@       default = [];       description = ''          Top level paths in the container.+      '';+    };+    image.includeStorePaths = mkOption {+      type = bool;+      default = true;+      internal = true;+      description = ''+        Include all referenced store paths. You generally want this in your+        image, unless you load store paths via some other means, like useHostStore = true;       '';     };     image.rawConfig = mkOption {
src/nix/modules/service/nixos-init.nix view
@@ -24,7 +24,13 @@       ../nixos/default-shell.nix       (pkgs.path + "/nixos/modules/profiles/minimal.nix")     ];-    image.command = [ "${config.nixos.build.toplevel}/init" ];+    image.command = [ "/usr/sbin/init" ];+    image.contents = [+      (pkgs.runCommand "root-init" {} ''+        mkdir -p $out/usr/sbin+        ln -s ${config.nixos.build.toplevel}/init $out/usr/sbin/init+      '')+    ];     service.environment.container = "docker";     service.environment.PATH = "/usr/bin:/run/current-system/sw/bin/";     service.volumes = [