From 0b4e9e092dc092c75cd52a1de1f141580308e88c Mon Sep 17 00:00:00 2001 From: Thierry Pouplier Date: Thu, 1 Jan 2026 02:25:05 -0500 Subject: [PATCH] chore: add docker stack integration with improved service management --- modules/nixos/services/docker_manager.nix | 44 +++++++++++++++-------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/modules/nixos/services/docker_manager.nix b/modules/nixos/services/docker_manager.nix index d8fa94e..3e36384 100644 --- a/modules/nixos/services/docker_manager.nix +++ b/modules/nixos/services/docker_manager.nix @@ -1,36 +1,50 @@ -{ config, lib, pkgs, ... }: +{ config, pkgs, lib, ... }: with lib; { - options.services.myDockerStacks = mkOption { + options.services.dockerStacks = mkOption { type = types.attrsOf (types.submodule { options = { - path = mkOption { type = types.path; }; - ports = mkOption { type = types.listOf types.int; default = []; }; + path = mkOption { type = types.str; }; + envFile = mkOption { type = types.nullOr types.path; default = null; }; + ports = mkOption { type = types.listOf types.int; default = [ ]; }; }; }); default = {}; - description = "Attribute set of docker-compose stacks to run."; }; config = { - # Generate the systemd services based on the options provided above + virtualisation.docker.enable = true; + virtualisation.docker.daemon.settings.dns = [ "1.1.1.1" "8.8.8.8" ]; + + networking.firewall.allowedTCPPorts = flatten (mapAttrsToList (name: value: value.ports) config.services.dockerStacks); + systemd.services = mapAttrs' (name: value: nameValuePair "${name}_stack" { - description = "${name} via Docker Compose"; - after = [ "network-online.target" "docker.service" ]; - wants = [ "network-online.target" "docker.service" ]; + description = "Docker Compose stack: ${name}"; + + # Added 'docker.socket' to both after and wants to ensure the API is reachable + after = [ "network.target" "docker.service" "docker.socket" "agenix.service" ]; + wants = [ "docker.socket" "agenix.service" ]; + requires = [ "docker.service" ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; WorkingDirectory = value.path; - ExecStartPre = "${pkgs.docker-compose}/bin/docker-compose down"; - ExecStart = "${pkgs.docker-compose}/bin/docker-compose up -d"; + User = "root"; + + # This line forces the service to wait until the docker socket is actually responsive + ExecStartPre = "${pkgs.bash}/bin/bash -c 'while [ ! -S /var/run/docker.sock ]; do sleep 1; done'"; + + ExecStart = "${pkgs.docker-compose}/bin/docker-compose up -d --remove-orphans"; ExecStop = "${pkgs.docker-compose}/bin/docker-compose down"; RemainAfterExit = true; + + # Ensure the environment file is passed correctly + EnvironmentFile = mkIf (value.envFile != null) [ value.envFile ]; }; - }) config.services.myDockerStacks; - - # Automatically open firewall ports - networking.firewall.allowedTCPPorts = flatten (mapAttrsToList (n: v: v.ports) config.services.myDockerStacks); + }) config.services.dockerStacks; }; }