Skip to content

Commit b8802e9

Browse files
authored
Merge pull request #215 from docker/add-host-option
Add --host flag to docker model install-runner command
2 parents cb15122 + de98e30 commit b8802e9

File tree

4 files changed

+116
-11
lines changed

4 files changed

+116
-11
lines changed

cmd/cli/commands/install-runner.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,15 @@ func ensureStandaloneRunnerAvailable(ctx context.Context, printer standalone.Sta
127127

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

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

160163
func newInstallRunner() *cobra.Command {
161164
var port uint16
165+
var host string
162166
var gpuMode string
163167
var doNotTrack bool
164168
c := &cobra.Command{
@@ -245,7 +249,7 @@ func newInstallRunner() *cobra.Command {
245249
return fmt.Errorf("unable to initialize standalone model storage: %w", err)
246250
}
247251
// Create the model runner container.
248-
if err := standalone.CreateControllerContainer(cmd.Context(), dockerClient, port, environment, doNotTrack, gpu, modelStorageVolume, cmd, engineKind); err != nil {
252+
if err := standalone.CreateControllerContainer(cmd.Context(), dockerClient, port, host, environment, doNotTrack, gpu, modelStorageVolume, cmd, engineKind); err != nil {
249253
return fmt.Errorf("unable to initialize standalone model runner container: %w", err)
250254
}
251255

@@ -256,6 +260,7 @@ func newInstallRunner() *cobra.Command {
256260
}
257261
c.Flags().Uint16Var(&port, "port", 0,
258262
"Docker container port for Docker Model Runner (default: 12434 for Docker CE, 12435 for Cloud mode)")
263+
c.Flags().StringVar(&host, "host", "127.0.0.1", "Host address to bind Docker Model Runner")
259264
c.Flags().StringVar(&gpuMode, "gpu", "auto", "Specify GPU support (none|auto|cuda)")
260265
c.Flags().BoolVar(&doNotTrack, "do-not-track", false, "Do not track models usage in Docker Model Runner")
261266
return c
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package commands
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestInstallRunnerHostFlag(t *testing.T) {
8+
// Create the install-runner command
9+
cmd := newInstallRunner()
10+
11+
// Verify the --host flag exists
12+
hostFlag := cmd.Flags().Lookup("host")
13+
if hostFlag == nil {
14+
t.Fatal("--host flag not found")
15+
}
16+
17+
// Verify the default value
18+
if hostFlag.DefValue != "127.0.0.1" {
19+
t.Errorf("Expected default host value to be '127.0.0.1', got '%s'", hostFlag.DefValue)
20+
}
21+
22+
// Verify the flag type
23+
if hostFlag.Value.Type() != "string" {
24+
t.Errorf("Expected host flag type to be 'string', got '%s'", hostFlag.Value.Type())
25+
}
26+
27+
// Test setting the flag value
28+
testCases := []struct {
29+
name string
30+
value string
31+
}{
32+
{"localhost", "127.0.0.1"},
33+
{"all interfaces", "0.0.0.0"},
34+
{"specific IP", "192.168.1.100"},
35+
}
36+
37+
for _, tc := range testCases {
38+
t.Run(tc.name, func(t *testing.T) {
39+
// Reset the command for each test
40+
cmd := newInstallRunner()
41+
err := cmd.Flags().Set("host", tc.value)
42+
if err != nil {
43+
t.Errorf("Failed to set host flag to '%s': %v", tc.value, err)
44+
}
45+
46+
// Verify the value was set
47+
hostValue, err := cmd.Flags().GetString("host")
48+
if err != nil {
49+
t.Errorf("Failed to get host flag value: %v", err)
50+
}
51+
if hostValue != tc.value {
52+
t.Errorf("Expected host value to be '%s', got '%s'", tc.value, hostValue)
53+
}
54+
})
55+
}
56+
}
57+
58+
func TestInstallRunnerCommandFlags(t *testing.T) {
59+
cmd := newInstallRunner()
60+
61+
// Verify all expected flags exist
62+
expectedFlags := []string{"port", "host", "gpu", "do-not-track"}
63+
for _, flagName := range expectedFlags {
64+
if cmd.Flags().Lookup(flagName) == nil {
65+
t.Errorf("Expected flag '--%s' not found", flagName)
66+
}
67+
}
68+
}
69+
70+
func TestInstallRunnerCommandType(t *testing.T) {
71+
cmd := newInstallRunner()
72+
73+
// Verify command properties
74+
if cmd.Use != "install-runner" {
75+
t.Errorf("Expected command Use to be 'install-runner', got '%s'", cmd.Use)
76+
}
77+
78+
if cmd.Short != "Install Docker Model Runner (Docker Engine only)" {
79+
t.Errorf("Unexpected command Short description: %s", cmd.Short)
80+
}
81+
82+
// Verify RunE is set
83+
if cmd.RunE == nil {
84+
t.Error("Expected RunE to be set")
85+
}
86+
}
87+
88+
func TestInstallRunnerValidArgsFunction(t *testing.T) {
89+
cmd := newInstallRunner()
90+
91+
// The install-runner command should not accept any arguments
92+
// So ValidArgsFunction should be set to handle no arguments
93+
if cmd.ValidArgsFunction == nil {
94+
t.Error("Expected ValidArgsFunction to be set")
95+
}
96+
}

cmd/cli/docs/reference/model_install-runner.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ Install Docker Model Runner (Docker Engine only)
55

66
### Options
77

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

1415

1516
<!---MARKER_GEN_END-->

cmd/cli/pkg/standalone/containers.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ func ensureContainerStarted(ctx context.Context, dockerClient client.ContainerAP
218218
}
219219

220220
// CreateControllerContainer creates and starts a controller container.
221-
func CreateControllerContainer(ctx context.Context, dockerClient *client.Client, port uint16, environment string, doNotTrack bool, gpu gpupkg.GPUSupport, modelStorageVolume string, printer StatusPrinter, engineKind types.ModelRunnerEngineKind) error {
221+
func CreateControllerContainer(ctx context.Context, dockerClient *client.Client, port uint16, host string, environment string, doNotTrack bool, gpu gpupkg.GPUSupport, modelStorageVolume string, printer StatusPrinter, engineKind types.ModelRunnerEngineKind) error {
222222
// Determine the target image.
223223
var imageName string
224224
switch gpu {
@@ -260,11 +260,14 @@ func CreateControllerContainer(ctx context.Context, dockerClient *client.Client,
260260
Name: "always",
261261
},
262262
}
263-
portBindings := []nat.PortBinding{{HostIP: "127.0.0.1", HostPort: portStr}}
263+
portBindings := []nat.PortBinding{{HostIP: host, HostPort: portStr}}
264264
if os.Getenv("_MODEL_RUNNER_TREAT_DESKTOP_AS_MOBY") != "1" {
265265
// Don't bind the bridge gateway IP if we're treating Docker Desktop as Moby.
266-
if bridgeGatewayIP, err := determineBridgeGatewayIP(ctx, dockerClient); err == nil && bridgeGatewayIP != "" {
267-
portBindings = append(portBindings, nat.PortBinding{HostIP: bridgeGatewayIP, HostPort: portStr})
266+
// Only add bridge gateway IP binding if host is 127.0.0.1
267+
if host == "127.0.0.1" {
268+
if bridgeGatewayIP, err := determineBridgeGatewayIP(ctx, dockerClient); err == nil && bridgeGatewayIP != "" {
269+
portBindings = append(portBindings, nat.PortBinding{HostIP: bridgeGatewayIP, HostPort: portStr})
270+
}
268271
}
269272
}
270273
hostConfig.PortBindings = nat.PortMap{

0 commit comments

Comments
 (0)