Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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: 1 addition & 0 deletions cmd/cli/commands/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func newUpCommand() *cobra.Command {
return errors.New("unable to determine standalone runner endpoint")
}

syncDockerConfigForRegistry(cmd.Context(), asPrinter(cmd))
if err := downloadModelsOnlyIfNotFound(desktopClient, models); err != nil {
return err
}
Expand Down
1 change: 1 addition & 0 deletions cmd/cli/commands/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ func newPullCmd() *cobra.Command {

func pullModel(cmd *cobra.Command, desktopClient *desktop.Client, model string) error {
printer := asPrinter(cmd)
syncDockerConfigForRegistry(cmd.Context(), printer)
response, _, err := desktopClient.Pull(model, printer)

if err != nil {
Expand Down
1 change: 1 addition & 0 deletions cmd/cli/commands/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func newPushCmd() *cobra.Command {

func pushModel(cmd *cobra.Command, desktopClient *desktop.Client, model string) error {
printer := asPrinter(cmd)
syncDockerConfigForRegistry(cmd.Context(), printer)
response, _, err := desktopClient.Push(model, printer)

if err != nil {
Expand Down
28 changes: 28 additions & 0 deletions cmd/cli/commands/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package commands

import (
"bytes"
"context"
"errors"
"fmt"
"io"
Expand All @@ -10,6 +11,7 @@ import (

"github.com/docker/model-runner/cmd/cli/desktop"
"github.com/docker/model-runner/cmd/cli/pkg/standalone"
"github.com/docker/model-runner/cmd/cli/pkg/types"
"github.com/docker/model-runner/pkg/distribution/distribution"
"github.com/docker/model-runner/pkg/distribution/oci/reference"
"github.com/docker/model-runner/pkg/inference/backends/vllm"
Expand Down Expand Up @@ -247,6 +249,32 @@ func addRunnerFlags(cmd *cobra.Command, opts runnerFlagOptions) {
}
}

// syncDockerConfigForRegistry copies the host's Docker config into the running
// container. Only applicable for Moby engine setups; a no-op otherwise.
func syncDockerConfigForRegistry(ctx context.Context, printer standalone.StatusPrinter) {
if modelRunner == nil {
return
}
engineKind := modelRunner.EngineKind()
if engineKind != types.ModelRunnerEngineKindMoby {
return
}
dockerClient, err := desktop.DockerClientForContext(dockerCLI, dockerCLI.CurrentContext())
Comment thread
areebahmeddd marked this conversation as resolved.
if err != nil {
return // non-fatal: proceed with potentially stale credentials
Comment thread
areebahmeddd marked this conversation as resolved.
Outdated
}
defer dockerClient.Close()

containerID, _, _, err := standalone.FindControllerContainer(ctx, dockerClient)
if err != nil || containerID == "" {
return // non-fatal: container may not be running yet
Comment thread
areebahmeddd marked this conversation as resolved.
Outdated
}

if err := standalone.SyncDockerConfigToContainer(ctx, dockerClient, containerID, engineKind); err != nil {
printer.Printf("Warning: failed to sync Docker credentials to runner: %v\n", err)
}
}

// newTable creates a new table with Docker CLI-style formatting:
// no borders, no column separators, no header line, left-aligned, and 2-space padding.
func newTable(w io.Writer) *tablewriter.Table {
Expand Down
9 changes: 4 additions & 5 deletions cmd/cli/pkg/standalone/containers.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,9 @@ import (
// controllerContainerName is the name to use for the controller container.
const controllerContainerName = "docker-model-runner"

// copyDockerConfigToContainer copies the Docker config file from the host to the container
// and sets up proper ownership and permissions for the modelrunner user.
// It does nothing for Desktop and Cloud engine kinds.
func copyDockerConfigToContainer(ctx context.Context, dockerClient *client.Client, containerID string, engineKind types.ModelRunnerEngineKind) error {
// SyncDockerConfigToContainer copies the host's ~/.docker/config.json into the
// running container. It is a no-op for Desktop and Cloud engine kinds.
func SyncDockerConfigToContainer(ctx context.Context, dockerClient *client.Client, containerID string, engineKind types.ModelRunnerEngineKind) error {
Comment thread
areebahmeddd marked this conversation as resolved.
Comment thread
areebahmeddd marked this conversation as resolved.
// Do nothing for Desktop and Cloud engine kinds
if engineKind == types.ModelRunnerEngineKindDesktop || engineKind == types.ModelRunnerEngineKindCloud ||
Comment thread
sourcery-ai[bot] marked this conversation as resolved.
os.Getenv("_MODEL_RUNNER_TREAT_DESKTOP_AS_MOBY") == "1" {
Expand Down Expand Up @@ -622,7 +621,7 @@ func CreateControllerContainer(ctx context.Context, dockerClient *client.Client,

// Copy Docker config file if it exists and we're the container creator.
if created && !vllmOnWSL {
if err := copyDockerConfigToContainer(ctx, dockerClient, resp.ID, engineKind); err != nil {
if err := SyncDockerConfigToContainer(ctx, dockerClient, resp.ID, engineKind); err != nil {
// Log warning but continue - don't fail container creation
printer.Printf("Warning: failed to copy Docker config: %v\n", err)
}
Expand Down
48 changes: 48 additions & 0 deletions cmd/cli/pkg/standalone/containers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package standalone

import (
"context"
"os"
"path/filepath"
"testing"

"github.com/docker/model-runner/cmd/cli/pkg/types"
)

// TestSyncDockerConfigToContainer_NoopForDesktopAndCloud verifies that
// SyncDockerConfigToContainer skips Desktop and Cloud engine kinds.
Comment thread
areebahmeddd marked this conversation as resolved.
func TestSyncDockerConfigToContainer_NoopForDesktopAndCloud(t *testing.T) {
tmpDir := t.TempDir()
dockerDir := filepath.Join(tmpDir, ".docker")
if err := os.MkdirAll(dockerDir, 0o700); err != nil {
t.Fatalf("failed to create .docker dir: %v", err)
}
if err := os.WriteFile(filepath.Join(dockerDir, "config.json"), []byte(`{}`), 0o600); err != nil {
t.Fatalf("failed to write config.json: %v", err)
}
t.Setenv("HOME", tmpDir)

for _, engineKind := range []types.ModelRunnerEngineKind{
types.ModelRunnerEngineKindDesktop,
types.ModelRunnerEngineKindCloud,
} {
t.Run(engineKind.String(), func(t *testing.T) {
err := SyncDockerConfigToContainer(context.Background(), nil, "container-id", engineKind)
if err != nil {
t.Fatalf("SyncDockerConfigToContainer(%v) returned unexpected error: %v", engineKind, err)
}
})
}
}

// TestSyncDockerConfigToContainer_NoopWhenConfigMissing verifies that
// SyncDockerConfigToContainer skips when the host config file is absent.
func TestSyncDockerConfigToContainer_NoopWhenConfigMissing(t *testing.T) {
tmpDir := t.TempDir()
t.Setenv("HOME", tmpDir)

err := SyncDockerConfigToContainer(context.Background(), nil, "container-id", types.ModelRunnerEngineKindMoby)
if err != nil {
t.Fatalf("SyncDockerConfigToContainer returned unexpected error for missing config: %v", err)
}
}