278 Commits
Author SHA1 Message Date
Sebastiaan van Stijn 7ec2f1d2d3 httpstatus: simplify distribution error status handling
Remove the redundant ErrorCoder type assertion and let the
recursive call handle unsupported error types.

Make all switch cases return explicitly.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-04 16:05:45 +01:00
Sebastiaan van Stijn 5df4160942 httpstatus: handle missing errdefs HTTP status codes
Add missing mappings for ErrFailedPrecondition (412) and
ErrResourceExhausted (429), aligning with containerd's errhttp
implementation.

Add table-driven tests covering the errdefs mappings, gRPC and
distribution errors, and wrapped and joined errors.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-11-04 16:05:40 +01:00
Jonathan A. Sternberg 48d9ab2412 daemon/server: fill in http request route pattern
Fill in the `Pattern` field on an `http.Request`. This field is filled
out by the standard library's `http.ServeMux` but is not filled in by
`gorilla/mux`. It is used to identify the matching route pattern and is
primarily used for traces and metrics to reduce cardinality on paths
that have variables in the routes so they can be recorded to traces.

The primary result of this change is that HTTP request traces will now
have the name `{method} {route}` rather than only `{method}` so an
invocation of `docker ps` will show up as `GET /containers/json` instead
of just `GET`.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2026-10-21 11:14:04 -05:00
Sebastiaan van Stijn c1ca724d3c daemon/server: use t.Context
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-18 18:28:46 +02:00
Sebastiaan van Stijn c47560390b daemon/server/router/grpc: fix linting for deprecated http2 code
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-09 12:47:44 +02:00
Sebastiaan van Stijn d8f48780e2 Merge pull request #53559 from thaJeztah/import_gddo
daemon/server: import golang/gddo
2026-09-03 18:32:41 +02:00
Sebastiaan van Stijn 67755e0655 Merge pull request #53463 from zhangyoufu/19189-umask
Add umask support
2026-09-03 15:23:16 +02:00
Paweł Gronowski 67288a3c6c Merge pull request #53552 from thaJeztah/logstream_refactor
daemon: logstream: refactor and optimize
2026-09-03 15:13:35 +02:00
Paweł GronowskiandYoufu Zhang 235d2876f8 api: Add container umask configuration
Add HostConfig.Umask and pass it to the OCI process spec for container
entrypoints, exec processes, and healthchecks.

Preserve the configured umask when exec user resolution reconstructs the
OCI User value, so runtimes receive it in the per-exec process spec.

Keep the field aligned with OCI's uint32 representation - raw JSON
clients need to use 18 for octal 0022 for example.

Co-authored-by: Youfu Zhang <zhangyoufu@gmail.com>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-09-03 10:41:23 +02:00
Sebastiaan van Stijn 2dc7a6be4f daemon/server/httputils: fix / suppress linting
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-03 01:18:41 +02:00
Sebastiaan van Stijn acf0989f9c daemon/server/httputils: remove unused code
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-03 01:18:38 +02:00
Sebastiaan van Stijn ac2f240268 daemon/server/httputils: update gddo attribution and documentation
Add a minimal README to document that it is a hard fork of the archived
golang/gddo repository, and add Go provenance to NOTICE.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-03 01:18:17 +02:00
Sebastiaan van Stijn a80fcadb91 daemon/server: import golang/gddo
Import golang/gddo at commit 20d68f94ee1f7547de2b1c68627253df20c8d45e
into daemon/server/httputils/internal/httputil.

The upstream repository was archived in 2021. Its history was filtered
to remove repository-specific CI and project files and rewritten to its
new location.

