Migrate Docker SDK to moby/moby v29 to fix docker/* CVEs

Why this is necessary

github.com/docker/docker and github.com/docker/cli carry several HIGH/MEDIUM CVEs (see the issue). Their fixes only exist in v29, and github.com/docker/docker has no v29 release — at v29 the Docker Engine SDK was split out of that module into two dedicated ones:

  • github.com/moby/moby/api — the API types
  • github.com/moby/moby/client — the client plus its option/result types

So the fix is not a version bump; it requires migrating off github.com/docker/docker onto github.com/moby/moby/{api,client} and bumping github.com/docker/cli to v29. A plain "bump cli to v29" was attempted in !6463 (closed) and could not compile, because cli v29 already returns moby types.

What this does

  • go.mod: drop docker/docker, add moby/moby/api + moby/moby/client, bump docker/cli to v29.6.1. Adds an exclude for the moby/moby v28 monolith so module resolution doesn't pull it back in beside the split api module.
  • Rewrites the helpers/docker.Client adapter for the v29 SDK (option-struct params, result-struct returns) while keeping the interface callers use unchanged.
  • Handles genuine v29 data-model changes in the docker executor: HostConfig.DNS ([]netip.Addr), MAC addresses (network.HardwareAddr), per-network container IPs, exposed-port handling, and disconnect-via-inspect.
  • Updates tests and regenerates mocks.

Approaches considered

  1. Bump the dependency versions only — not possible: docker/docker has no v29, and cli v29 forces moby types. This is the wall the earlier renovate MR hit.
  2. Migrate the interface to mirror the v29 SDK (option-in/result-out everywhere) — most faithful to upstream, but pushes the new call shapes onto every executor call site: a much larger, riskier diff.
  3. Keep the runner's docker.Client interface stable and translate to v29 inside the adapter (chosen) — the runner already wraps the SDK behind its own interface for insulation and mockability, so this leans on that. The v29 churn is confined to one adapter file plus the executor's real data-model changes; callers and tests barely move. Smallest, most reviewable diff for a security fix.

Reviewing

Most of the diff is mechanical: regenerated mocks (~380 lines) and import/type renames in tests. The substantive logic is commit 2 (docker.go) plus the adapter (official_docker_client.go / options.go).

The change is compile-atomic (the CVE-bearing module can't be dropped without moving every import at once), so it is one MR structured as ordered commits for reading, not for bisection — intermediate commits don't individually compile; only the final state builds:

  1. Migrate Docker SDK ... moby/moby v29 — go.mod + adapter/interface + mechanical renames
  2. Adapt Docker executor to moby v29 data-model changesdocker.go, the real logic (worth the closest read)
  3. Update Docker executor tests for moby v29 SDK
  4. Regenerate Docker client mocks for moby v29

Verification

go build ./...; docker unit and integration test packages compile; docker unit tests pass; golangci-lint (v2.12.1) reports no issues on the changed packages.

Closes https://gitlab.com/gitlab-org/gitlab-runner/-/issues/39536

Edited by Lachlan Grant

Merge request reports

Loading