Docker context not available when executed in cron or systemd.timers

I have a docker container running. The container supports an export functionality which needs to be executed like

docker compose -f docker-compose.yml exec -T <container> export-exe 

This works as long as the command is given in the shell. But as soon as it is executed in cron or systemsd.timer (tried both), the is not found.

If I execute instead a “docker ps”, the output shows an empty list (heading is available, but no single container). But there are currently more than 10 containers running.

What did I miss?

This is an example configuration:

systemd.timers."hello-world" = {
  wantedBy = [ "timers.target" ];
    timerConfig = {
      OnBootSec = "1m";
      OnUnitActiveSec = "1m";
      Unit = "hello-world.service";
    };
};

systemd.services."hello-world" = {
  script = ''
    set -eu
    ${pkgs.coreutils}/bin/echo "Hello World" > /tmp/timer.log
    /run/current-system/sw/bin/bash -l -c 'docker ps' >> /tmp/timer.log
  '';
  serviceConfig = {
    Type = "oneshot";
    User = "root";
  };
};

How does your docker setup look like? (virtualization.docker.*)

Here it is (sorry I missed that):

  # List packages installed in system profile. To search, run:
  environment.systemPackages = with pkgs; [
    docker-compose
  ];

  # enable docker
  virtualisation.docker.enable = true;
  # use docker without Root access (Rootless docker)
  virtualisation.docker.rootless = {
    enable = true;
    setSocketVariable = true;
  };

After script = ... I think you also need

path = [pkgs.docker pkgs.coreutils];

Thank you for the idea. So I changed it to this:

systemd.services."hello-world" = {
  script = ''
    set -eu
    ${pkgs.coreutils}/bin/echo "Hello World" > /tmp/timer.log
    /run/current-system/sw/bin/bash -l -c 'docker ps' >> /tmp/timer.log
  '';
  path = [ pkgs.docker pkgs.coreutils ];
  serviceConfig = {
    Type = "oneshot";
    User = "root";
  };
};

Unfortunately I still get the same output (just the header line, no listed containers):

Hello World
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES

Looks like you have your containers set up for rootless access, but your service is calling docker as root. You have to run the service as the same user as is running the containers.

Sounds logical.

I tried several combinations:

  • docker not rootless, timer as above
  • docker rootless, timer with unitConfig.ConditionUser = my_user
  • docker rootless, executed service with serviceConfig.User = my_user

Checked which user is taken for task dockerd, the user of the created file, all these changed with the changes above, but still the command docker ps shows an empty list when executed by the timer.