June 18, 2026·4 min read·engineeringdockerattestationsapi

Docker Engine 29.6 makes image attestations queryable

The new attestation endpoint distinguishes missing evidence from unsupported storage and requires an explicit request for statement bodies. Runtime device-limit updates also stop silently ignoring fields.

Docker Engine 29.6.0 adds an endpoint for retrieving image attestations. The June 18 release notes name SLSA provenance and SPDX software bills of materials as examples of the in-toto statements it can retrieve. I care about the query contract because evidence is useful only when an operator can tell what a response actually establishes.

My preference for a multi-stage build ending with a static Go binary in a scratch image makes the final filesystem relatively easy to explain. It does not, by itself, explain how the binary was built. An attestation query can supply evidence for a separate question about the artifact's production. I would keep that question explicit when adding the endpoint to a release process.

The query follows the selected image platform

The API specification shipped with this release defines GET /images/{name}/attestations. The daemon locates attestation manifests that reference the selected platform's image manifest. It then returns information about their statement layers. If no attestations exist for the image, the successful response is an empty array.

Platform selection is therefore part of the evidence request. The parameter accepts a JSON-encoded OCI platform, such as an object identifying Linux and amd64. If the caller omits it, Docker uses the daemon's default host platform. I would supply the intended deployment platform explicitly in a release check so the result does not depend on the machine running the query.

There is a detail that client authors should preserve. The specification represents platform as an array parameter, but the implementation currently accepts only one value. Passing more than one produces an error. The array representation reserves room for later expansion without changing the wire representation. It does not authorize a client to assume that a single request already evaluates every platform in an image index.

For a multi-platform release, I would make the validation record identify each platform examined. A successful query for one platform should not be recorded as evidence for another. This is an implication of the endpoint's selection rules, not a reason to infer anything about the contents of an unqueried manifest.

Statement content is an explicit request

The statement parameter defaults to false. In that mode, the daemon returns the descriptor and predicate type without reading the statement blobs. Setting it to true requests the verbatim statement bodies. A consumer that intends to examine build inputs needs to distinguish the descriptor response from the evidence content it plans to evaluate.

The following request illustrates that distinction using an example image name. It assumes access to the local Engine socket and an image called example-service that the operator has already supplied:

curl --unix-socket /var/run/docker.sock --get   --data-urlencode 'platform={"os":"linux","architecture":"amd64"}'   --data-urlencode 'statement=true'   http://localhost/images/example-service/attestations

The socket and image reference belong to the operator's environment. I would avoid turning this illustration into an installation script. Its purpose is to show the JSON platform encoding and the explicit statement request defined by the release's API.

The optional type parameter filters by predicate-type URI. It may repeat to accept several types, while an omitted filter requests all statements. That gives a client a way to ask for the forms of evidence its policy understands. I would still inspect the returned predicate type before decoding a statement with a type-specific parser.

A retrieval result should remain separate from a policy decision. The endpoint describes attached statements and their contents. An application's release policy must decide which builder and inputs it accepts. I would want that policy to state the expected evidence before treating a response as approval to deploy.

Missing evidence and unsupported storage need different handling

The API specifies an empty array when an image has no attestations. A nonexistent image, or a missing manifest for the requested platform, returns 404. Malformed parameters have a separate 400 response. These distinctions let a client explain whether it asked a valid question about an available image.

The legacy graphdriver image store introduces another case. It does not preserve OCI image indexes, and the endpoint returns 501 because that backend cannot support attestations. I would not translate that response into an empty list. Doing so would hide a storage limitation behind the same result used for an image that has no attached evidence.

This matters for a rollout across existing hosts. Before making the query mandatory, I would check which image backend each host uses. The failure policy should explain whether an unsupported host blocks the release or requires a different evidence retrieval process. An unexplained retry would not change the backend's capabilities.

For troubleshooting, I would retain the selected image reference and platform alongside the response category. That would make an evidence failure actionable without requiring the operator to reconstruct the request from an application log. It would also avoid describing a platform-selection failure as a provenance failure.

Device-limit updates now apply the accepted fields

The same release changes POST /containers/{id}/update for per-device block-I/O settings. The implementation change explains that the API previously accepted five fields but silently ignored them. Those fields cover device weights and per-device read or write limits expressed in bytes or operations per second.

The conversion to containerd resources mapped only the overall block-I/O weight. The fix reuses the device conversion helpers already used during container creation and propagates invalid-device-path errors. According to the change description, the old request could return HTTP 200 without writing the intended cgroup limit.

I would validate a resource update by checking the resulting control, including an application-specific acceptance check where appropriate. That proposed validation follows directly from the failure mode. A successful HTTP response was insufficient evidence that these settings had taken effect.

These two additions improve different operational tasks, but both require a precise account of evidence. For attestations, the client must request the relevant platform and content. For a live resource update, the operator needs confirmation that the requested limit reached the runtime. I would record those checks in the release workflow so an API success does not become a broader claim than its response supports.