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
1 change: 0 additions & 1 deletion .github/workflows/cli-validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,5 +62,4 @@ jobs:
uses: docker/bake-action@v6
with:
files: ./cmd/cli/docker-bake.hcl
workdir: ./cmd/cli
targets: ${{ matrix.target }}
2 changes: 1 addition & 1 deletion cmd/cli/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ RUN --mount=target=/context \
git add -A
rm -rf cmd/cli/docs/reference/*
cp -rf /out/* ./cmd/cli/docs/reference/
if [ -n "$(git status --porcelain -- docs/reference)" ]; then
if [ -n "$(git status --porcelain -- cmd/cli/docs/reference)" ]; then
echo >&2 'ERROR: Docs result differs. Please update with "make docs"'
git status --porcelain -- cmd/cli/docs/reference
exit 1
Expand Down
5 changes: 2 additions & 3 deletions cmd/cli/commands/configure.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ func newConfigureCmd() *cobra.Command {
var opts scheduling.ConfigureRequest

c := &cobra.Command{
Use: "configure [--context-size=<n>] MODEL [-- <runtime-flags...>]",
Short: "Configure runtime options for a model",
Hidden: true,
Use: "configure [--context-size=<n>] MODEL [-- <runtime-flags...>]",
Short: "Configure runtime options for a model",
Args: func(cmd *cobra.Command, args []string) error {
argsBeforeDash := cmd.ArgsLenAtDash()
if argsBeforeDash == -1 {
Expand Down
9 changes: 7 additions & 2 deletions cmd/cli/commands/install-runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,15 @@ func ensureStandaloneRunnerAvailable(ctx context.Context, printer standalone.Sta

// Create the model runner container.
port := uint16(standalone.DefaultControllerPortMoby)
// For auto-installation, always bind to localhost for security.
// Users can run install-runner explicitly with --host to change this.
host := "127.0.0.1"
environment := "moby"
if engineKind == types.ModelRunnerEngineKindCloud {
port = standalone.DefaultControllerPortCloud
environment = "cloud"
}
if err := standalone.CreateControllerContainer(ctx, dockerClient, port, environment, false, gpu, modelStorageVolume, printer, engineKind); err != nil {
if err := standalone.CreateControllerContainer(ctx, dockerClient, port, host, environment, false, gpu, modelStorageVolume, printer, engineKind); err != nil {
return nil, fmt.Errorf("unable to initialize standalone model runner container: %w", err)
}

Expand All @@ -159,6 +162,7 @@ func ensureStandaloneRunnerAvailable(ctx context.Context, printer standalone.Sta

func newInstallRunner() *cobra.Command {
var port uint16
var host string
var gpuMode string
var doNotTrack bool
c := &cobra.Command{
Expand Down Expand Up @@ -245,7 +249,7 @@ func newInstallRunner() *cobra.Command {
return fmt.Errorf("unable to initialize standalone model storage: %w", err)
}
// Create the model runner container.
if err := standalone.CreateControllerContainer(cmd.Context(), dockerClient, port, environment, doNotTrack, gpu, modelStorageVolume, cmd, engineKind); err != nil {
if err := standalone.CreateControllerContainer(cmd.Context(), dockerClient, port, host, environment, doNotTrack, gpu, modelStorageVolume, cmd, engineKind); err != nil {
return fmt.Errorf("unable to initialize standalone model runner container: %w", err)
}

Expand All @@ -256,6 +260,7 @@ func newInstallRunner() *cobra.Command {
}
c.Flags().Uint16Var(&port, "port", 0,
"Docker container port for Docker Model Runner (default: 12434 for Docker CE, 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
Expand Down
96 changes: 96 additions & 0 deletions cmd/cli/commands/install-runner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package commands

import (
"testing"
)

func TestInstallRunnerHostFlag(t *testing.T) {
// Create the install-runner command
cmd := newInstallRunner()

// Verify the --host flag exists
hostFlag := cmd.Flags().Lookup("host")
if hostFlag == nil {
t.Fatal("--host flag not found")
}

// Verify the default value
if hostFlag.DefValue != "127.0.0.1" {
t.Errorf("Expected default host value to be '127.0.0.1', got '%s'", hostFlag.DefValue)
}

// Verify the flag type
if hostFlag.Value.Type() != "string" {
t.Errorf("Expected host flag type to be 'string', got '%s'", hostFlag.Value.Type())
}

// Test setting the flag value
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 := newInstallRunner()
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 TestInstallRunnerCommandFlags(t *testing.T) {
cmd := newInstallRunner()

// 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 TestInstallRunnerCommandType(t *testing.T) {
cmd := newInstallRunner()

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

if cmd.Short != "Install 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 TestInstallRunnerValidArgsFunction(t *testing.T) {
cmd := newInstallRunner()

// The install-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")
}
}
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 @@ -6,6 +6,7 @@ long: |-
pname: docker
plink: docker.yaml
cname:
- docker model configure
- docker model df
- docker model inspect
- docker model install-runner
Expand All @@ -24,6 +25,7 @@ cname:
- docker model unload
- docker model version
clink:
- docker_model_configure.yaml
- docker_model_df.yaml
- docker_model_inspect.yaml
- docker_model_install-runner.yaml
Expand Down
2 changes: 1 addition & 1 deletion cmd/cli/docs/reference/docker_model_configure.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ options:
kubernetes: false
swarm: false
deprecated: false
hidden: true
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
Expand Down
10 changes: 10 additions & 0 deletions cmd/cli/docs/reference/docker_model_install-runner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ options:
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"
Expand Down
20 changes: 15 additions & 5 deletions cmd/cli/docs/reference/docker_model_package.yaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
command: docker model package
short: |
Package a GGUF file into a Docker model OCI artifact, with optional licenses.
Package a GGUF file or Safetensors directory into a Docker model OCI artifact.
long: |-
Package a GGUF file into a Docker model OCI artifact, with optional licenses. The package is sent to the model-runner, unless --push is specified.
When packaging a sharded model --gguf should point to the first shard. All shard files should be siblings and should include the index in the file name (e.g. model-00001-of-00015.gguf).
usage: docker model package --gguf <path> [--license <path>...] [--context-size <tokens>] [--push] MODEL
Package a GGUF file or Safetensors directory into a Docker model OCI artifact, with optional licenses. The package is sent to the model-runner, unless --push is specified.
When packaging a sharded GGUF model, --gguf should point to the first shard. All shard files should be siblings and should include the index in the file name (e.g. model-00001-of-00015.gguf).
When packaging a Safetensors model, --safetensors-dir should point to a directory containing .safetensors files and config files (*.json, merges.txt). All files will be auto-discovered and config files will be packaged into a tar archive.
usage: docker model package (--gguf <path> | --safetensors-dir <path>) [--license <path>...] [--context-size <tokens>] [--push] MODEL
pname: docker model
plink: docker_model.yaml
options:
Expand All @@ -29,7 +30,7 @@ options:
swarm: false
- option: gguf
value_type: string
description: absolute path to gguf file (required)
description: absolute path to gguf file
deprecated: false
hidden: false
experimental: false
Expand Down Expand Up @@ -58,6 +59,15 @@ options:
experimentalcli: false
kubernetes: false
swarm: false
- option: safetensors-dir
value_type: string
description: absolute path to directory containing safetensors files and config
deprecated: false
hidden: false
experimental: false
experimentalcli: false
kubernetes: false
swarm: false
deprecated: false
hidden: false
experimental: false
Expand Down
39 changes: 20 additions & 19 deletions cmd/cli/docs/reference/model.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,26 @@ Docker Model Runner

### Subcommands

| Name | Description |
|:------------------------------------------------|:------------------------------------------------------------------------------|
| [`df`](model_df.md) | Show Docker Model Runner disk usage |
| [`inspect`](model_inspect.md) | Display detailed information on one model |
| [`install-runner`](model_install-runner.md) | Install Docker Model Runner (Docker Engine only) |
| [`list`](model_list.md) | List the models pulled to your local environment |
| [`logs`](model_logs.md) | Fetch the Docker Model Runner logs |
| [`package`](model_package.md) | Package a GGUF file into a Docker model OCI artifact, with optional licenses. |
| [`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 |
| [`requests`](model_requests.md) | Fetch requests+responses from Docker Model Runner |
| [`rm`](model_rm.md) | Remove local models downloaded from Docker Hub |
| [`run`](model_run.md) | Run a model and interact with it using a submitted prompt or chat mode |
| [`status`](model_status.md) | Check if the Docker Model Runner is running |
| [`tag`](model_tag.md) | Tag a model |
| [`uninstall-runner`](model_uninstall-runner.md) | Uninstall Docker Model Runner |
| [`unload`](model_unload.md) | Unload running models |
| [`version`](model_version.md) | Show the Docker Model Runner version |
| Name | Description |
|:------------------------------------------------|:-------------------------------------------------------------------------------|
| [`configure`](model_configure.md) | Configure runtime options for a model |
| [`df`](model_df.md) | Show Docker Model Runner disk usage |
| [`inspect`](model_inspect.md) | Display detailed information on one model |
| [`install-runner`](model_install-runner.md) | Install Docker Model Runner (Docker Engine only) |
| [`list`](model_list.md) | List the models pulled to your local environment |
| [`logs`](model_logs.md) | Fetch the Docker Model Runner logs |
| [`package`](model_package.md) | Package a GGUF file or Safetensors directory into a Docker model OCI artifact. |
| [`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 |
| [`requests`](model_requests.md) | Fetch requests+responses from Docker Model Runner |
| [`rm`](model_rm.md) | Remove local models downloaded from Docker Hub |
| [`run`](model_run.md) | Run a model and interact with it using a submitted prompt or chat mode |
| [`status`](model_status.md) | Check if the Docker Model Runner is running |
| [`tag`](model_tag.md) | Tag a model |
| [`uninstall-runner`](model_uninstall-runner.md) | Uninstall Docker Model Runner |
| [`unload`](model_unload.md) | Unload running models |
| [`version`](model_version.md) | Show the Docker Model Runner version |



Expand Down
11 changes: 6 additions & 5 deletions cmd/cli/docs/reference/model_install-runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ Install 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) |
| `--port` | `uint16` | `0` | Docker container port for Docker Model Runner (default: 12434 for Docker CE, 12435 for Cloud mode) |
| 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 CE, 12435 for Cloud mode) |


<!---MARKER_GEN_END-->
Expand Down
20 changes: 11 additions & 9 deletions cmd/cli/docs/reference/model_package.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
# docker model package

<!---MARKER_GEN_START-->
Package a GGUF file into a Docker model OCI artifact, with optional licenses. The package is sent to the model-runner, unless --push is specified.
When packaging a sharded model --gguf should point to the first shard. All shard files should be siblings and should include the index in the file name (e.g. model-00001-of-00015.gguf).
Package a GGUF file or Safetensors directory into a Docker model OCI artifact, with optional licenses. The package is sent to the model-runner, unless --push is specified.
When packaging a sharded GGUF model, --gguf should point to the first shard. All shard files should be siblings and should include the index in the file name (e.g. model-00001-of-00015.gguf).
When packaging a Safetensors model, --safetensors-dir should point to a directory containing .safetensors files and config files (*.json, merges.txt). All files will be auto-discovered and config files will be packaged into a tar archive.

### Options

| Name | Type | Default | Description |
|:------------------|:--------------|:--------|:---------------------------------------------------------------------------------------|
| `--chat-template` | `string` | | absolute path to chat template file (must be Jinja format) |
| `--context-size` | `uint64` | `0` | context size in tokens |
| `--gguf` | `string` | | absolute path to gguf file (required) |
| `-l`, `--license` | `stringArray` | | absolute path to a license file |
| `--push` | `bool` | | push to registry (if not set, the model is loaded into the Model Runner content store) |
| Name | Type | Default | Description |
|:--------------------|:--------------|:--------|:---------------------------------------------------------------------------------------|
| `--chat-template` | `string` | | absolute path to chat template file (must be Jinja format) |
| `--context-size` | `uint64` | `0` | context size in tokens |
| `--gguf` | `string` | | absolute path to gguf file |
| `-l`, `--license` | `stringArray` | | absolute path to a license file |
| `--push` | `bool` | | push to registry (if not set, the model is loaded into the Model Runner content store) |
| `--safetensors-dir` | `string` | | absolute path to directory containing safetensors files and config |


<!---MARKER_GEN_END-->
Expand Down
Loading
Loading