[CONTINT-5217][CONTINT-5218][CONTINT-5219][CONTINT-5220] Upgrade Docker SDK from docker/docker v28 to moby/moby v29#48777
Conversation
Go Package Import DifferencesBaseline: 61fdef4
|
Files inventory check summaryFile checks results against ancestor 61fdef49: Results for datadog-agent_7.79.0~devel.git.464.c1e5bcd.pipeline.106591804-1_amd64.deb:No change detected |
Static quality checks✅ Please find below the results from static quality gates Successful checksInfo
7 successful checks with minimal change (< 2 KiB)
On-wire sizes (compressed)
|
Regression DetectorRegression Detector ResultsMetrics dashboard Baseline: fd8f08b Optimization Goals: ✅ No significant changes detected
|
| perf | experiment | goal | Δ mean % | Δ mean % CI | trials | links |
|---|---|---|---|---|---|---|
| ➖ | docker_containers_cpu | % cpu utilization | +3.16 | [+0.10, +6.21] | 1 | Logs |
Fine details of change detection per experiment
| perf | experiment | goal | Δ mean % | Δ mean % CI | trials | links |
|---|---|---|---|---|---|---|
| ➖ | docker_containers_cpu | % cpu utilization | +3.16 | [+0.10, +6.21] | 1 | Logs |
| ➖ | quality_gate_logs | % cpu utilization | +2.71 | [+1.03, +4.40] | 1 | Logs bounds checks dashboard |
| ➖ | file_tree | memory utilization | +0.93 | [+0.87, +0.99] | 1 | Logs |
| ➖ | quality_gate_idle | memory utilization | +0.85 | [+0.80, +0.91] | 1 | Logs bounds checks dashboard |
| ➖ | uds_dogstatsd_20mb_12k_contexts_20_senders | memory utilization | +0.76 | [+0.69, +0.82] | 1 | Logs |
| ➖ | otlp_ingest_metrics | memory utilization | +0.55 | [+0.39, +0.71] | 1 | Logs |
| ➖ | ddot_logs | memory utilization | +0.40 | [+0.34, +0.47] | 1 | Logs |
| ➖ | ddot_metrics_sum_cumulative | memory utilization | +0.34 | [+0.20, +0.49] | 1 | Logs |
| ➖ | docker_containers_memory | memory utilization | +0.24 | [+0.16, +0.32] | 1 | Logs |
| ➖ | quality_gate_idle_all_features | memory utilization | +0.17 | [+0.14, +0.21] | 1 | Logs bounds checks dashboard |
| ➖ | tcp_syslog_to_blackhole | ingress throughput | +0.15 | [-0.03, +0.33] | 1 | Logs |
| ➖ | otlp_ingest_logs | memory utilization | +0.05 | [-0.05, +0.15] | 1 | Logs |
| ➖ | ddot_metrics | memory utilization | +0.04 | [-0.15, +0.23] | 1 | Logs |
| ➖ | file_to_blackhole_1000ms_latency | egress throughput | +0.02 | [-0.42, +0.46] | 1 | Logs |
| ➖ | file_to_blackhole_0ms_latency | egress throughput | +0.02 | [-0.55, +0.59] | 1 | Logs |
| ➖ | file_to_blackhole_500ms_latency | egress throughput | +0.02 | [-0.38, +0.42] | 1 | Logs |
| ➖ | file_to_blackhole_100ms_latency | egress throughput | +0.01 | [-0.10, +0.12] | 1 | Logs |
| ➖ | uds_dogstatsd_to_api_v3 | ingress throughput | +0.01 | [-0.19, +0.21] | 1 | Logs |
| ➖ | tcp_dd_logs_filter_exclude | ingress throughput | +0.01 | [-0.11, +0.12] | 1 | Logs |
| ➖ | uds_dogstatsd_to_api | ingress throughput | +0.00 | [-0.21, +0.22] | 1 | Logs |
| ➖ | ddot_metrics_sum_delta | memory utilization | -0.07 | [-0.25, +0.10] | 1 | Logs |
| ➖ | ddot_metrics_sum_cumulativetodelta_exporter | memory utilization | -0.10 | [-0.32, +0.13] | 1 | Logs |
| ➖ | quality_gate_metrics_logs | memory utilization | -0.29 | [-0.53, -0.06] | 1 | Logs bounds checks dashboard |
Bounds Checks: ✅ Passed
| perf | experiment | bounds_check_name | replicates_passed | observed_value | links |
|---|---|---|---|---|---|
| ✅ | docker_containers_cpu | simple_check_run | 10/10 | 674 ≥ 26 | |
| ✅ | docker_containers_memory | memory_usage | 10/10 | 275.44MiB ≤ 370MiB | |
| ✅ | docker_containers_memory | simple_check_run | 10/10 | 697 ≥ 26 | |
| ✅ | file_to_blackhole_0ms_latency | memory_usage | 10/10 | 0.19GiB ≤ 1.20GiB | |
| ✅ | file_to_blackhole_0ms_latency | missed_bytes | 10/10 | 0B = 0B | |
| ✅ | file_to_blackhole_1000ms_latency | memory_usage | 10/10 | 0.23GiB ≤ 1.20GiB | |
| ✅ | file_to_blackhole_1000ms_latency | missed_bytes | 10/10 | 0B = 0B | |
| ✅ | file_to_blackhole_100ms_latency | memory_usage | 10/10 | 0.20GiB ≤ 1.20GiB | |
| ✅ | file_to_blackhole_100ms_latency | missed_bytes | 10/10 | 0B = 0B | |
| ✅ | file_to_blackhole_500ms_latency | memory_usage | 10/10 | 0.22GiB ≤ 1.20GiB | |
| ✅ | file_to_blackhole_500ms_latency | missed_bytes | 10/10 | 0B = 0B | |
| ✅ | quality_gate_idle | intake_connections | 10/10 | 3 = 3 | bounds checks dashboard |
| ✅ | quality_gate_idle | memory_usage | 10/10 | 177.54MiB ≤ 181MiB | bounds checks dashboard |
| ✅ | quality_gate_idle_all_features | intake_connections | 10/10 | 3 = 3 | bounds checks dashboard |
| ✅ | quality_gate_idle_all_features | memory_usage | 10/10 | 498.90MiB ≤ 550MiB | bounds checks dashboard |
| ✅ | quality_gate_logs | intake_connections | 10/10 | 3 ≤ 6 | bounds checks dashboard |
| ✅ | quality_gate_logs | memory_usage | 10/10 | 206.16MiB ≤ 220MiB | bounds checks dashboard |
| ✅ | quality_gate_logs | missed_bytes | 10/10 | 0B = 0B | bounds checks dashboard |
| ✅ | quality_gate_metrics_logs | cpu_usage | 10/10 | 353.23 ≤ 2000 | bounds checks dashboard |
| ✅ | quality_gate_metrics_logs | intake_connections | 10/10 | 4 ≤ 6 | bounds checks dashboard |
| ✅ | quality_gate_metrics_logs | memory_usage | 10/10 | 423.94MiB ≤ 475MiB | bounds checks dashboard |
| ✅ | quality_gate_metrics_logs | missed_bytes | 10/10 | 0B = 0B | bounds checks dashboard |
Explanation
Confidence level: 90.00%
Effect size tolerance: |Δ mean %| ≥ 5.00%
Performance changes are noted in the perf column of each table:
- ✅ = significantly better comparison variant performance
- ❌ = significantly worse comparison variant performance
- ➖ = no significant change in performance
A regression test is an A/B test of target performance in a repeatable rig, where "performance" is measured as "comparison variant minus baseline variant" for an optimization goal (e.g., ingress throughput). Due to intrinsic variability in measuring that goal, we can only estimate its mean value for each experiment; we report uncertainty in that value as a 90.00% confidence interval denoted "Δ mean % CI".
For each experiment, we decide whether a change in performance is a "regression" -- a change worth investigating further -- if all of the following criteria are true:
-
Its estimated |Δ mean %| ≥ 5.00%, indicating the change is big enough to merit a closer look.
-
Its 90.00% confidence interval "Δ mean % CI" does not contain zero, indicating that if our statistical model is accurate, there is at least a 90.00% chance there is a difference in performance between baseline and comparison variants.
-
Its configuration does not mark it "erratic".
CI Pass/Fail Decision
✅ Passed. All Quality Gates passed.
- quality_gate_metrics_logs, bounds check memory_usage: 10/10 replicas passed. Gate passed.
- quality_gate_metrics_logs, bounds check intake_connections: 10/10 replicas passed. Gate passed.
- quality_gate_metrics_logs, bounds check missed_bytes: 10/10 replicas passed. Gate passed.
- quality_gate_metrics_logs, bounds check cpu_usage: 10/10 replicas passed. Gate passed.
- quality_gate_idle_all_features, bounds check intake_connections: 10/10 replicas passed. Gate passed.
- quality_gate_idle_all_features, bounds check memory_usage: 10/10 replicas passed. Gate passed.
- quality_gate_idle, bounds check memory_usage: 10/10 replicas passed. Gate passed.
- quality_gate_idle, bounds check intake_connections: 10/10 replicas passed. Gate passed.
- quality_gate_logs, bounds check intake_connections: 10/10 replicas passed. Gate passed.
- quality_gate_logs, bounds check memory_usage: 10/10 replicas passed. Gate passed.
- quality_gate_logs, bounds check missed_bytes: 10/10 replicas passed. Gate passed.
docker/docker v28 to moby/moby v29
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 51fa32cde4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
…er SDK from docker/docker v28 to moby/moby v29 Migrate from github.com/docker/docker v28.5.2+incompatible to github.com/moby/moby/api v1.54.1 and github.com/moby/moby/client v0.4.0 to fix CVE-2026-34040 (High, CVSS 7.8) and CVE-2026-33997 (Medium, CVSS 8.1). This is a major SDK migration: Docker Engine v29 restructured its Go modules into separate sub-modules (moby/moby/api for types, moby/moby/client for the client) with a new Options/Result pattern for all API methods. Key changes: - Update all 55 files importing from github.com/docker/docker - Adapt to v29 Options/Result method signatures in DockerUtil wrapper - Migrate filters from api/types/filters to client.Filters - Handle removed types: ContainerJSONBase (flattened into InspectResponse), image.Summary.VirtualSize, image.InspectResponse.DockerVersion/ContainerConfig - Handle type changes: IPAddress (string -> netip.Addr), Port (nat.Port -> network.Port), ContainerState (string -> typed) - Replace libnetwork/resolvconf with inline implementation (removed in v29) - Update ContainerExec* -> Exec* method names in e2e framework Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
51fa32c to
27747ca
Compare
YoannGh
left a comment
There was a problem hiding this comment.
Thanks for taking care of this!
|
/merge |
|
View all feedbacks in Devflow UI.
The expected merge time in
|
|
We're having some pipeline failures, often around container building. Pipeline failure analysisThis PR appears to be the cause of pipeline failures starting around 2026-04-10. What fails: The OTel agent build pipeline fails at Root cause: The In Go workspace mode, replace directives from individual This PR updated the root
In workspace mode, Recommended fix: From the repo root, run: go work syncThis will update |
|
TBH. I think the claude analysis is wrong here. I'm still leaving the comment because we are getting random docker container build failures, and this seems like a likely culprit. |
…49233) ### What does this PR do? Adds `KUBERNETES_MEMORY_REQUEST` and `KUBERNETES_MEMORY_LIMIT` (32Gi) to the `docker_image_build_otel` CI job, which was the only OTel integration test job without Kubernetes memory limits. ### Motivation The `docker_image_build_otel` job has a **~12% flaky failure rate** on `main`, caused by OOM kills during `go mod download` of 40+ OTel modules inside a Docker-in-Docker build (see [Slack thread](https://dd.slack.com/archives/CR5TV8QBY/p1775901945411339)). **Root cause analysis** ([posted in thread](https://dd.slack.com/archives/CR5TV8QBY/p1775979407970919?thread_ts=1775901945.411339&cid=CR5TV8QBY)): - Datadog CI data shows **64 failures / 469 successes over 7 days** (~12%), with failures pre-dating the initially suspected PR #48777 (one failure on Apr 9, a day before the PR merged) - **60%** of failures are Kubernetes pod scheduling failures (insufficient memory, unmatched node affinity) - **25%** are silent process kills (exit code 255) during `go mod download` — classic OOM pattern - The two sibling OTel jobs already have memory limits: - `integration_tests_otel`: 16Gi - `datadog_otel_components_ocb_build`: 32Gi + 16 CPU - `docker_image_build_otel` had **none**, relying on runner defaults Setting REQUEST = LIMIT = 32Gi gives the pod a Guaranteed QoS class in Kubernetes, matching the OCB build job which performs the same workload (OCB generation + Go compilation). ### Describe how you validated your changes - The YAML structure matches the existing pattern used by all other jobs in this file - The 32Gi value matches `datadog_otel_components_ocb_build` which does the same work - Validation will come from observing the failure rate drop after merge ### Additional Notes The `.ddot_byoc_oci_build_test` template and `ddot_byoc_binary_build_test_ubuntu2004` job in the same file also lack memory limits and perform similar Docker builds. They may benefit from the same treatment as a follow-up. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…AddressPools` (#51235) ### What does this PR do? Adds a tolerant decoder for the Docker daemon's `/info` response in `pkg/util/docker/`, so that daemons emitting invalid CIDRs in `DefaultAddressPools[].Base` no longer break `DockerUtil` and its downstream callers. Concretely: - New helper `safeInfo(ctx, cli)` (`pkg/util/docker/safe_info.go`): tries `cli.Info(...)` first; on the SDK's JSON-decode failure prefix only, reissues `GET /info` via `cli.Dialer()` and decodes into a mirror of `system.Info` where `DefaultAddressPools` is shadowed by `json.RawMessage`, so the strict `netip.Prefix` field stays at zero value and the rest of the struct still parses. - 5 callsites of `cli.Info(ctx, client.InfoOptions{})` switched to `safeInfo(...)`: `ConnectToDocker`, `DockerUtil.GetHostname`, `DockerUtil.GetStorageStats`, `GetMetadata`, `GetTags`. - `host_tags.go` refactored: pure `buildSwarmTags(info system.Info) []string` extracted; `host_tags_test.go` tests it directly without the `client.SystemAPIClient` mock. - `BUILD.bazel` updated: new files added, unused `//pkg/util/docker/fake` test dep removed. - Release note added. ### Motivation [Incident #54830](https://dd.slack.com/archives/C0B55994JGL/p1779448036913569). Reported symptom (from agent debug logs): ``` PROCESS | DEBUG | (pkg/util/hostname/container.go:34 in callContainerProvider) | GetHostname trying provider 'docker' ... PROCESS | DEBUG | (pkg/util/docker/global.go:40 in GetDockerUtilWithRetrier) | Docker init error: temporary failure in dockerutil, will retry later: Error reading remote info: netip.ParsePrefix("invalid Prefix"): no '/' ``` Root cause: PR #48777 migrated the Docker SDK to `moby/moby` v29 to fix CVE-2026-34040 / CVE-2026-33997. The new `system.Info.DefaultAddressPools[].Base` field is typed as `netip.Prefix`, whose `UnmarshalText` is strict and rejects any string without `/`. Some Docker daemons emit the literal string `"invalid Prefix"` (exactly the output of `netip.Prefix.String()` for the zero/invalid value) for that field, which makes the entire `/info` JSON decode fail. That single decode failure cascaded into: - `DockerUtil` init failure → workloadmeta Docker collector failure → Docker core check failure → missing container/image tags on metrics, traces, logs. - Hostname provider `docker` failure → in containerized environments without an explicit `DD_HOSTNAME`, the agent could refuse to start if other providers (kubelet, EC2/GCE metadata, OS) also failed. - Host metadata (`docker_version`, `docker_swarm`) and host tags (`docker_swarm_node_role`) silently missing. This PR makes the SDK's strict decoding tolerant of the offending field while preserving the strict typing of every other field. Relates to incident #54830. Functionally supersedes #51128 (which patches only the init probe via `Ping`); the two approaches can be discussed and merged into one. ### Describe how you validated your changes - `dda inv agent.build --build-exclude=systemd` — PASS - `dda inv cluster-agent.build` — PASS - `dda inv test --targets=./pkg/util/docker/...` — PASS (30 tests, 3 new in `safe_info_test.go` covering happy path, fallback on `"invalid Prefix"`, and non-decode-error propagation) - `dda inv test --targets=./pkg/util/docker/...,./pkg/collector/corechecks/containers/docker/...,./pkg/util/containers/metrics/docker/...,./comp/core/workloadmeta/collectors/internal/docker/...` — 71/71 PASS - Bazel verification: not run locally (no `bazel` binary on the dev box); BUILD.bazel was updated manually to add `safe_info.go`/`safe_info_test.go` srcs and drop the now-unused `//pkg/util/docker/fake` test dep — CI will validate. ### Additional Notes The fallback's URL construction mirrors the SDK's `getAPIPath` (preserves the configured base path and `cli.ClientVersion()` prefix) so daemons behind reverse proxies that route on `Host` header or `/v<version>/` path receive the request the same way the SDK does. A `log.Debugf` line fires whenever the fallback engages so operators can see when the workaround is active. The match on `"Error reading remote info"` is a string prefix on the SDK's wrapped JSON-decode error. It is stable today (`moby/moby/client@v0.4.1/system_info.go:32`) and unique to JSON-decode failures of `/info`, but is the most fragile part of the patch. If moby ever exposes a typed sentinel for this case, we should switch to `errors.As`/`errors.Is`. Co-authored-by: lenaic.huard <lenaic.huard@datadoghq.com>
…n `/info` `DefaultAddressPools` (#51382) Backport 309b25f from #51235. ___ ### What does this PR do? Adds a tolerant decoder for the Docker daemon's `/info` response in `pkg/util/docker/`, so that daemons emitting invalid CIDRs in `DefaultAddressPools[].Base` no longer break `DockerUtil` and its downstream callers. Concretely: - New helper `safeInfo(ctx, cli)` (`pkg/util/docker/safe_info.go`): tries `cli.Info(...)` first; on the SDK's JSON-decode failure prefix only, reissues `GET /info` via `cli.Dialer()` and decodes into a mirror of `system.Info` where `DefaultAddressPools` is shadowed by `json.RawMessage`, so the strict `netip.Prefix` field stays at zero value and the rest of the struct still parses. - 5 callsites of `cli.Info(ctx, client.InfoOptions{})` switched to `safeInfo(...)`: `ConnectToDocker`, `DockerUtil.GetHostname`, `DockerUtil.GetStorageStats`, `GetMetadata`, `GetTags`. - `host_tags.go` refactored: pure `buildSwarmTags(info system.Info) []string` extracted; `host_tags_test.go` tests it directly without the `client.SystemAPIClient` mock. - `BUILD.bazel` updated: new files added, unused `//pkg/util/docker/fake` test dep removed. - Release note added. ### Motivation [Incident #54830](https://dd.slack.com/archives/C0B55994JGL/p1779448036913569). Reported symptom (from agent debug logs): ``` PROCESS | DEBUG | (pkg/util/hostname/container.go:34 in callContainerProvider) | GetHostname trying provider 'docker' ... PROCESS | DEBUG | (pkg/util/docker/global.go:40 in GetDockerUtilWithRetrier) | Docker init error: temporary failure in dockerutil, will retry later: Error reading remote info: netip.ParsePrefix("invalid Prefix"): no '/' ``` Root cause: PR #48777 migrated the Docker SDK to `moby/moby` v29 to fix CVE-2026-34040 / CVE-2026-33997. The new `system.Info.DefaultAddressPools[].Base` field is typed as `netip.Prefix`, whose `UnmarshalText` is strict and rejects any string without `/`. Some Docker daemons emit the literal string `"invalid Prefix"` (exactly the output of `netip.Prefix.String()` for the zero/invalid value) for that field, which makes the entire `/info` JSON decode fail. That single decode failure cascaded into: - `DockerUtil` init failure → workloadmeta Docker collector failure → Docker core check failure → missing container/image tags on metrics, traces, logs. - Hostname provider `docker` failure → in containerized environments without an explicit `DD_HOSTNAME`, the agent could refuse to start if other providers (kubelet, EC2/GCE metadata, OS) also failed. - Host metadata (`docker_version`, `docker_swarm`) and host tags (`docker_swarm_node_role`) silently missing. This PR makes the SDK's strict decoding tolerant of the offending field while preserving the strict typing of every other field. Relates to incident #54830. Functionally supersedes #51128 (which patches only the init probe via `Ping`); the two approaches can be discussed and merged into one. ### Describe how you validated your changes - `dda inv agent.build --build-exclude=systemd` — PASS - `dda inv cluster-agent.build` — PASS - `dda inv test --targets=./pkg/util/docker/...` — PASS (30 tests, 3 new in `safe_info_test.go` covering happy path, fallback on `"invalid Prefix"`, and non-decode-error propagation) - `dda inv test --targets=./pkg/util/docker/...,./pkg/collector/corechecks/containers/docker/...,./pkg/util/containers/metrics/docker/...,./comp/core/workloadmeta/collectors/internal/docker/...` — 71/71 PASS - Bazel verification: not run locally (no `bazel` binary on the dev box); BUILD.bazel was updated manually to add `safe_info.go`/`safe_info_test.go` srcs and drop the now-unused `//pkg/util/docker/fake` test dep — CI will validate. ### Additional Notes The fallback's URL construction mirrors the SDK's `getAPIPath` (preserves the configured base path and `cli.ClientVersion()` prefix) so daemons behind reverse proxies that route on `Host` header or `/v<version>/` path receive the request the same way the SDK does. A `log.Debugf` line fires whenever the fallback engages so operators can see when the workaround is active. The match on `"Error reading remote info"` is a string prefix on the SDK's wrapped JSON-decode error. It is stable today (`moby/moby/client@v0.4.1/system_info.go:32`) and unique to JSON-decode failures of `/info`, but is the most fragile part of the patch. If moby ever exposes a typed sentinel for this case, we should switch to `errors.As`/`errors.Is`. Co-authored-by: sabrina.lu <sabrina.lu@datadoghq.com>
What does this PR do?
Migrates the Docker SDK dependency from
github.com/docker/dockerv28.5.2+incompatible togithub.com/moby/mobyv29 sub-modules (moby/moby/apiv1.54.1,moby/moby/clientv0.4.0) to fix two security vulnerabilities:Docker Engine v29 restructured its Go modules into separate sub-modules with a new Options/Result API pattern. This PR updates all 55 affected files across the codebase:
github.com/docker/docker/*imports replaced withgithub.com/moby/moby/*equivalentsDockerUtilwrapper adapted to v29 Options/Result method signaturesapi/types/filters.Argstoclient.FiltersContainerJSONBase(flattened),image.Summary.VirtualSize,image.InspectResponse.DockerVersion/ContainerConfigIPAddress(string→netip.Addr),Port(nat.Port→network.Port),ContainerState(string→ typed)libnetwork/resolvconfreplaced with inline implementation (removed from moby/moby in v29)ContainerExec*→Exec*method renames applied in e2e frameworkreplacedirective added to pin the remaining indirectdocker/dockerdependency (from otel-collector-contrib) to the28.xbranch head which includes backported security fixesMotivation
Fix CVE-2026-34040 and CVE-2026-33997 affecting both the agent and cluster-agent binaries.
Jira: CONTINT-5217, CONTINT-5218, CONTINT-5219, CONTINT-5220, VULN-59766, VULN-59767, VULN-59774, VULN-59775
Describe how you validated your changes
dda inv agent.build --build-exclude=systemd— PASSdda inv cluster-agent.build— PASSdda inv test --targets=./pkg/util/docker/...— ALL PASSEDdda inv test --targets=./pkg/collector/corechecks/containers/docker/...— 15/15 PASSEDdda inv test --targets=./pkg/util/containers/metrics/docker/...— ALL PASSEDdda inv test --targets=./comp/core/workloadmeta/collectors/internal/docker/...— 13/13 PASSEDAdditional Notes
Indirect
docker/dockerdependency:github.com/docker/dockerremains as an indirect dependency pulled in transitively byopentelemetry-collector-contrib/dockerobserverand other third-party modules. Areplacedirective pins it to the28.xbranch head (31a1689cb0a1) which includes the same security fixes backported from v29.3.1 (not yet released as a tagged v28.x version). No datadog-agent code directly imports fromdocker/dockeranymore.docker.image.virtual_sizemetric: This metric now reportsimage.Sizeinstead of the removedimage.VirtualSizefield. These values have been identical since Docker API v1.44 (VirtualSizewas already deprecated).