Strategy taken:

    # install filter-repo (https://github.com/newren/git-filter-repo/blob/main/INSTALL.md)
    brew install git-filter-repo

    cd ~/projects

    # create a temporary clone of gddo
    git clone --single-branch --branch master --no-tags https://github.com/golang/gddo.git tmp_gddo

    cd tmp_gddo

    git rev-parse HEAD
    20d68f94ee1f7547de2b1c68627253df20c8d45e

    git filter-repo --analyze

    git filter-repo \
        --path httputil/negotiate.go \
        --path httputil/negotiate_test.go \
        --path httputil/header/header.go \
        --path httputil/header/header_test.go \
        --path LICENSE \
        --path-rename httputil/:daemon/server/httputils/internal/httputil/ \
        --path-rename LICENSE:daemon/server/httputils/internal/httputil/LICENSE \
        --prune-empty always \
        --prune-degenerate always

    # go to the target github.com/moby/moby repository
    cd ~/projects/moby

    # create a branch to work with
    git checkout -b import_gddo

    # add the temporary repository as an upstream and make sure it's up-to-date
    git remote add tmp_gddo ~/projects/tmp_gddo
    git fetch --no-tags tmp_gddo master

    # merge the upstream code
    git merge --allow-unrelated-histories --no-ff --signoff -S tmp_gddo/master

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-03 01:17:07 +02:00
Sebastiaan van Stijn 36f51dfaa9 daemon/server/httputils: add contentencoding package
Add a small wrapper around gddo's NegotiateContentEncoding utility
with a signature tailored to our use, accepting just the request
headers instead of the whole request.

This keeps content-encoding negotiation behind an internal API,
similar to the existing contenttype package, and prepares for
internalising the gddo implementation without changing callers.

Add tests covering explicit encodings, wildcard matching, quality
values, identity encoding, and the case where no encoding is
acceptable.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-03 00:00:37 +02:00
Sebastiaan van Stijn 02d8222552 daemon: logstream: skip formatting discarded messages
Select the output stream before constructing the log message, and skip
messages for disabled or unknown streams immediately.

This avoids timestamp formatting, attribute sorting and escaping, and buffer
allocation for messages that would not be written.

For messages that don't require additional formatting, write the original
message payload directly to the selected stream.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-02 14:55:18 +02:00
Sebastiaan van Stijn feb2c10ea7 daemon: logstream: simplify log message construction
Build log messages from left to right, appending optional timestamps and
attributes before the log payload.

Avoid allocating and copying the log payload when no additional formatting
is requested. When formatting is needed, preallocate the output buffer using
the known message and timestamp sizes, with a small per-attribute estimate
to reduce reallocations while appending details.

Replace the custom sort.Interface implementation for log attributes with
slices.SortFunc, and append encoded attributes directly to the log buffer
instead of constructing an intermediate byte slice.

This preserves the existing output format while simplifying message
construction and reducing unnecessary allocations.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-02 14:55:18 +02:00
Sebastiaan van Stijn 12821ed0d4 daemon: logstream: add benchmark
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-09-02 14:51:21 +02:00
Paweł Gronowski 98d4cd6551 daemon: Pass context through container kill operations
Drop cancellation at the kill boundary because killing starts
irreversible task and cleanup work that must finish after request
cancellation.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-07-27 19:11:36 +02:00
Paweł Gronowski 99c1a9c778 daemon: Add configurable default container stop timeout
A container that defines no stop timeout of its own always got 10
seconds on Linux, or 30 on Windows, to shut down before being killed.
The value was a constant in the container package, so operators who
wanted a different grace period had to pass `--stop-timeout` on every
container.

Add a `default-stop-timeout` daemon flag and configuration file option
that supplies that fallback. Stopping a container, killing it, and
computing the daemon shutdown timeout take the value from the daemon
configuration when the container has no timeout of its own, so an
explicit per-container timeout still wins and the container
configuration itself stays untouched. The option can be reloaded, and
negative values are rejected.

mergo cannot tell an unset option from a zero value, so a configured
timeout of `0`, meaning "kill immediately", would be replaced by the
non-zero flag default while merging. Remember whether the
configuration file set the option, and restore its value after the
merge.

