Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 29 additions & 20 deletions cmd/cli/commands/install-runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,14 @@ func ensureStandaloneRunnerAvailable(ctx context.Context, printer standalone.Sta
return inspectStandaloneRunner(container), nil
}

// runnerOptions holds common configuration for install/start commands
// runnerOptions holds common configuration for install/start/reinstall commands
type runnerOptions struct {
port uint16
host string
gpuMode string
doNotTrack bool
pullImage bool
port uint16
host string
gpuMode string
doNotTrack bool
pullImage bool
pruneContainers bool
}

// runInstallOrStart is shared logic for install-runner and start-runner commands
Expand Down Expand Up @@ -216,16 +217,23 @@ func runInstallOrStart(cmd *cobra.Command, opts runnerOptions) error {
return fmt.Errorf("failed to create Docker client: %w", err)
}

// Check if an active model runner container already exists.
if ctrID, ctrName, _, err := standalone.FindControllerContainer(cmd.Context(), dockerClient); err != nil {
return err
} else if ctrID != "" {
if ctrName != "" {
cmd.Printf("Model Runner container %s (%s) is already running\n", ctrName, ctrID[:12])
} else {
cmd.Printf("Model Runner container %s is already running\n", ctrID[:12])
// If pruning containers (reinstall), remove any existing model runner containers.
if opts.pruneContainers {
if err := standalone.PruneControllerContainers(cmd.Context(), dockerClient, false, cmd); err != nil {
return fmt.Errorf("unable to remove model runner container(s): %w", err)
}
} else {
// Check if an active model runner container already exists (install only).
if ctrID, ctrName, _, err := standalone.FindControllerContainer(cmd.Context(), dockerClient); err != nil {
return err
} else if ctrID != "" {
if ctrName != "" {
cmd.Printf("Model Runner container %s (%s) is already running\n", ctrName, ctrID[:12])
} else {
cmd.Printf("Model Runner container %s is already running\n", ctrID[:12])
}
return nil
}
return nil
}

// Determine GPU support.
Expand Down Expand Up @@ -272,11 +280,12 @@ func newInstallRunner() *cobra.Command {
Short: "Install Docker Model Runner (Docker Engine only)",
RunE: func(cmd *cobra.Command, args []string) error {
return runInstallOrStart(cmd, runnerOptions{
port: port,
host: host,
gpuMode: gpuMode,
doNotTrack: doNotTrack,
pullImage: true,
port: port,
host: host,
gpuMode: gpuMode,
doNotTrack: doNotTrack,
pullImage: true,
pruneContainers: false,
})
},
ValidArgsFunction: completion.NoComplete,
Expand Down
34 changes: 34 additions & 0 deletions cmd/cli/commands/reinstall-runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package commands

import (
"github.com/docker/model-runner/cmd/cli/commands/completion"
"github.com/spf13/cobra"
)

func newReinstallRunner() *cobra.Command {
var port uint16
var host string
var gpuMode string
var doNotTrack bool
c := &cobra.Command{
Use: "reinstall-runner",
Short: "Reinstall Docker Model Runner (Docker Engine only)",
RunE: func(cmd *cobra.Command, args []string) error {
return runInstallOrStart(cmd, runnerOptions{
port: port,
host: host,
gpuMode: gpuMode,
doNotTrack: doNotTrack,
pullImage: true,
pruneContainers: true,
})
},
ValidArgsFunction: completion.NoComplete,
}
c.Flags().Uint16Var(&port, "port", 0,
"Docker container port for Docker Model Runner (default: 12434 for Docker Engine, 12435 for Cloud mode)")
c.Flags().StringVar(&host, "host", "127.0.0.1", "Host address to bind Docker Model Runner")
c.Flags().StringVar(&gpuMode, "gpu", "auto", "Specify GPU support (none|auto|cuda)")
c.Flags().BoolVar(&doNotTrack, "do-not-track", false, "Do not track models usage in Docker Model Runner")
return c
}
76 changes: 76 additions & 0 deletions cmd/cli/commands/reinstall-runner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package commands

import (
"testing"
)

func TestReinstallRunnerHostFlag(t *testing.T) {
testCases := []struct {
name string
value string
}{
{"localhost", "127.0.0.1"},
{"all_interfaces", "0.0.0.0"},
{"specific_IP", "192.168.1.100"},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
// Reset the command for each test
cmd := newReinstallRunner()
err := cmd.Flags().Set("host", tc.value)
if err != nil {
t.Errorf("Failed to set host flag to '%s': %v", tc.value, err)
}

// Verify the value was set
hostValue, err := cmd.Flags().GetString("host")
if err != nil {
t.Errorf("Failed to get host flag value: %v", err)
}
if hostValue != tc.value {
t.Errorf("Expected host value to be '%s', got '%s'", tc.value, hostValue)
}
})
}
}

func TestReinstallRunnerCommandFlags(t *testing.T) {
cmd := newReinstallRunner()

// Verify all expected flags exist
expectedFlags := []string{"port", "host", "gpu", "do-not-track"}
for _, flagName := range expectedFlags {
if cmd.Flags().Lookup(flagName) == nil {
t.Errorf("Expected flag '--%s' not found", flagName)
}
}
}

func TestReinstallRunnerCommandType(t *testing.T) {
cmd := newReinstallRunner()

// Verify command properties
if cmd.Use != "reinstall-runner" {
t.Errorf("Expected command Use to be 'reinstall-runner', got '%s'", cmd.Use)
}

if cmd.Short != "Reinstall Docker Model Runner (Docker Engine only)" {
t.Errorf("Unexpected command Short description: %s", cmd.Short)
}

// Verify RunE is set
if cmd.RunE == nil {
t.Error("Expected RunE to be set")
}
}

func TestReinstallRunnerValidArgsFunction(t *testing.T) {
cmd := newReinstallRunner()

// The reinstall-runner command should not accept any arguments
// So ValidArgsFunction should be set to handle no arguments
if cmd.ValidArgsFunction == nil {
t.Error("Expected ValidArgsFunction to be set")
}
}
1 change: 1 addition & 0 deletions cmd/cli/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ func NewRootCmd(cli *command.DockerCli) *cobra.Command {
newStartRunner(),
newStopRunner(),
newRestartRunner(),
newReinstallRunner(),
newConfigureCmd(),
newPSCmd(),
newDFCmd(),
Expand Down
2 changes: 2 additions & 0 deletions cmd/cli/docs/reference/docker_model.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ cname:
- docker model ps
- docker model pull
- docker model push
- docker model reinstall-runner
- docker model requests
- docker model restart-runner
- docker model rm
Expand All @@ -38,6 +39,7 @@ clink:
- docker_model_ps.yaml
- docker_model_pull.yaml
- docker_model_push.yaml
- docker_model_reinstall-runner.yaml
- docker_model_requests.yaml
- docker_model_restart-runner.yaml
- docker_model_rm.yaml
Expand Down
56 changes: 56 additions & 0 deletions cmd/cli/docs/reference/docker_model_reinstall-runner.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
command: docker model reinstall-runner
short: Reinstall Docker Model Runner (Docker Engine only)
long: |
This command removes the existing Docker Model Runner container and reinstalls it with the specified configuration. Models and images are preserved during reinstallation.
usage: docker model reinstall-runner
pname: docker model
plink: docker_model.yaml
options:
- option: do-not-track
value_type: bool
default_value: "false"
description: Do not track models usage in Docker Model Runner
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: gpu
value_type: string
default_value: auto
description: Specify GPU support (none|auto|cuda)
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: host
value_type: string
default_value: 127.0.0.1
description: Host address to bind Docker Model Runner
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
- option: port
value_type: uint16
default_value: "0"
description: |
Docker container port for Docker Model Runner (default: 12434 for Docker Engine, 12435 for Cloud mode)
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false

1 change: 1 addition & 0 deletions cmd/cli/docs/reference/model.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Docker Model Runner
| [`ps`](model_ps.md) | List running models |
| [`pull`](model_pull.md) | Pull a model from Docker Hub or HuggingFace to your local environment |
| [`push`](model_push.md) | Push a model to Docker Hub |
| [`reinstall-runner`](model_reinstall-runner.md) | Reinstall Docker Model Runner (Docker Engine only) |
| [`requests`](model_requests.md) | Fetch requests+responses from Docker Model Runner |
| [`restart-runner`](model_restart-runner.md) | Restart Docker Model Runner (Docker Engine only) |
| [`rm`](model_rm.md) | Remove local models downloaded from Docker Hub |
Expand Down
20 changes: 20 additions & 0 deletions cmd/cli/docs/reference/model_reinstall-runner.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# docker model reinstall-runner

<!---MARKER_GEN_START-->
Reinstall Docker Model Runner (Docker Engine only)

### Options

| Name | Type | Default | Description |
|:-----------------|:---------|:------------|:-------------------------------------------------------------------------------------------------------|
| `--do-not-track` | `bool` | | Do not track models usage in Docker Model Runner |
| `--gpu` | `string` | `auto` | Specify GPU support (none\|auto\|cuda) |
| `--host` | `string` | `127.0.0.1` | Host address to bind Docker Model Runner |
| `--port` | `uint16` | `0` | Docker container port for Docker Model Runner (default: 12434 for Docker Engine, 12435 for Cloud mode) |


<!---MARKER_GEN_END-->

## Description

This command removes the existing Docker Model Runner container and reinstalls it with the specified configuration. Models and images are preserved during reinstallation.
Loading