Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
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