`ContainerConfig.StopTimeout` in the API documentation no longer
claims a fixed default of 10 seconds, because the fallback is now
whatever `default-stop-timeout` holds.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-07-27 14:15:55 +02:00
Sebastiaan van Stijn 74364ae3d2 daemon/server: fix perfsprint linting
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-07-06 15:36:17 +02:00
Paweł Gronowski dc97f25cbf daemon/router: Gate ContainerUpdate blkio device fields by API version
ContainerUpdate only starts applying per-device blkio settings in the
current API version.

The fields existed in the Go request type before that because it shares
`container.Resources` with other endpoints, but they were not documented
as supported for container update and older daemons ignored them.

Clear these fields when handling requests for older API versions so
clients pinned to those versions keep the previous behavior, while v1.55
clients can use the newly supported fields.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-06-12 15:52:31 +02:00
Paweł Gronowski 5eda928bb8 Merge pull request #52636 from smerkviladze/add-attestation-statements
image: expose in-toto attestation statements via the API
2026-06-12 15:49:34 +02:00
Sopho Merkviladze 0b2c3780be api: declare ImageAttestations platform and type as repeatable
Both query parameters are now collectionFormat: multi arrays in the
swagger so they can accept multiple values later without an API
version bump. The server still operates on a single platform and
rejects requests passing more than one; type is read directly as a
list of repeated values instead of a comma-separated string.

Signed-off-by: Sopho Merkviladze <smerkviladze@mirantis.com>
2026-06-12 16:20:52 +04:00
Sopho Merkviladze a0b6dbc2fc api: add GET /images/{name}/attestations endpoint
Add a new Engine API endpoint that returns the in-toto attestation
statements attached to an image for a given platform. The endpoint
locates the attestation manifest(s) referencing the requested platform's
image manifest, enumerates the statement layers, and returns each
layer's OCI descriptor (including media type, digest, size, and
annotations) together with its in-toto predicate type.

Query parameters:
  - platform: JSON-encoded OCI platform; defaults to the daemon's host
    platform if omitted.
  - type: comma-separated list of in-toto predicate type URIs; if
    omitted, all statements are returned.
  - statement: boolean, defaults to false. When true, the daemon reads
    each matching statement blob and includes the verbatim in-toto JSON
    in the response. When false (or omitted), statement blobs are not
    read and the Statement field is absent from each entry.

The manifest-chain walk (locating the platform image manifest and its
associated attestation manifest) is delegated to policy-helpers'
image.ResolveSignatureChain so that moby and BuildKit agree on how to
interpret the attestation storage format. The statement-layer iteration
and blob reading is inlined: when statement bodies are requested it
fails fast on the first unreadable blob and reads matching blobs
eagerly into memory; otherwise statement-layer blobs are never read
from the content store.

The endpoint is implemented for the containerd image store. The legacy
graphdriver store returns errdefs.NotImplemented (HTTP 501).

Signed-off-by: Sopho Merkviladze <smerkviladze@mirantis.com>
2026-06-12 13:40:58 +04:00
Akihiro Suda efe6156e19 daemon: allow RawSysInfo to return an error
Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
2026-06-11 17:39:03 +09:00
Sebastiaan van Stijn 91ae7ea8c8 dockerversion: un-export UAStringKey, add WithUpstreamUserAgent
Add a WithUpstreamUserAgent utility instead of exporting the context-key
used.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-05-14 15:29:35 +02:00
Sebastiaan van Stijn d92a8c97de container/logs: add support for JSON streams (experimental)
This adds support for streaming logs as JSON stream either through an
"Accept" header ("application/jsonl", "application/x-ndjson", or
"application/json-seq"), or through a `format=json` query variable.

By default log messages are included as UTF-8 encoded strings, which should
work for regular logs, but can be lossy.

```bash
docker rm -fv my-container3
docker run \
    -qit \
    --name my-container3 \
    --label=labelA=foo \
    --label=labelB=bar \
    --log-opt labels=labelA,labelB \
    ubuntu bash
```

Inside the container:

```bash
root@b36bfcd439e9:/# echo {1..9} && exit
1 2 3 4 5 6 7 8 9
exit
```

