Skip to content

Commit

Permalink
Compose Deploy support for Docker CDI (#36)
Browse files Browse the repository at this point in the history
* feat: Compose deploy support for CDI devices

* add GPU section to README
  • Loading branch information
aksiksi authored Aug 31, 2024
1 parent 3f3f499 commit 9145716
Show file tree
Hide file tree
Showing 25 changed files with 221 additions and 39 deletions.
45 changes: 45 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,51 @@ You can do one of the following:
sudo systemctl start podman-compose-myservice-root.target
```

### Nvidia GPU Support

1. Enable CDI support in your NixOS config:

```nix
{
hardware.nvidia-container-toolkit.enable = true;
}
```

**Docker only:**

Make sure you are running Docker 25+:

```nix
{
virtualisation.docker.package = pkgs.docker_25;
}
```

2. Pass in CDI devices via either `devices` **or** `deploy` (both map to the same thing under the hood):

```yaml
services:
myservice:
# ... other fields

# Option 1
devices:
- nvidia.com/gpu=all
# Option 2
deploy:
resources:
reservations:
devices:
# Driver must be set to "cdi" - all others are ignored.
- driver: cdi
device_ids:
- nvidia.com/gpu=all

# Required for Podman.
security_opt:
- label=disable
```
### NixOS Version Support Policy
I always aim to support the **latest** stable version of NixOS (24.05 at the
Expand Down
10 changes: 10 additions & 0 deletions compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,16 @@ func (g *Generator) buildNixContainer(service types.ServiceConfig, networkMap ma
if reservations.NanoCPUs != 0 {
c.ExtraOptions = append(c.ExtraOptions, "--cpus="+strconv.FormatFloat(float64(reservations.NanoCPUs), 'f', -1, 32))
}

// CDI GPU support.
for _, device := range reservations.Devices {
if strings.ToLower(device.Driver) != "cdi" {
continue
}
for _, deviceID := range device.IDs {
c.ExtraOptions = append(c.ExtraOptions, "--device="+deviceID)
}
}
}
}

Expand Down
9 changes: 9 additions & 0 deletions nix_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -274,3 +274,12 @@ func TestEmptyEnv(t *testing.T) {
}
runSubtestsWithGenerator(t, g)
}

func TestDeployDevices(t *testing.T) {
composePath, _ := getPaths(t, false)
g := &Generator{
Inputs: []string{composePath},
Project: NewProject("test"),
}
runSubtestsWithGenerator(t, g)
}
2 changes: 0 additions & 2 deletions testdata/TestBasic.docker.nix
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."docker-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestBasic.podman.nix
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."podman-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestBasicAutoFormat.docker.nix
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."docker-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestBasicAutoFormat.podman.nix
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."podman-traefik" = {
Expand Down
19 changes: 19 additions & 0 deletions testdata/TestDeployDevices.compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
services:
test:
image: nginx:latest
security_opt:
- label=disable
devices:
- nvidia.com/gpu=abc
deploy:
resources:
reservations:
devices:
- driver: cdi
device_ids:
- nvidia.com/gpu=all
- driver: ignore-me
device_ids:
- unknown
restart: unless-stopped

68 changes: 68 additions & 0 deletions testdata/TestDeployDevices.docker.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
{ pkgs, lib, ... }:

{
# Runtime
virtualisation.docker = {
enable = true;
autoPrune.enable = true;
};
virtualisation.oci-containers.backend = "docker";

# Containers
virtualisation.oci-containers.containers."test-test" = {
image = "nginx:latest";
log-driver = "journald";
autoStart = false;
extraOptions = [
"--device=nvidia.com/gpu=abc"
"--device=nvidia.com/gpu=all"
"--network-alias=test"
"--network=test_default"
"--security-opt=label=disable"
];
};
systemd.services."docker-test-test" = {
serviceConfig = {
Restart = lib.mkOverride 500 "always";
RestartMaxDelaySec = lib.mkOverride 500 "1m";
RestartSec = lib.mkOverride 500 "100ms";
RestartSteps = lib.mkOverride 500 9;
};
after = [
"docker-network-test_default.service"
];
requires = [
"docker-network-test_default.service"
];
partOf = [
"docker-compose-test-root.target"
];
wantedBy = [
"docker-compose-test-root.target"
];
};

# Networks
systemd.services."docker-network-test_default" = {
path = [ pkgs.docker ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStop = "docker network rm -f test_default";
};
script = ''
docker network inspect test_default || docker network create test_default
'';
partOf = [ "docker-compose-test-root.target" ];
wantedBy = [ "docker-compose-test-root.target" ];
};

# Root service
# When started, this will automatically create all resources and start
# the containers. When stopped, this will teardown all resources.
systemd.targets."docker-compose-test-root" = {
unitConfig = {
Description = "Root target generated by compose2nix.";
};
};
}
70 changes: 70 additions & 0 deletions testdata/TestDeployDevices.podman.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{ pkgs, lib, ... }:

{
# Runtime
virtualisation.podman = {
enable = true;
autoPrune.enable = true;
dockerCompat = true;
defaultNetwork.settings = {
# Required for container networking to be able to use names.
dns_enabled = true;
};
};
virtualisation.oci-containers.backend = "podman";

# Containers
virtualisation.oci-containers.containers."test-test" = {
image = "nginx:latest";
log-driver = "journald";
autoStart = false;
extraOptions = [
"--device=nvidia.com/gpu=abc"
"--device=nvidia.com/gpu=all"
"--network-alias=test"
"--network=test_default"
"--security-opt=label=disable"
];
};
systemd.services."podman-test-test" = {
serviceConfig = {
Restart = lib.mkOverride 500 "always";
};
after = [
"podman-network-test_default.service"
];
requires = [
"podman-network-test_default.service"
];
partOf = [
"podman-compose-test-root.target"
];
wantedBy = [
"podman-compose-test-root.target"
];
};

# Networks
systemd.services."podman-network-test_default" = {
path = [ pkgs.podman ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStop = "podman network rm -f test_default";
};
script = ''
podman network inspect test_default || podman network create test_default
'';
partOf = [ "podman-compose-test-root.target" ];
wantedBy = [ "podman-compose-test-root.target" ];
};

# Root service
# When started, this will automatically create all resources and start
# the containers. When stopped, this will teardown all resources.
systemd.targets."podman-compose-test-root" = {
unitConfig = {
Description = "Root target generated by compose2nix.";
};
};
}
2 changes: 0 additions & 2 deletions testdata/TestEnvFilesOnly.docker.nix
Original file line number Diff line number Diff line change
Expand Up @@ -265,8 +265,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."docker-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestEnvFilesOnly.podman.nix
Original file line number Diff line number Diff line change
Expand Up @@ -263,8 +263,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."podman-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestNoWriteNixSetup.docker.nix
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."docker-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestNoWriteNixSetup.podman.nix
Original file line number Diff line number Diff line change
Expand Up @@ -278,8 +278,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."podman-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestOverrideSystemdStopTimeout.docker.nix
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."docker-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestOverrideSystemdStopTimeout.podman.nix
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."podman-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestProject.docker.nix
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."docker-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestProject.podman.nix
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."podman-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestRemoveVolumes.docker.nix
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."docker-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestRemoveVolumes.podman.nix
Original file line number Diff line number Diff line change
Expand Up @@ -289,8 +289,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."podman-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestSystemdMount.docker.nix
Original file line number Diff line number Diff line change
Expand Up @@ -305,8 +305,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."docker-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestSystemdMount.podman.nix
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."podman-traefik" = {
Expand Down
2 changes: 0 additions & 2 deletions testdata/TestUpheldBy.docker.nix
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,6 @@
"--log-opt=max-file=3"
"--log-opt=max-size=10m"
"--network=container:sabnzbd"
"--runtime=nvidia"
"--security-opt=label=disable"
];
};
systemd.services."docker-traefik" = {
Expand Down
Loading

0 comments on commit 9145716

Please sign in to comment.