Skip to content

Commit 86a2bbc

Browse files
authored
Merge pull request #437 from doringeman/wake-up-docker-cloud
feat: wake up idle Docker Cloud contexts automatically
2 parents acf63aa + 6e20dcd commit 86a2bbc

File tree

2 files changed

+61
-2
lines changed

2 files changed

+61
-2
lines changed

cmd/cli/commands/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func NewRootCmd(cli *command.DockerCli) *cobra.Command {
6666

6767
// Detect the model runner context and create a client for it.
6868
var err error
69-
modelRunner, err = desktop.DetectContext(cmd.Context(), dockerCLI)
69+
modelRunner, err = desktop.DetectContext(cmd.Context(), dockerCLI, asPrinter(cmd))
7070
if err != nil {
7171
return fmt.Errorf("unable to detect model runner context: %w", err)
7272
}

cmd/cli/desktop/context.go

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"strings"
1212
"time"
1313

14+
"github.com/containerd/errdefs"
1415
"github.com/docker/cli/cli/command"
1516
"github.com/docker/cli/cli/context/docker"
1617
clientpkg "github.com/docker/docker/client"
@@ -131,8 +132,59 @@ func NewContextForTest(endpoint string, client DockerHttpClient) (*ModelRunnerCo
131132
}, nil
132133
}
133134

135+
// wakeUpCloudIfIdle checks if the Docker Cloud context is idle and wakes it up if needed.
136+
func wakeUpCloudIfIdle(ctx context.Context, cli *command.DockerCli) error {
137+
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
138+
defer cancel()
139+
140+
info, err := cli.Client().Info(ctx)
141+
if err != nil {
142+
return fmt.Errorf("failed to get Docker info: %w", err)
143+
}
144+
145+
// Check if the cloud.docker.run.engine label is set to "idle".
146+
isIdle := false
147+
for _, label := range info.Labels {
148+
if label == "cloud.docker.run.engine=idle" {
149+
isIdle = true
150+
break
151+
}
152+
}
153+
if !isIdle {
154+
return nil
155+
}
156+
157+
// Wake up Docker Cloud by triggering an empty ContainerCreate call.
158+
dockerClient, err := DockerClientForContext(cli, cli.CurrentContext())
159+
if err != nil {
160+
return fmt.Errorf("failed to create Docker client: %w", err)
161+
}
162+
163+
// The call is expected to fail with a client error due to nil arguments, but it triggers
164+
// Docker Cloud to wake up from idle. Only return unexpected failures (network issues,
165+
// server errors) so they're logged as warnings.
166+
_, err = dockerClient.ContainerCreate(ctx, nil, nil, nil, nil, "")
167+
if err != nil && !errdefs.IsInvalidArgument(err) {
168+
return fmt.Errorf("failed to wake up Docker Cloud: %w", err)
169+
}
170+
171+
// Verify Docker Cloud is no longer idle.
172+
info, err = cli.Client().Info(ctx)
173+
if err != nil {
174+
return fmt.Errorf("failed to verify Docker Cloud wake-up: %w", err)
175+
}
176+
177+
for _, label := range info.Labels {
178+
if label == "cloud.docker.run.engine=idle" {
179+
return fmt.Errorf("failed to wake up Docker Cloud from idle state")
180+
}
181+
}
182+
183+
return nil
184+
}
185+
134186
// DetectContext determines the current Docker Model Runner context.
135-
func DetectContext(ctx context.Context, cli *command.DockerCli) (*ModelRunnerContext, error) {
187+
func DetectContext(ctx context.Context, cli *command.DockerCli, printer standalone.StatusPrinter) (*ModelRunnerContext, error) {
136188
// Check for an explicit endpoint setting.
137189
modelRunnerHost := os.Getenv("MODEL_RUNNER_HOST")
138190

@@ -151,6 +203,13 @@ func DetectContext(ctx context.Context, cli *command.DockerCli) (*ModelRunnerCon
151203
}
152204
} else if isCloudContext(cli) {
153205
kind = types.ModelRunnerEngineKindCloud
206+
// Wake up Docker Cloud if it's idle.
207+
if err := wakeUpCloudIfIdle(ctx, cli); err != nil {
208+
// Log the error as a warning but don't fail - we'll try to use Docker Cloud anyway.
209+
// The downside is that the wrong docker/model-runner image might be automatically
210+
// pulled on docker install-runner because the runtime can't be properly verified.
211+
printer.Printf("Warning: %v\n", err)
212+
}
154213
}
155214

156215
// Compute the URL prefix based on the associated engine kind.

0 commit comments

Comments
 (0)