Skip to content

updating docker to moby. Removing windows support for lifecycle#10096

Merged
Darien-Lin merged 1 commit into
GoogleContainerTools:mainfrom
Darien-Lin:main
May 28, 2026
Merged

updating docker to moby. Removing windows support for lifecycle#10096
Darien-Lin merged 1 commit into
GoogleContainerTools:mainfrom
Darien-Lin:main

Conversation

@Darien-Lin

@Darien-Lin Darien-Lin commented May 27, 2026

Copy link
Copy Markdown
Contributor

Overview

This PR updates Skaffold's Docker SDK dependencies from the legacy github.com/docker/docker package to the modern github.com/moby/moby/client package to address a security vulnerability (CVE-2026-34040).

As part of this upgrade, downstream dependency updates (including go-containerregistry and lifecycle) have been integrated.

Key Changes

  1. Docker to Moby Migration
    Migrated Skaffold's Docker client initialization and structures from github.com/docker/docker to github.com/moby/moby/client.
    Minimally refactored pkg/skaffold/deploy/docker/deploy.go and related tasks to adapt to the new Moby API types (such as container.Summary and client.Filters) while preserving 100% of the original logic and removing any compile-time dependencies on the legacy docker/docker repository.
  2. go-containerregistry Concurrency Deadlock Resolution
    Upgrading the dependencies introduced a critical deadlock during local Minikube/sideloading operations in GHA integration tests (TestRun/ko test hung indefinitely). This was caused by a leaked layer stream reader bug in go-containerregistry v0.21.6's newly added concurrency pullLimiter.
    Resolution: Pinned go-containerregistry to v0.21.4 in go.mod. This version fully supports the new Moby client migration but does not include the concurrency limiter feature, eliminating the deadlock natively and ensuring all integration suites pass cleanly. go-containerregistry already has the fix in @ HEAD.

⚠️ Critical User-Facing Changes (Windows Impact)

Bumping the lifecycle package past v0.20.6 (required for Moby alignment) introduces breaking changes regarding native Windows support:

Native Buildpacks on Windows Hosts are No Longer Supported

Natively running Buildpack-based builds on a Windows host is no longer supported in Skaffold.

Impacted Skaffold Features & Workarounds:
Skaffold Buildpacks Builder:
Native Windows Execution: Running skaffold build or skaffold dev on a native Windows machine targeting buildpacks will fail.
Workaround: Windows users must run Buildpack-based builds inside a Linux environment.

# examples/buildpacks/skaffold.yaml
profiles:
- name: gcb
  build:
    googleCloudBuild: {}
@Darien-Lin Darien-Lin requested a review from a team as a code owner May 27, 2026 18:43

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request migrates the codebase from the deprecated github.com/docker/docker package to github.com/moby/moby and github.com/containerd/errdefs. This migration affects numerous imports, client configurations, and error handling paths across the skaffold, buildpacks, and pack components. Two critical issues were identified in the review: first, the use of client.ImageInspectWithRawResponse in pkg/skaffold/docker/image.go causes a SIGSEGV panic in tests due to mock client limitations, which can be resolved by directly marshaling the inspect response to JSON; second, the mock errors in pkg/skaffold/build/docker/docker_test.go need to be updated to use Internal() and Canceled() to align with the new containerd/errdefs expectations.

Comment on lines +617 to 624
func (l *localDaemon) ImageInspectWithRaw(ctx context.Context, img string) (image.InspectResponse, []byte, error) {
var raw bytes.Buffer
res, err := l.apiClient.ImageInspect(ctx, img, client.ImageInspectWithRawResponse(&raw))
if err != nil {
return image.InspectResponse{}, nil, err
}
return res.InspectResponse, raw.Bytes(), nil
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

Using client.ImageInspectWithRawResponse causes a SIGSEGV panic in tests (as seen in test.log) because the fake/mock client (FakeAPIClient) cannot safely extract the unexported rawResponse field from the unexported imageInspectConfig struct across package boundaries, leading to memory corruption or nil pointer dereferences.

We can completely avoid this fragile dependency on client.ImageInspectWithRawResponse by simply marshaling the returned res.InspectResponse to JSON directly using json.Marshal. This is fully compatible, safer, and fixes the test failures.

func (l *localDaemon) ImageInspectWithRaw(ctx context.Context, img string) (image.InspectResponse, []byte, error) {
	res, err := l.apiClient.ImageInspect(ctx, img)
	if err != nil {
		return image.InspectResponse{}, nil, err
	}
	raw, err := json.Marshal(res.InspectResponse)
	if err != nil {
		return image.InspectResponse{}, nil, err
	}
	return res.InspectResponse, raw, nil
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need the option for fakes. In fakes, we don't set the config, which ends up causing issues.

Comment on lines +281 to +291
type systemError struct {
error
}

func (systemError) System() {}

type cancelledError struct {
error
}

func (cancelledError) Cancelled() {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The mock errors systemError and cancelledError are using method names (System() and Cancelled()) from the old docker/errdefs package. Since this PR migrates to containerd/errdefs, these mocks will no longer be recognized by errdefs.IsInternal and errdefs.IsCanceled.

Specifically:

  1. errdefs.IsInternal checks for an Internal() method, not System().
  2. errdefs.IsCanceled checks for a Canceled() method (spelled with one 'l'), not Cancelled().

We should update these mock methods to match the containerd/errdefs expectations so that the error classification behaves correctly in tests.

Suggested change
type systemError struct {
error
}
func (systemError) System() {}
type cancelledError struct {
error
}
func (cancelledError) Cancelled() {}
type systemError struct {
error
}
func (systemError) Internal() {}
type cancelledError struct {
error
}
func (cancelledError) Canceled() {}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

errdefs.IsInternal / IsCancelled requires System / Canceled. This comment is incorrect.

@Darien-Lin Darien-Lin force-pushed the main branch 16 times, most recently from abb88b5 to 9ba2d30 Compare May 28, 2026 05:06
@Darien-Lin Darien-Lin added the kokoro:force-run forces a kokoro re-run on a PR label May 28, 2026
@kokoro-team kokoro-team removed the kokoro:force-run forces a kokoro re-run on a PR label May 28, 2026
@Darien-Lin Darien-Lin merged commit ee7ac82 into GoogleContainerTools:main May 28, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

3 participants