With the message encoded as utf-8;

```bash
curl -s --unix-socket /var/run/docker.sock 'http://localhost/v1.54/containers/my-container3/logs?stdout=1&stderr=1&format=json' | jq .
{
  "Line": "\u001b[?2004h\u001b]0;root@1065b85dd167: /\u0007root@1065b85dd167:/# \u001b[7mecho {1..9} && exit\u001b[27m\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\becho {1..9} && exit\r\n",
  "Source": "stdout",
  "Timestamp": "2026-02-20T15:39:01.083531419Z"
}
{
  "Line": "\u001b[?2004l\r1 2 3 4 5 6 7 8 9\r\n",
  "Source": "stdout",
  "Timestamp": "2026-02-20T15:39:01.088152377Z"
}
{
  "Line": "exit\r\n",
  "Source": "stdout",
  "Timestamp": "2026-02-20T15:39:01.088183336Z"
}
```

With `details` enabled;

```bash
curl -s --unix-socket /var/run/docker.sock 'http://localhost/v1.54/containers/my-container3/logs?stdout=1&stderr=1&format=json&details=1' | jq .
{
  "Line": "\u001b[?2004h\u001b]0;root@1065b85dd167: /\u0007root@1065b85dd167:/# \u001b[7mecho {1..9} && exit\u001b[27m\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\becho {1..9} && exit\r\n",
  "Source": "stdout",
  "Timestamp": "2026-02-20T15:39:01.083531419Z",
  "Attrs": [{"Key": "labelA","Value": "foo"},{"Key": "labelB","Value": "bar"}]
}
{
  "Line": "\u001b[?2004l\r1 2 3 4 5 6 7 8 9\r\n",
  "Source": "stdout",
  "Timestamp": "2026-02-20T15:39:01.088152377Z",
  "Attrs": [{"Key": "labelA","Value": "foo"},{"Key": "labelB","Value": "bar"}]
}
{
  "Line": "exit\r\n",
  "Source": "stdout",
  "Timestamp": "2026-02-20T15:39:01.088183336Z",
  "Attrs": [{"Key": "labelA","Value": "foo"},{"Key": "labelB","Value": "bar"}]
}
```

Using `Accept` header instead of the `format=json` query parameter;

```bash
curl -s -H 'Accept: application/json-seq' --unix-socket /var/run/docker.sock 'http://localhost/v1.54/containers/my-container3/logs?stdout=1&stderr=1' | jq .
{
  "Line": "\u001b[?2004h\u001b]0;root@1065b85dd167: /\u0007root@1065b85dd167:/# \u001b[7mecho {1..9} && exit\u001b[27m\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\becho {1..9} && exit\r\n",
  "Source": "stdout",
  "Timestamp": "2026-02-20T15:39:01.083531419Z"
}
{
  "Line": "\u001b[?2004l\r1 2 3 4 5 6 7 8 9\r\n",
  "Source": "stdout",
  "Timestamp": "2026-02-20T15:39:01.088152377Z"
}
{
  "Line": "exit\r\n",
  "Source": "stdout",
  "Timestamp": "2026-02-20T15:39:01.088183336Z"
}
```

Metadata about partial messages is included (except for the json-file logging
driver, which doesn't use it currently);

The partial messages also don't get a trailing newline, except for the last entry;

```bash
docker run --name bar alpine sh -c 'head -c 20000 /dev/zero | tr "\0" A; echo'
curl -s --unix-socket /var/run/docker.sock 'http://localhost/v1.54/containers/bar/logs?stdout=1&stderr=1&format=json'
{"Line":"AAAAAAAAAA....AAAA","Source":"stdout","Timestamp":"2026-02-21T21:45:47.075093919Z"}
{"Line":"AAAAAAAAAAAAAAAA\n","Source":"stdout","Timestamp":"2026-02-21T21:45:47.075093919Z"}
```

And for logging drivers other than the `json-file`, we have information about
partials in a slightly more structured format:

```bash
docker run --name baz --log-driver=local alpine sh -c 'head -c 20000 /dev/zero | tr "\0" A; echo'
curl -s --unix-socket /var/run/docker.sock 'http://localhost/v1.54/containers/baz/logs?stdout=1&stderr=1&format=json'
{"Line":"AAAAAAAAAA....ASAA","Source":"stdout","Timestamp":"2026-02-21T21:49:42.453363584Z","LogMetaData":{"Last":false,"ID":"46a9188a552a068c1d63a5096b7335788aea7e430817f3d2d83c5fd90c6365ef","Ordinal":1}}
{"Line":"AAAAAAAAAAAAAAAA\n","Source":"stdout","Timestamp":"2026-02-21T21:49:42.453363584Z","LogMetaData":{"Last":true,"ID":"46a9188a552a068c1d63a5096b7335788aea7e430817f3d2d83c5fd90c6365ef","Ordinal":2}}
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-05-07 21:40:52 +02:00
Vedant Madane 70ac493e97 server/router/build: replace output buffering workaround with EnableFullDuplex
The wrapOutputBufferedUntilRequestRead helper was added as a workaround
for Go not supporting full-duplex HTTP/1 responses (golang/go#15527,
golang/go#22209). Since Go 1.21, the standard library ships
http.ResponseController.EnableFullDuplex which tells the server that
the handler will interleave reads and writes, making the buffering
wrap unnecessary.

Replace the workaround with a single EnableFullDuplex call and remove
the helper types (wcf, rcNotifier, flusher, nopFlusher) that were only
used by the old path.

Fixes #51209

Signed-off-by: Vedant Madane <vedant.madane@gmail.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-05-07 01:34:39 +02:00
Ogulcan Aydogan 735d17e1a5 fix: return 400 instead of 500 for invalid request parameters
Wrap plain errors with errdefs.InvalidParameter so the API returns
HTTP 400 instead of 500 for user input errors:

- image export: invalid reference format
- container stop/list: invalid integer for t/limit params
- plugin privileges: invalid reference format
- plugin enable: invalid integer for timeout param
- service/task logs: missing stdout/stderr stream selection

Fixes #48173

Signed-off-by: Ogulcan Aydogan <ogulcanaydogan@hotmail.com>
2026-04-01 18:10:28 +02:00
Paweł Gronowski b77af956b1 Merge pull request #52094 from thaJeztah/backend_log_opts
daemon/server: improve parsing timestamps and move it to the router
2026-04-01 13:17:42 +02:00
Sebastiaan van Stijn b24c8272e5 go fix "omitempty"
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-25 23:24:53 +01:00
Sebastiaan van Stijn 405a787917 daemon/server: don't log context cancelation as error
The [httpstatus.FromError] utility currently maps context cancellation and
deadline errors to a 500 ("internal server error"). As a result, a client
disconnecting would produce an error log:

    ERRO[2026-03-11T11:54:39.872784425Z] Handler for POST /v1.54/images/create returned error: failed to resolve reference "docker.io/library/alpine:latest": failed to do request: Head "https://registry-1.docker.io/v2/library/alpine/manifests/latest": context canceled

This patch:

- Checks for context-cancelation on the context, and instead logs an "INFO"
  message. For tracing/OTEL, it produces a "499" status code, which is non-
  standard, but commonly accepted (and used by NGINX, CloudFront). Given that
  no client should be listening anymore, it omits an actual response.
- Adds more structured logs, to align with the logs we produce in our Debug
  middleware.

With this patch:

    INFO[2026-03-11T16:43:55.567731845Z] API listen on /var/run/docker.sock
    INFO[2026-03-11T16:43:58.152254638Z] fetch failed                                  error="failed to do request: Head \"https://registry-1.docker.io/v2/library/alpine/manifests/latest\": context canceled" host=registry-1.docker.io
    INFO[2026-03-11T16:43:58.152608805Z] Cancel with lease, leased resources will remain until expiration  expires_at="2026-03-12 00:43:57.965872638 +0000 UTC m=+28803.424778128" lease=965878679-Q_SJ
    INFO[2026-03-11T16:43:58.152917138Z] request cancelled by client                   error="failed to resolve reference \"docker.io/library/alpine:latest\": failed to do request: Head \"https://registry-1.docker.io/v2/library/alpine/manifests/latest\": context canceled" method=POST module=api request-url="/v1.54/images/create?fromImage=docker.io%2Flibrary%2Falpine&tag=latest" status=499 vars="map[version:1.54]"

Note some duplication in logs, as some logs are produced by containerd code.

[httpstatus.FromError]: https://github.com/moby/moby/blob/v2.0.0-beta.7/daemon/server/httpstatus/status.go#L44-L45

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-11 17:45:24 +01:00
Paweł Gronowski 2fa6029be4 network/connect: Support MacAddress
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-03-05 14:11:08 +01:00
Sebastiaan van Stijn f401a9678b daemon/server/backend: ContainerLogsOptions: use time.Time for since, until
Move parsing the wire format to the router instead of in the daemon, so
that a strong type can be used internally.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-03 21:53:23 +01:00
Sebastiaan van Stijn 210cdcbd46 daemon/server/router: fix "no stream selected" error and status
Tweak the wording, and make sure we return a 400 status, not a 500

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-03 21:53:23 +01:00
Sebastiaan van Stijn 568312cb85 daemon/internal/timestamp: replace ParseTimestamps with ParseUnixTimestamp
Return a time.Time instead of splitting to seconds/nanoseconds.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-03 21:53:23 +01:00
Sebastiaan van Stijn 8f8b23c729 daemon: fix some untyped "invalid parameter" errors
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-03-03 20:30:24 +01:00
Paweł Gronowski 11d1267e88 Merge pull request #52030 from crazy-max/image-list-identity
image: add opt-in identity field to image list API for containerd backend
2026-02-27 18:31:01 +00:00
Sebastiaan van Stijn 52dc67c0df Merge pull request #52067 from cpuguy83/restore_older_apis
Add compatibility with API v1.40 and up
2026-02-27 18:07:02 +01:00
CrazyMax 6d133c5ec6 image: add opt-in identity support to image list API
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2026-02-27 16:35:31 +01:00
Sebastiaan van Stijn a49c2f66db Merge pull request #52083 from thaJeztah/negotiate
api: improve, fix content-negotiation for /events endpoint
2026-02-24 19:46:33 +01:00
Sebastiaan van Stijn 2283e0351c daemon/server/httputils/logstream: Write: tidy-up stream handling
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-02-24 14:18:38 +01:00
Sebastiaan van Stijn b55842c85f daemon/server/httputils/logstream: Write: handle context cancellation
The context arg was kept when extracting the code in 1044093bb0
but it was not handled; let's wire it up.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-02-24 14:18:38 +01:00
Sebastiaan van Stijn d593a7b427 daemon/server/httputils: move WriteLogStream to its own package
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-02-24 14:18:38 +01:00
Sebastiaan van Stijn 35fdcb802c api: improve, fix content-negotiation for /events endpoint
Commits df506c107e and aef5d996ce
fixed the content-type advertised by the `/events` endpoint, and added content
negotiation as an "opt-in" by clients.

A fallback / default value was added to keep the old (`application/json`)
content type, however, some clients may send `*/*` as a default, which
would considered as "opt-in" in the negotiation, and pick the first "offer"
(`application/jsonl`) instead of the fallback.

On docker 28.x and lower, omitting an `Accept` header, or sending `*/*`
would produce the `application/json` content-type:

```
curl -sS -D - --unix-socket /var/run/docker.sock 'http://localhost/v1.50/events?until=1' | grep 'Content-Type'

curl -sS -D - -H 'Accept: */*' --unix-socket /var/run/docker.sock 'http://localhost/v1.50/events?until=1' | grep 'Content-Type'
```

On docker 29.x, a missing accept header, or a `*/*` would use the new content-type,
not the previous default;

```
curl -sS -D - --unix-socket /var/run/docker.sock 'http://localhost/v1.50/events?until=1' | grep 'Content-Type'

curl -sS -D - -H 'Accept: */*' --unix-socket /var/run/docker.sock 'http://localhost/v1.50/events?until=1' | grep 'Content-Type'
```

With this patch, the default depends on the API version, and we only
override the content-type if there's a match with any of the types
set in the `Accept` header, ignoring wildcards (`*/*`) that are sent
as default by some clients, such as cURL or `docker-py`;

```
curl -sS -D - --unix-socket /var/run/docker.sock 'http://localhost/v1.51/events?until=1' | grep 'Content-Type'

curl -sS -D - -H 'Accept: */*' --unix-socket /var/run/docker.sock 'http://localhost/v1.51/events?until=1' | grep 'Content-Type'

curl -sS -D - --unix-socket /var/run/docker.sock 'http://localhost/v1.52/events?until=1' | grep 'Content-Type'
Content-Type: application/jsonl

curl -sS -D - -H 'Accept: */*' --unix-socket /var/run/docker.sock 'http://localhost/v1.52/events?until=1' | grep 'Content-Type'

curl -sS -D - -H 'Accept: application/json-seq' --unix-socket /var/run/docker.sock 'http://localhost/v1.50/events?until=1' | grep 'Content-Type'
```

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-02-23 13:15:52 +01:00
Sebastiaan van Stijn dff0d87430 daemon/server/httputils: contenttype package and MatchAcceptStrict utility
This allows negotiating the content-type without wildcard-matching.
In most of our uses, we want to provide the best match that the
client accepts, but have to avoid picking the first match if a
client would send "*/*" (or, e.g., "application/*").

For example, the events endpoint added support for JSON-stream
content types, but older API versions unconditionally returned
"application/json". Clients sending "*/*" (such as docker/docker-py)
would now get a different content type as before.

For convenience, also adding a wrapper for the gddo NegotiateContentType
utility with a slightly different signature (accepting just the headers
instead of the whole request).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-02-23 13:13:39 +01:00
Brian Goff f96921e5e5 api: lower default minimum API version to v1.40
Extend the previous commit to support API v1.40 (Docker 19.03) by
lowering defaultMinAPIVersion and client MinAPIVersion from 1.41 to
1.40.

Reject container create requests that set the HostConfig.Capabilities
field on API v1.40, since this daemon can no longer honor it. The field
was removed before API v1.41 (24f173a003) and the Go type no longer
includes it, so without this check the field would be silently dropped.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2026-02-19 14:54:56 -08:00
Brian Goff e2fad779f7 api: restore support for API v1.41, v1.42, and v1.43
Lower the default minimum API version from v1.44 to v1.41, restore
VirtualSize in image list and disk usage responses for API < 1.44, and
add version-gated skips for integration tests that need newer APIs.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2026-02-19 14:54:44 -08:00
Paweł Gronowski 45aee529d2 Merge pull request #51862 from thaJeztah/identity_version_gate
inspect: add API-version gate for image identity
2026-01-26 17:08:02 +00:00
Sebastiaan van Stijn 5961616a77 daemon/server/backend: ContainerListOptions: remove unused Latest field
The `--latest` option was implemented in [moby@b295239] as a CLI shortcut
for `--last=1`.

However, as part of a large refactor of the client in [moby@d05aa41], a
`ContainerListOptions` type was introduced, which contained a `Latest`
field.

This field was never used, as the `Latest` option was handled in the CLI,
and had no corresponding option for the API (other than `limit`).

This patch removes the field from the backend, because it's not used. Removal
from the client will require a deprecation, and will be handled separately.

[moby@b295239]: https://github.com/moby/moby/commit/b295239de20f15620ee4149fcc7c13ce461cdaac
[moby@d05aa41]: https://github.com/moby/moby/commit/d05aa418b0466553a24d42896f99176cfa29765f

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2026-01-20 12:44:58 +01:00