Compare commits

...

290 Commits

Author SHA1 Message Date
Paweł Gronowski
3f46cadf39 Merge pull request #49805 from thaJeztah/vendor_goarchive
vendor: github.com/moby/go-archive v0.1.0
2025-04-16 12:07:48 +00:00
Sebastiaan van Stijn
b57d41c4bf Merge pull request #49799 from thaJeztah/apparmor_cleanups
profiles/apparmor: add some optimisations and tests
2025-04-16 13:21:25 +02:00
Sebastiaan van Stijn
29edd17909 Merge pull request #49815 from z63d/docs-api-image-tarball-format
docs/api: update image tarball format
2025-04-16 13:05:21 +02:00
Sebastiaan van Stijn
fd550344b1 vendor: github.com/moby/go-archive v0.1.0
full diff: https://github.com/moby/go-archive/compare/21f3f3385ab7...v0.1.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-16 13:00:13 +02:00
Paweł Gronowski
2834da861b Merge pull request #49814 from thaJeztah/initlayer_rm_idtools
daemon/initlayer: Setup: remove uses of idtools.Identity
2025-04-16 09:42:35 +00:00
Paweł Gronowski
1f43ad3a16 Merge pull request #49782 from thaJeztah/container_rm_idtools
container: Container.SetupWorkingDirectory: remove use of pkg/idtools
2025-04-16 09:41:35 +00:00
Kaita Nakamura
b8067d159f docs/api: update image tarball format
Signed-off-by: Kaita Nakamura <kaita.nakamura0830@gmail.com>
2025-04-16 18:02:08 +09:00
Sebastiaan van Stijn
a38ca9a548 daemon/initlayer: Setup: remove uses of idtools.Identity
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-16 09:58:24 +02:00
Rob Murray
9c9a6cb941 Merge pull request #49812 from robmry/endpoint_count_for_downgrade
Store an endpoint count for networks, for downgrade
2025-04-15 21:59:50 +01:00
Rob Murray
380ded6309 Store an endpoint count for networks, for downgrade
Since commit 51d7f95 ("libnet: remove struct endpointCnt") an
endpoint count for networks has not been persisted.

But, on downgrade to a version older than that commit, the
missing field caused daemon startup to fail.

So, create the count in the store - it only needs to exist, it's
no longer maintained as a count of endpoints. On downgrade, the
count is probably zero anyway (the daemon is stopped), but the
older daemon fixes it up on startup if necessary.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-15 17:59:34 +01:00
Sebastiaan van Stijn
c58a765707 Merge pull request #49809 from crazy-max/buildkit-0.21.0
vendor: update buildkit to v0.21.0
2025-04-15 18:20:39 +02:00
CrazyMax
ae0331d8f5 vendor: update buildkit to v0.21.0
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2025-04-15 17:04:25 +02:00
Paweł Gronowski
b2d06baf9b Merge pull request #49806 from robmry/missing_firewaller_error_check
bridge: Add a missing error check for firewaller setup
2025-04-15 13:06:27 +00:00
Rob Murray
57bf7a8c70 bridge: Add a missing error check for firewaller setup
It got lost in commit 29e0db2 ("Factor out top-level iptables
setup into its own object").

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-15 12:05:10 +01:00
Paweł Gronowski
bb8fcf3031 Merge pull request #49802 from vvoland/TestStopContainerWithTimeout-noparallel
integration/TestStopContainerWithTimeout: Attempt to fix flakiness
2025-04-14 15:19:25 +00:00
Paweł Gronowski
c49ce64514 integration/TestStopContainerWithTimeout: Attempt to fix flakiness
Temporarily remove Parallel.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-04-14 12:31:52 +02:00
Akihiro Suda
aa51a79ef9 Merge pull request #49800 from thaJeztah/seccomp_stdlib
profiles/seccomp: use stdlib for asserting, remove "// import" comments
2025-04-13 00:51:57 +09:00
Sebastiaan van Stijn
ecde7b9b7c Merge pull request #49797 from jsternberg/buildkit-rc2
vendor: github.com/moby/buildkit v0.21.0-rc2
2025-04-12 14:25:17 +02:00
Sebastiaan van Stijn
7eda35fd05 profiles/apparmor: IsLoaded: optimize
- Use a bufio.Scanner to read the profiles
- Use strings.Cut

Before/After:

    BenchmarkIsLoaded-10  2258	    508049 ns/op    244266 B/op    10004 allocs/op
    BenchmarkIsLoaded-10  5680	    208703 ns/op      4264 B/op	       4 allocs/op

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-12 13:34:13 +02:00
Sebastiaan van Stijn
0462b5e318 profiles/apparmor: add BenchmarkIsLoaded
go test -bench=. ./profiles/apparmor/
    goos: linux
    goarch: arm64
    pkg: github.com/docker/docker/profiles/apparmor
    BenchmarkIsLoaded-10    	    2258	    508049 ns/op	  244266 B/op	   10004 allocs/op
    PASS
    ok  	github.com/docker/docker/profiles/apparmor	1.210s

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-12 13:34:13 +02:00
Sebastiaan van Stijn
b23d267cb5 profiles/apparmor: add basic unit-test for IsLoaded
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-12 13:34:12 +02:00
Sebastiaan van Stijn
0dd5959eeb profiles/apparmor: InstallDefault: slight cleanup and optimization
The existing code was more complicated than needed. By default, the daemon
runs "unconfined", but we try to detect the current profile that's set.
When failing to do so (error, or detected profile is empty), we assume
the default ("unconfined").

This patch simplifies the logic;

- Set the default ("unconfined")
- Only update the default when we successfully found the current profile
  (no error occurred, and the profile is not empty).

While updating, also;

- Replaced use of `strings.SplitN` for `strings.Cut`, which is more
  efficient, and doesn't allocate.
- Move constructing the profileData closer to where it's used.
- Remove intermediate var.
- Combine defers and change the order (close file first, before removing),
  and suppress errors to keep linters happy.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-12 13:34:12 +02:00
Sebastiaan van Stijn
0bb761698c profiles/apparmor: loadprofile: fix double command in error message
`exec.Cmd.Path` already contains the command that was executed, so we
were printing the command twice. However, `exec.Cmd` implements a stringer
interface, which provides a readable version of the command that was
executed, so use that instead. While updating, lso change backticks in
the error for regular quotes.

Before:

    running `/usr/sbin/apparmor_parser apparmor_parser -Kr /no/such/file` failed with output: Cache read/write disabled: interface file missing. (Kernel needs AppArmor 2.4 compatibility patch.)
    Warning: unable to find a suitable fs in /proc/mounts, is it mounted?
    Use --subdomainfs to override.

    error: exit status 1

After:

    running '/usr/sbin/apparmor_parser -Kr /no/such/file' failed with output: Cache read/write disabled: interface file missing. (Kernel needs AppArmor 2.4 compatibility patch.)
    Warning: unable to find a suitable fs in /proc/mounts, is it mounted?
    Use --subdomainfs to override.

    error: exit status 1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-12 13:34:12 +02:00
Sebastiaan van Stijn
8e1c366773 profiles/apparmor: remove "// import" comments
We are considering moving the apparmor profile to a separate module,
so removing these comments in preparation. These comments are ignored
already when building in go module mode, so have little benefits.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-12 13:34:12 +02:00
Sebastiaan van Stijn
1fa6a46c5d profiles/seccomp: remove "// import" comments
We are considering moving the seccomp profile to a separate module,
so removing these comments in preparation. These comments are ignored
already when building in go module mode, so have little benefits.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-12 10:46:03 +02:00
Sebastiaan van Stijn
89604f1df1 profiles/seccomp: use stdlib for asserting
We are considering moving the seccomp profile to a separate module,
so reducing the list of dependencies for this package.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-12 10:26:10 +02:00
Jonathan A. Sternberg
14623770e1 vendor: github.com/moby/buildkit v0.21.0-rc2
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2025-04-11 14:02:47 -05:00
Paweł Gronowski
250792c1a5 Merge pull request #49795 from thaJeztah/revert_info_changes
Revert "API: /info: remove BridgeNfIptables, BridgeNfIp6tables fields"
2025-04-11 13:17:24 +00:00
Sebastiaan van Stijn
eacbbdeec6 Revert "API: /info: remove BridgeNfIptables, BridgeNfIp6tables fields"
This reverts commit 5d2006256f, which
caused some issues in the docker/cli formatting code that needs some
investigating.

Let's (temporarily) revert this while we look what's wrong.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-11 14:47:10 +02:00
Paweł Gronowski
73520a5ab7 Merge pull request #49793 from vvoland/cut-api
docs/api: add documentation for API v1.49
2025-04-11 11:40:21 +00:00
Paweł Gronowski
36f87754c2 Merge pull request #49794 from vvoland/update-authors
Update AUTHORS
2025-04-11 11:40:06 +00:00
Paweł Gronowski
ece7e02b86 Update AUTHORS
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-04-11 13:08:52 +02:00
Paweł Gronowski
adb9e9135a docs/api: add documentation for API v1.49
Copy the swagger / OpenAPI file to the documentation. This is the API
version used by the upcoming v28.1.0 release.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-04-11 13:01:02 +02:00
Paweł Gronowski
f3d6830d27 Merge pull request #49783 from thaJeztah/deprecate_bridgenfip_fields
API: /info: remove BridgeNfIptables, BridgeNfIp6tables fields
2025-04-11 10:46:59 +00:00
Paweł Gronowski
cdad178d02 Merge pull request #49789 from akerouanton/trace-containerCreate-labels
daemon: containerCreate, containerStart: add filtered labels to OTel span
2025-04-11 10:34:02 +00:00
Paweł Gronowski
fb2983ab0d Merge pull request #49677 from vvoland/integration-cli-bump-cli
integration-cli: Update default CLI version to v18.06.3-ce
2025-04-11 10:32:36 +00:00
Sebastiaan van Stijn
a6928fd396 Merge pull request #49787 from thaJeztah/bump_registry
Dockerfile: update registry to v3.0.0
2025-04-10 22:13:58 +02:00
Sebastiaan van Stijn
511cd1c0a7 Merge pull request #49785 from thaJeztah/fix_debug_logs
api/server/middleware: fix debug-logs missing form-data
2025-04-10 21:54:00 +02:00
Sebastiaan van Stijn
e2b95a9525 Merge pull request #49770 from dmcgowan/containerd-registry-error-handling
Add registry error handling for push and pull
2025-04-10 21:32:56 +02:00
Albin Kerouanton
099d3ee008 daemon: containerStart: add filtered labels to OTel span
Like for containerCreate, filter the list of container labels based on
`DOCKER_OTEL_INCLUDE_CONTAINER_LABEL_ATTRS` and put that list in the
OTel span.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-10 19:12:25 +02:00
Albin Kerouanton
0c5e816638 daemon: trace containerCreate
This commit adds a new OTel span to `(*Daemon).containerCreate()` and
puts filtered container labels in the span attributes.

The filter is based on a comma-separated list of labels provided through
the `DOCKER_OTEL_INCLUDE_CONTAINER_LABEL_ATTRS` environment variable.
This label might be removed at any point in time if we figure out a
better way to filter labels, or if that span becomes unecessary.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-10 19:12:25 +02:00
Rob Murray
3fc5bfd565 Merge pull request #49778 from robmry/fix_delete_legacy_link
Fix removal of legacy links
2025-04-10 15:16:00 +01:00
Sebastiaan van Stijn
f96dc9d1a5 Dockerfile: update registry to v3.0.0
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-10 15:54:11 +02:00
Rob Murray
4d35864c3d Fix removal of legacy links
It's possible to remove a legacy link from running containers.
When that happens, the Sandbox's Endpoints are removed and
re-added.

Since commit 65120d5 ("Create bridge veth in container netns")
the veth device has been created in the container's netns. When
that happens, a flag is set on the Endpoint to note that it
does not need to be moved into the netns.

But, during the Leave/Join (Sandbox.Refresh) the veth is moved
out of the netns. So, clear the flag during the Leave, to note
that it needs to be moved back in during the Join.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-10 14:22:40 +01:00
Sebastiaan van Stijn
5d2006256f API: /info: remove BridgeNfIptables, BridgeNfIp6tables fields
The `BridgeNfIptables` and `BridgeNfIp6tables` fields in the
`GET /info` response were deprecated in API v1.48, and are now omitted
in API v1.49.

With this patch, old API version continue to return the field:

    curl -s --unix-socket /var/run/docker.sock http://localhost/v1.48/info | jq .BridgeNfIp6tables
    false

    curl -s --unix-socket /var/run/docker.sock http://localhost/v1.48/info | jq .BridgeNfIptables
    false

Omitting the field in API v1.49 and above

    curl -s --unix-socket /var/run/docker.sock http://localhost/v1.49/info | jq .BridgeNfIp6tables
    null

    curl -s --unix-socket /var/run/docker.sock http://localhost/v1.49/info | jq .BridgeNfIptables
    null

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-10 14:26:42 +02:00
Sebastiaan van Stijn
499e15d4ab api/server/middleware: fix debug-logs missing form-data
This was introduced in c817ea2159, but overlooked
that the logs were now produced before (for POST requests) the form-data was
handled and added to the "fields" variable.

This patch changes the logic to wrap the handler and make sure logs are
created before, and after the handler is called (the "form-data" is always
added before the handler is called).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-10 14:22:31 +02:00
Paweł Gronowski
325076df0c Merge pull request #49765 from robmry/iptables_bridge_driver_level_rules
Put bridge driver's top-level iptables config in a separate object
2025-04-10 11:08:51 +00:00
Sebastiaan van Stijn
97688e8d06 container: Container.SetupWorkingDirectory: remove use of pkg/idtools
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-10 12:30:34 +02:00
Sebastiaan van Stijn
3e993060ee Merge pull request #48556 from thaJeztah/deprecate_info_expected_version_step2
api: info: omit deprecated "Commit.Expected" fields on API >= 1.49
2025-04-10 12:29:48 +02:00
Sebastiaan van Stijn
91ba210bc8 Merge pull request #49666 from thaJeztah/legacy_errors
api, client: produce human-readable errors for unsupported API versions (< v1.24)
2025-04-10 12:08:56 +02:00
Sebastiaan van Stijn
bfbd1004f4 Merge pull request #49762 from thaJeztah/remove_deprecated_AllowNondistributableArtifacts
registry: remove deprecated ServiceConfig.AllowNondistributableArtifacts
2025-04-10 12:08:14 +02:00
Paweł Gronowski
5f9d99b4cc integration-cli/swarm: Update to use gotest.tools
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-04-10 11:39:18 +02:00
Paweł Gronowski
ea6c76ee03 integration-cli/TestSwarmInit: Skip failing part on CLI after 18.06
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-04-10 11:39:16 +02:00
Paweł Gronowski
fab94808f5 integration-cli: Update default CLI version to v18.06.3-ce
This updates the Docker CLI version used for integration-cli tests from
v17.06.2-ce to v18.06.3-ce.

v18.06 is the first one that supports enabling BuildKit.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-04-10 11:39:13 +02:00
Tianon Gravi
6df89e7961 Merge pull request #49775 from dmcgowan/remove-ubuntu-20.04
Update remaining Ubuntu 20.04 GHA uses to 22.04 and 24.04
2025-04-10 00:05:30 +00:00
Sebastiaan van Stijn
466dda63dc Merge pull request #49747 from jsternberg/buildkit-vendor
vendor: github.com/moby/buildkit v0.21.0-rc1
2025-04-10 01:18:47 +02:00
Derek McGowan
6c73266a71 Add registry error handling for push and pull
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-04-09 14:19:27 -07:00
Jonathan A. Sternberg
ae3a1ac602 vendor: github.com/moby/buildkit v0.21.0-rc1
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2025-04-09 14:37:09 -05:00
Derek McGowan
cd89a35ea0 Run CLI tests with cgroups v2
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-04-09 11:05:14 -07:00
Sebastiaan van Stijn
da039bf8e6 Merge pull request #49777 from thaJeztah/bump_x_deps
vendor: update golang.org/x/.. dependencies
2025-04-09 18:05:11 +02:00
Sebastiaan van Stijn
58eabf4b36 Merge pull request #49759 from thaJeztah/migrate_archive_squashed_alt_step2
replace uses of idtools.MkdirAllAndChown, MkdirAllAndChownNew
2025-04-09 17:04:34 +02:00
Albin Kerouanton
888c14749d Merge pull request #47733 from krissetto/otel-test-stack
otel: simple OTEL collector/Jaeger/Aspire stack for testing purposes
2025-04-09 16:25:42 +02:00
Sebastiaan van Stijn
7435e4a1be registry: remove deprecated ServiceConfig.AllowNondistributableArtifacts
This option was deprecated in 1932091e21, and
is no longer used. It was only kept to allow priniting a deprecation warning
if the config would happen to have the field set.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-09 15:26:50 +02:00
Sebastiaan van Stijn
ba03cd7a63 daemon/config: add test for deprecated daemon.json fields
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-09 15:26:50 +02:00
Albin Kerouanton
27e7c650b8 Merge pull request #49773 from akerouanton/improve-has-active-endpoints-error
libnet: add ep name in 'has active endpoints' error
2025-04-09 15:14:37 +02:00
Sebastiaan van Stijn
d72e434d30 vendor: golang.org/x/mod v0.24.0
full diff: https://github.com/golang/mod/compare/v0.22.0...v0.24.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-09 14:28:37 +02:00
Sebastiaan van Stijn
224b393eb3 vendor: golang.org/x/net v0.39.0
full diff: https://github.com/golang/net/compare/v0.36.0...v0.39.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-09 14:26:51 +02:00
Sebastiaan van Stijn
b1ac2a53ed vendor: golang.org/x/crypto v0.37.0
full diff: https://github.com/golang/crypto/compare/v0.35.0...v0.37.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-09 14:25:29 +02:00
Sebastiaan van Stijn
a8af27bbae vendor: golang.org/x/text v0.24.0
no changes in vendored files

full diff: https://github.com/golang/text/compare/v0.22.0...v0.24.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-09 14:23:48 +02:00
Sebastiaan van Stijn
7d49b014b6 vendor: golang.org/x/sync v0.13.0
full diff: https://github.com/golang/sync/compare/v0.11.0...v0.13.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-09 14:20:16 +02:00
Sebastiaan van Stijn
9d04c28def vendor: golang.org/x/time v0.11.0
full diff: https://github.com/golang/time/compare/v0.6.0...v0.11.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-09 14:18:22 +02:00
Sebastiaan van Stijn
cdb3590e1a vendor: golang.org/x/sys v0.32.0
full diff: https://github.com/golang/sys/compare/v0.31.0...v0.32.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-09 14:16:30 +02:00
Christopher Petito
970fc1b6f7 Basic compose file for testing OTEL bits
Signed-off-by: Christopher Petito <chrisjpetito@gmail.com>
2025-04-09 13:48:04 +02:00
Sebastiaan van Stijn
d8a5e8928b replace uses of idtools.MkdirAllAndChown, MkdirAllAndChownNew
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-09 12:04:42 +02:00
Sebastiaan van Stijn
d96d20d45f update golangci-lint exceptions
These are no longer needed since d0154d3e59

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-09 12:00:50 +02:00
Rob Murray
29e0db25e7 Factor out top-level iptables setup into its own object
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-09 10:54:14 +01:00
Sebastiaan van Stijn
bcbcbb73fa Merge pull request #49743 from dmcgowan/update-archive-to-go-archive
Update archive to use github.com/moby/go-archive
2025-04-09 11:51:14 +02:00
Paweł Gronowski
5172617617 Merge pull request #49774 from akerouanton/fix-ContainerStart-trace
libnet/osl: independent OTel trace for advertiseAddrs
2025-04-09 09:29:48 +00:00
Albin Kerouanton
45daa6de06 Merge pull request #49769 from akerouanton/trace-bridge-createNetwork
libnet/d/bridge: trace createNetwork
2025-04-09 11:28:53 +02:00
Albin Kerouanton
241d685574 libnet: add ep name in 'has active endpoints' error
There have been numerous reports of the "has active endpoints" error
over the years. Historically, there were some faulty code paths that
could lead to this error, but we believe they all have been fixed by
now.

However, users are still facing this error from time to time. Either
because they forgot that some containers are still running, or because
we still have bugs lying around.

To help users figure whether this error is legitimate, and what triggers
it, add endpoint names (which are just container names) to the error
message.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 10:53:56 +02:00
Albin Kerouanton
489cd7edfc api, daemon, libnet: add a 'trigger' baggage member
Add an OTel span processor copying the 'trigger' baggage member
propagated through contexts to all children spans. It's used to identify
what triggered a trace / span (API call, libnet init, etc...)

All code paths that call libnet's `NewNetwork` set this baggage member
with a unique value.

For instance, this can be used to distinguish bridge's `createNetwork`
spans triggered by daemon / libnet initialization from custom network
creation triggerd by an API call.

Two util functions are added to wrap `baggage.New` and
`baggage.NewMemberRaw` to make it easier to deal with baggage and
members by panicking on error. These should not be used with dynamic
values.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:45:33 +02:00
Albin Kerouanton
31ac5cb6d9 libnet: New: plumb context
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:45:33 +02:00
Albin Kerouanton
667c7d70b3 libnet/d/bridge: trace network setup steps
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:45:33 +02:00
Albin Kerouanton
eaae4b5fb6 libnet/d/bridge: put span prefix in var
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:45:33 +02:00
Albin Kerouanton
78be7ebad7 libnet/d/bridge: trace createNetwork
Plumb context from the API down to libnet driver method `CreateNetwork`,
and add an OTel span to the bridge driver's `createNetwork` method.
Include a few attributes describing the network configuration (e.g.
IPv4/IPv6, ICC, internal and MTU).

A new util function, `RecordStatus`, is added to the `otelutil` package
to easily record any error, and update the span status accordingly.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:45:33 +02:00
Albin Kerouanton
f8806f2b80 libnet/osl: independent OTel trace for advertiseAddrs
Since commit `eaa84bc`, when a container joins a network, we broadcast
unsolicited ARP/NAs to other containers connected to that network. The
initial advertisement is sent synchronously, and then remaining
advertisements (by default, 2) are sent asynchronously at a regular
interval (by default, 1 second).

An OTel span records the time spent sending subsequent advertisements,
but it's attached to the parent span `libnetwork.osl.AddInterface` so it
affects the overall latency reported by the trace.

The real latency (i.e. excluding the latency of that asynchronous
process), is pretty much what CLI users perceive, so it's an important
measure. It's available on the top-most span in the trace, but limiting
the trace to the real time taken by the Engine to process the HTTP
request seems better.

With this change, the initial advertisement is now tracked by a
dedicated span, and a new independent trace (containing a single span)
is created and linked to the 'initial' span / HTTP trace.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-09 08:43:34 +02:00
Derek McGowan
d0154d3e59 Update to use github.com/moby/go-archive
Update use of idtools to moby/user for archive and other deprecated uses

Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-04-08 17:35:05 -07:00
Derek McGowan
45f9d679f8 Update remaining Ubuntu 20.04 uses to 22.04 and 24.04
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-04-08 12:50:52 -07:00
Derek McGowan
57a042b77c deprecate pkg/(chroot)archive for github.com/moby/go-archive
- pkg/archive: deprecate, and add aliases
  Keeping the tests in this commit; also moves various utilities
  into a _test.go file, as they were now only used in tests.
- pkg/chrootarchive: deprecate and add aliase
  deprecate pkg/archive and add aliases
  keeping the tests in this commit
- Add temporary exceptions for deprecation linting errors, because
  this commit is to verify everything works with the aliases.
- remove tests that depend on un-exported types

    === RUN   TestDisablePigz
    --- FAIL: TestDisablePigz (0.00s)
    panic: interface conversion: io.Reader is *archive.readCloserWrapper, not *archive.readCloserWrapper (types from different packages) [recovered]

- pkg/archive, pkg/chrootarchive: remove test files

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-04-08 10:56:58 -07:00
Sebastiaan van Stijn
564abf9157 api: info: omit deprecated "Commit.Expected" fields on API >= 1.49
These fields were deprecated in ff191c58f7,
and are now omitted.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-08 15:15:58 +02:00
Sebastiaan van Stijn
ba12b2d0bc Merge pull request #49749 from thaJeztah/omit_non_distributable
api: /info: omit non-distributable-artifacts fields for API >= 1.49
2025-04-08 15:14:02 +02:00
Paweł Gronowski
cf1001d555 Merge pull request #48563 from crazy-max/dockerfile-dind
dockerfile: dind target to build docker image for testing
2025-04-08 10:33:40 +00:00
Rob Murray
1b187e0959 Merge pull request #49728 from robmry/bridge_driver_firewalld_reload
Stop firewalld reload re-creating rules for deleted networks
2025-04-08 11:18:34 +01:00
CrazyMax
f410dbda88 dockerfile: dind target to build docker image for testing
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
2025-04-08 11:48:33 +02:00
Rob Murray
c3fa7c1779 Test that firewalld reload doesn't re-create deleted iptables rules
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-08 10:27:35 +01:00
Rob Murray
dbea045e0d Report firewalld reload time in Info.FirewallBackend
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-08 10:26:41 +01:00
Rob Murray
a527e5a546 Restore iptables for current networks on firewalld reload
Using iptables.OnReloaded to restore individual per-network rules
on firewalld reload means rules for deleted networks pop back in
to existence (because there was no way to delete the callbacks on
network-delete).

So, on firewalld reload, walk over current networks and ask them
to restore their iptables rules.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-08 10:26:41 +01:00
Rob Murray
9ba5c5d70e Merge pull request #49732 from robmry/nftables_primitives
Add utils for manipulating nftables rules
2025-04-08 09:25:41 +01:00
Akihiro Suda
3509feb1a5 Merge pull request #49763 from thaJeztah/registry_wire_up_contexts
registry: wire up contexts in some places, and remove some intermediate vars
2025-04-08 16:14:31 +09:00
Sebastiaan van Stijn
185651d26b Merge pull request #49767 from thaJeztah/vendor_atomicwriter
vendor: github.com/moby/sys/atomicwriter v0.1.0
2025-04-07 19:17:02 +02:00
Sebastiaan van Stijn
7d9c50db2b api: /info: omit non-distributable-artifacts fields for API >= 1.49
- registry.ServiceConfig: add a "ExtraFields" for outputting deprecated
  fields.
- remove uses of AllowNondistributableArtifactsCIDRs and AllowNondistributableArtifactsHostnames

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-07 19:12:09 +02:00
Paweł Gronowski
ebc6c065d2 Merge pull request #49761 from robmry/add_info_firewallbackend
Add Info.FirewallBackend
2025-04-07 17:00:45 +00:00
Paweł Gronowski
83278485c0 Merge pull request #49734 from Shaggy84675/49709-fix_system_cpu_usage_stat
Fix docker stats parsing with large amount of interrupts
2025-04-07 16:41:25 +00:00
Rob Murray
a0a86d0982 Add Info.FirewallBackend
Report FirewallBackend in "docker info".

It's currently "iptables" or "iptables+firewalld" on Linux, and
omitted on Windows.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-07 16:56:49 +01:00
Sebastiaan van Stijn
25a80bd48e vendor: github.com/moby/sys/atomicwriter v0.1.0
no changes in vendored files

full diff: https://github.com/moby/sys/compare/6e2523cbf3a1...atomicwriter/v0.1.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-07 17:44:43 +02:00
Paweł Gronowski
d7d91b6bc5 Merge pull request #49764 from akerouanton/fix-TestNetworkStore-TestEndpointStore
libnet: de-flake TestEndpointStore and TestNetworkStore
2025-04-07 15:31:16 +00:00
Sebastiaan van Stijn
96601d1211 Merge pull request #49586 from vvoland/image-inspect-platform
image/inspect: Add platform selection
2025-04-07 16:29:57 +02:00
Albin Kerouanton
4eebd2c920 libnet: TestNetworkStore: replace assert.Equal with Check
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-07 16:25:00 +02:00
Patrik Leifert
e22d04e8a9 Improve CPU usage parsing and error reporting
This fix address issues where the scanner was unable to properly parse longer outputs from /proc/stat. This could happen on an ARM machine with large amount of CPU cores (and interrupts). By switching to reader we have more control over data parsing and dump unnecessary data

Signed-off-by: Patrik Leifert <patrikleifert@hotmail.com>
2025-04-07 16:19:02 +02:00
Albin Kerouanton
40650c6982 libnet: de-flake TestNetworkStore
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-07 16:03:36 +02:00
Albin Kerouanton
1c79c893b1 libnet: de-flake TestEndpointStore
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-07 16:03:03 +02:00
Paweł Gronowski
d9fd0c2db4 Merge pull request #49746 from vvoland/c8d-pull-progress-all
c8d/pull: Show progress for non-layer blobs
2025-04-07 12:40:46 +00:00
Sebastiaan van Stijn
8a5f141b0e registry: Service.lookupV2Endpoints: wire-up context
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-07 13:36:21 +02:00
Sebastiaan van Stijn
9d8c8382d3 registry: authorizeClient: wire-up context
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-07 13:35:03 +02:00
Sebastiaan van Stijn
8b920b2812 registry: loginV2: wire-up context
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-07 13:35:03 +02:00
Sebastiaan van Stijn
4642704ed7 registry: newTransport: remove intermediate var
Align closer to other code doing the same.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-07 13:35:03 +02:00
Paweł Gronowski
7acef8101e c8d/pull: Show progress for non-layer blobs
Use the same logic as push for determining whether a progress should be
shown for a blob.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-04-07 13:31:04 +02:00
Paweł Gronowski
da3b31fb2c Merge pull request #49736 from akerouanton/cache-endpoint-in-memory
libnet: Controller: cache networks & endpoints in-memory
2025-04-07 10:00:36 +00:00
Paweł Gronowski
4f7588f6ad Merge pull request #49724 from akerouanton/fix-duplicated-port-mappings
libnet: fix duplicated port mappings in overlay networks
2025-04-07 09:57:38 +00:00
Sebastiaan van Stijn
c95e17638f Merge pull request #49757 from thaJeztah/archive_fix_linting
pkg/archive: fix linting issues
2025-04-07 10:18:03 +02:00
Akihiro Suda
b3bafd4b78 Merge pull request #49753 from thaJeztah/idtools_replace
pkg/idtools: MkdirAllAndChownNew: improve deprecation message
2025-04-07 09:00:46 +01:00
Akihiro Suda
e7ab601ab9 Merge pull request #49750 from thaJeztah/bump_go_cmp
vendor: github.com/google/go-cmp v0.7.0
2025-04-07 08:59:43 +01:00
Sebastiaan van Stijn
b3791dea92 pkg/archive: fix linting issues
fix "struct literal uses unkeyed fields" (govet)

    pkg/archive/changes_test.go:123:18: composites: github.com/docker/docker/pkg/archive.Change struct literal uses unkeyed fields (govet)
        modifyChange := Change{"change", ChangeModify}
                        ^
    pkg/archive/changes_test.go:128:15: composites: github.com/docker/docker/pkg/archive.Change struct literal uses unkeyed fields (govet)
        addChange := Change{"change", ChangeAdd}
                     ^
    ...

fix various variables that shadowed types

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-07 08:48:53 +02:00
Akihiro Suda
27568e54ce Merge pull request #49751 from thaJeztah/bump_compress
vendor: github.com/klauspost/compress v1.18.0
2025-04-07 04:52:12 +01:00
Sebastiaan van Stijn
a427477220 pkg/idtools: MkdirAllAndChownNew: improve deprecation message
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-06 13:02:52 +02:00
Sebastiaan van Stijn
a91bcc677b vendor: github.com/klauspost/compress v1.18.0
full diff: https://github.com/klauspost/compress/compare/v1.17.11...v1.18.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-05 16:44:10 +02:00
Sebastiaan van Stijn
2c54f6f316 vendor: github.com/google/go-cmp v0.7.0
full diff: https://github.com/google/go-cmp/v0.6.0...v0.7.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-05 16:42:24 +02:00
Sebastiaan van Stijn
6cbca96bfa Merge pull request #49748 from thaJeztah/migrate_atomicwriter
deprecate pkg/atomicwriter, migrate to github.com/moby/sys/atomicwriter
2025-04-05 11:01:16 +02:00
Sebastiaan van Stijn
79b22645fc Merge pull request #49737 from thaJeztah/bump_golang_1.23.8
update to go1.23.8 (fix CVE-2025-22871)
2025-04-05 11:00:11 +02:00
Sebastiaan van Stijn
6422ff2804 deprecate pkg/atomicwriter, migrate to github.com/moby/sys/atomicwriter
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-04 23:07:00 +02:00
Sebastiaan van Stijn
872b6d5df9 Merge pull request #49738 from thaJeztah/bump_cdi
vendor: tags.cncf.io/container-device-interface v1.0.1
2025-04-04 22:43:21 +02:00
Sebastiaan van Stijn
d7b743b856 Merge pull request #49741 from thaJeztah/atomicwriter_stricter_validate
pkg/atomicwriter: disallow symlinks for now, add more tests and touch-up GoDoc
2025-04-04 20:11:23 +02:00
Sebastiaan van Stijn
43b7c78cbd Merge pull request #49566 from dmcgowan/update-moby-user-idtools
Update `github.com/moby/sys/user` and use of idtools
2025-04-04 18:31:19 +02:00
Sebastiaan van Stijn
5ea21c927c Merge pull request #49745 from thaJeztah/registry_cleanup_step3
registry: wire up context in some places
2025-04-04 17:43:49 +02:00
Sebastiaan van Stijn
f1ec5bf14f pkg/idtools: remove tests already covered in moby/sys/user
Removes all tests, except for TestGetRootUIDGID and TestToContainer, which
are the only once that have a local implementation that's not covered.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-04 08:24:09 -07:00
Derek McGowan
3fc36bcac4 Update daemon to use moby sys/user identity mapping
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-04-04 08:24:09 -07:00
Derek McGowan
b5c99c0e95 Update moby/sys/user to version which includes mapping
Update idtools to use Mkdir funcs from moby sys/user package
Add deprecation exception to golanci until move off idtools is complete

Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-04-04 08:22:05 -07:00
Sebastiaan van Stijn
0a83a476d8 registry: v1Endpoint.ping: pass through context
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-04 12:59:42 +02:00
Sebastiaan van Stijn
2a272a0c5d registry: newV1Endpoint: pass through context
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-04 12:59:42 +02:00
Sebastiaan van Stijn
f158d2e809 registry: ReadCertsDirectory: internalize, and pass context
- Split the implementation from the exported function (exported
  function is still used by the CLI for Docker Content Trust).
- Pass through context to allow handling context-cancellation
  once wired up in callers.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-04 12:59:36 +02:00
Sebastiaan van Stijn
11bf52e9e3 Merge pull request #49739 from thaJeztah/registry_cleanup_step2
registry: minor fixes and cleanups
2025-04-04 12:30:52 +02:00
Albin Kerouanton
51d7f95c4b libnet: remove struct endpointCnt
endpointCnt is a refcounter used to track how many endpoints use a
network, and how many networks references a config-only network. It's
stored separately from the network.

This is only used to determine if a network can be removed.

This commit removes the `endpointCnt` struct and all its references. The
refcounter is replaced by two lookups in the newly introduced `networks`
and `endpoints` caches added to the `Controller`.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-04 11:21:17 +02:00
Paweł Gronowski
68451d3c99 Merge pull request #49650 from jsternberg/containerd-dangling-image-on-load
containerd: ensure overwritten images from load are left dangling
2025-04-04 09:14:38 +00:00
Albin Kerouanton
d377cd3810 libnet: Controller: cache networks in-memory
The `Controller`'s store is used by:

- `deleteFromStore`
- `getNetworks`
- `getNetworksFromStore`
- `updateToStore`
- … and other methods that can't store / delete / retrieve a Network

Calls to `updateToStore` and `deleteFromStore` have been replaced with
`upsertNetwork` and `deleteNetwork`.

Both `getNetworks` and `getNetworksFromStore` call `cacheNetwork` to
ensure networks loaded from the datastore are kept in-memory.

Finally, `sandboxRestore` was instantiating `Network` itself. These are
cached too.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-04 10:03:02 +02:00
Albin Kerouanton
cc8bd2016e libnet: Controller: cache endpoints in-memory
The `Controller`'s store is used by:

- `deleteFromStore`
- `getEndpointFromStore`
- `getEndpointsFromStore`
- `updateToStore`
- … and other methods that can't store / delete / retrieve an Endpoint

Calls to `updateToStore` and `deleteFromStore` have been replaced with
`upsertEndpoint` and `deleteEndpoint`.

Both `getEndpointFromStore` and `getEndpointsFromStore` call
`cacheEndpoint` to ensure endpoints loaded from the datastore are kept
in-memory.

Finally, `sandboxRestore` was instantiating `Endpoint` itself. These are
cached too.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-04 10:03:02 +02:00
Sebastiaan van Stijn
4ad6854eb3 Merge pull request #49727 from robmry/rootlesskit_iptables_check
Rootless setup: check for module nf_tables
2025-04-04 01:06:14 +02:00
Sebastiaan van Stijn
c6cdfbf495 pkg/atomicwriter: return early if parent directory is invalid
Rewrite `validateDestination` to first check if the destination path
exists. This slightly simplifies the logic (allowing returning
early in each step of the validation) and slightly improves the
error produced.

Before this, the error confusingly would mention the full path
not being a directory. While this _does_ match what `os.Writefile`
would return, it's .. confusing:

    failed to stat output path: lstat ./not-a-dir/new-file.txt: not a directory

After this, the error would mention the directory that doesn't exist:

    invalid output path: stat ./not-a-dir: not a directory

A slight optimization is made as well, now checking for _both_ "."
and ".." as special case, as either path should exist given any current
working directory (unless the working directory has been deleted, but we'd
fail further down the line).

With this change in order, we can also merge `validateFileMode` into
`validateDestination`.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-03 21:57:13 +02:00
Sebastiaan van Stijn
00c988caa4 pkg/atomicwriter: add test for parent dir not being a directory
While the target-file does not have to exist, its parent must, and must
be a directory. This adds a test-case to verify the behavior if the
parent is not a directory.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-03 21:39:33 +02:00
Sebastiaan van Stijn
ad386f64e5 pkg/atomicwriter: error on unknown file-modes
Previously, we were silently discarding this situation and hoping that
it would work; let's produce an error instead (we can add additional
filemodes when they arrive and if we need them)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-03 21:39:32 +02:00
Sebastiaan van Stijn
ec82bc35c3 pkg/atomicwriter: disallow symlinked files for now
The implementation uses "os.Rename" to move the temporary file to
the destination, which does not follow symlinks, and because of this
would replace a symlink with a file.

We can consider adding support for symlinked files in future, so that
WriteFile can be used as a drop-in replacement for `os.WriteFile()`
but in the meantime, let's produce an error so that nobody can depend
on this.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-03 21:39:32 +02:00
Sebastiaan van Stijn
f3aebbf9d8 pkg/atomicwriter: add basic godoc for package
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-03 21:39:21 +02:00
Rob Murray
f80feba181 Rootlesskit: check for module nf_tables
CentOS 10 uses iptables-nft by default, and doesn't have
kernel module ip_tables - so dockerd-rootless-setuptool.sh
reports that the module is missing. It suggests installing
it (which isn't needed), or using --skip-iptables (which
disables iptables in daemon config).

So, unless "iptables --version" command reports "legacy",
check for kernel module "nf_tables" instead of "ip_tables".

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-03 20:25:35 +01:00
Paweł Gronowski
26e516dff4 Merge pull request #49720 from robmry/iptablesnetwork_per_port_rules
Include per-port rules in iptablesNetwork
2025-04-03 18:59:09 +00:00
Rob Murray
7d742ebf75 Add utils for manipulating nftables rules
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-03 16:47:30 +01:00
Paweł Gronowski
59169d0f97 image/inspect: Add platform selection
`GET /image/{name}/json` now supports `platform` parameter allowing to
specify which platform variant of a multi-platform image to inspect.

For servers that do not use containerd image store integration, this
option will cause an error if the requested platform doesn't match the
image's actual platform

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-04-03 13:57:51 +02:00
Sebastiaan van Stijn
d4e70f6325 vendor: tags.cncf.io/container-device-interface v1.0.1
full diff: https://github.com/cncf-tags/container-device-interface/compare/v0.8.1...v1.0.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-03 13:10:29 +02:00
Sebastiaan van Stijn
74b71c41ac update to go1.23.8 (fix CVE-2025-22871)
full diff: https://github.com/golang/go/compare/go1.23.7...go1.23.8
release notes: https://go.dev/doc/devel/release#go1.24.2

go1.23.8 (released 2025-04-01) includes security fixes to the net/http package,
as well as bug fixes to the runtime and the go command. See the Go 1.23.8
milestone on our issue tracker for details;

https://github.com/golang/go/issues?q=milestone%3AGo1.23.8+label%3ACherryPickApproved

From the mailing list:

Hello gophers,

We have just released Go versions 1.24.2 and 1.23.8, minor point releases.
These minor releases include 1 security fixes following the security policy:

- net/http: request smuggling through invalid chunked data
  The net/http package accepted data in the chunked transfer encoding
  containing an invalid chunk-size line terminated by a bare LF.
  When used in conjunction with a server or proxy which incorrectly
  interprets a bare LF in a chunk extension as part of the extension,
  this could permit request smuggling.
  The net/http package now rejects chunk-size lines containing a bare LF.
  Thanks to Jeppe Bonde Weikop for reporting this issue.
  This is CVE-2025-22871 and Go issue https://go.dev/issue/71988.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-03 12:30:00 +02:00
Sebastiaan van Stijn
fc58c829e8 registry: ParseRepositoryInfo: remove some intermediate vars
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-03 12:10:17 +02:00
Sebastiaan van Stijn
44b7a42fc6 registry: ReadCertsDirectory: return early on error
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-03 12:10:16 +02:00
Sebastiaan van Stijn
4f65e35f02 registry: NewService: return nil on error
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-03 12:10:16 +02:00
Sebastiaan van Stijn
a7daab5df4 registry: authTransport: un-export AuthConfig, RoundTripper
Don't embed these interfaces/types, and keep them internal.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-03 12:10:13 +02:00
Paweł Gronowski
36295bb9ed Merge pull request #49714 from thaJeztah/distribution_cleanups
distribution: cleanup tests, and remove unused fields
2025-04-03 09:26:31 +00:00
Rob Murray
2e92272753 Merge pull request #49735 from thaJeztah/sync_swagger_docs
docs: API v1.48: Add missing platform parameter to ImageGet api docs and add it under Image tag
2025-04-03 09:47:35 +01:00
Sebastiaan van Stijn
5b8a41934b Merge pull request #49729 from robmry/no_rootless_unit_tests
Don't run unit tests with mode rootless
2025-04-02 23:51:12 +02:00
Kristian Heljas
795461eceb docs: api v1.48: Move ImageGet api docs under Image tag
Signed-off-by: Kristian Heljas <kristian@kristian.ee>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-02 23:25:57 +02:00
Kristian Heljas
e1e58409a1 docs: API v1.48 Add missing platform parameter to ImageGetAll api docs
Signed-off-by: Kristian Heljas <kristian@kristian.ee>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-02 23:25:26 +02:00
Rob Murray
b5b6e1b24c Merge pull request #49726 from kristianheljas/image-get-platform-parameter
Add missing platform parameter to ImageGet api docs and add it under Image tag
2025-04-02 19:26:01 +01:00
Albin Kerouanton
db275ddbc1 libnet: fix duplicated port mappings in overlay networks
Since commit f2a183a99, `getEndpointPortMapInfo` is called for all the
endpoints of a container to get its complete list of port mappings. This
is required as multiple endpoints might publish different ports (e.g.
IPv4-only and IPv6-only endpoints mapping an IPv4 and an IPv6 port).

`getEndpointPortMapInfo` calls `(*Endpoint).DriverInfo()` which has a
dodgy behavior: if the endpoint is part of a sandbox that also has an
endpoint for the `docker_gwbridge` network, then `(*Endpoint).DriverInfo()`
returns the DriverInfo of that `docker_gwbridge` endpoint in place of
the current Endpoint's DriverInfo.

On overlay networks, host port-mappings are made through the
`docker_gwbridge` network (which is automatically attached to all Swarm
tasks). This results in duplicated port mappings reported for all Swarm
containers.

Since `getEndpointPortMapInfo` is the only place where
`(*Endpoint).DriverInfo()` is called, just remove that dodgy behavior.

`(*Endpoint).DriverInfo()` has an OS-specific implementation. Unlike the
Linux implementation, on Windows, `DriverInfo()` returns the DriverInfo
of the gateway endpoint _in addition_ to the current Endpoint's
DriverInfo. So it shouldn't be affected by this bug -- don't touch it.

Signed-off-by: Albin Kerouanton <albinker@gmail.com>
2025-04-02 12:30:50 +02:00
Rob Murray
a9e22ee5e7 Don't run unit tests with mode rootless
Tests will run in the host's namspace not the rootlesskit
namespace. So, just duplicating the non-rootless unit tests.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-04-02 10:43:40 +01:00
Rob Murray
25905ab6c6 Merge pull request #49718 from vvoland/api-1.49
api: bump API version to 1.49
2025-04-01 19:53:31 +01:00
Kristian Heljas
749e35cf5e Move ImageGet api docs under Image tag
Signed-off-by: Kristian Heljas <kristian@kristian.ee>
2025-04-01 16:06:17 +03:00
Kristian Heljas
094df015b1 Add missing platform parameter to ImageGetAll api docs
Signed-off-by: Kristian Heljas <kristian@kristian.ee>
2025-04-01 16:06:03 +03:00
Sebastiaan van Stijn
843e51459f Merge pull request #49609 from thaJeztah/client_more_canonical
client: keep image refs in canonical format where possible
2025-04-01 09:43:52 +02:00
Sebastiaan van Stijn
b5280352e9 Merge pull request #49608 from thaJeztah/atomicwriter_sequential
pkg/atomicwriter: use sequential file access on Windows
2025-03-31 18:11:18 +02:00
Rob Murray
7243860557 Include per-port rules in iptablesNetwork
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-31 17:04:17 +01:00
Rob Murray
f01a2eb710 Merge pull request #49710 from robmry/simplify_bridge_legacy_links
Simplify bridge legacy links
2025-03-31 16:15:00 +01:00
Paweł Gronowski
4390ab275a api: bump API version to 1.49
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-31 14:09:39 +02:00
Paweł Gronowski
67670ddc80 Merge pull request #49715 from thaJeztah/registry_touchup_ValidateMirror
registry: ValidateMirror: touch-up GoDoc and improve test-coverage
2025-03-31 11:48:46 +00:00
Paweł Gronowski
0cabd9dfba Merge pull request #49713 from thaJeztah/search_pass_context
registry: session.searchRepositories: pass through context
2025-03-31 11:46:47 +00:00
Rob Murray
0b5e1f904a Use netip.Addr instead of net.IP for legacy links
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-31 11:52:16 +01:00
Rob Murray
725e699741 Simplify iptables setup for legacy links
Include legacy link setup in IptablesNetwork, with the other
per-network rules.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-31 11:52:16 +01:00
Rob Murray
c5c9dc0376 Merge pull request #49668 from robmry/iptables_network_rules
Bridge: factor out creation of network-level iptables rules
2025-03-31 11:48:45 +01:00
Sebastiaan van Stijn
31f9ae0d19 registry: TestValidateMirror: improve coverage
Test actual error returned, and test normalized value.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-31 10:14:43 +02:00
Sebastiaan van Stijn
cb0a9d713c registry: ValidateMirror: touch-up GoDoc
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-31 10:11:29 +02:00
Sebastiaan van Stijn
6b258ce567 registry: session.searchRepositories: pass through context
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-31 10:00:23 +02:00
Sebastiaan van Stijn
83aaa3428f distribution: pusher.push(): don't use APIEndpoint.Mirror field
Unlike the equivalent for pulling images, [Service.LookupPushEndpoints]
never returns mirror endpoints, as it calls [Service.lookupV2Endpoints]
with "includeMirrors=false", so we should not use this field, and
unconditionally handle errors without the additional fallbacks that
we consider for pulling images from a mirror.

[Service.LookupPushEndpoints]: cea56c1d9c/registry/service.go (L134-L139)
[Service.lookupV2Endpoints]: cea56c1d9c/registry/service_v2.go (L10-L40)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-31 09:57:05 +02:00
Sebastiaan van Stijn
6439824449 distribution: pushDescriptor: remove unused endpoint field
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-31 09:57:05 +02:00
Sebastiaan van Stijn
09ee47de39 distribution: cleanup some tests and add missing error-checks
- use gotest.tools for assertions
- remove some debug-logs

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-31 09:57:04 +02:00
Rob Murray
37f866285a Merge pull request #49659 from robmry/firewalld_status
Run firewalld in CI
2025-03-28 18:32:18 +00:00
Rob Murray
adfed82ab8 Install and run firewalld for CI's firewalld tests
The github action running bake expected FIREWALLD to be set, but
DOCKER_FIREWALLD was set instead, so firewalld wasn't installed
in the dev image.

The dind-systemd script expected DOCKER_FIREWALLD to be set if it
needed to run firewalld, and it was. But it had no effect.

In CI, bake builds the image then make runs it - and the use the
same env. So, align on FIREWALLD (as it's not a docker feature).

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-28 16:59:48 +00:00
Rob Murray
409707b633 bridge: factor out creation of network-level iptables rules
Create an iptablesNetwork containing all the info needed to
set up per-network iptables rules, give it methods to do
create the rules, and use it instead of per-rule-type calls
from driver.createNetwork().

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-28 16:57:16 +00:00
Sebastiaan van Stijn
4cc249d7e3 Merge pull request #49706 from thaJeztah/deprecate_apiendpoint_official
registry: deprecate APIEndpoint.Official field
2025-03-28 16:24:15 +01:00
Sebastiaan van Stijn
81e267c013 Merge pull request #49696 from thaJeztah/registry_cleanup_step1
refactor and simplify various code-paths related to distribution / authentication
2025-03-28 15:48:00 +01:00
Sebastiaan van Stijn
ec7fe73690 distribution: pushDescriptor: rename repoInfo to repoName
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:58 +01:00
Sebastiaan van Stijn
b1c526b4a9 daemon/containerd: remove registryResolver interface
While it's generally better to define interfaces locally, this one
now duplicated distribution.RegistryResolver, and it's passed on
to other types which expect that interface.

Remove this (un-exported) interface to make it easier to discover
what's used where.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:58 +01:00
Sebastiaan van Stijn
0d95e1680a registry: ResolveAuthConfig: inline newIndexInfo code
inline a simplified version of "newIndexInfo" without handling of
insecure registries and mirrors, as we don't need that information
to resolve the auth-config.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:57 +01:00
Sebastiaan van Stijn
6c643bc366 lookup auth-config without depending on RepositoryInfo
Simplify how we lookup auth-config, as we don't need the
additional information provided by RepositoryInfo. There's
still more layers to peel off, which will be done in follow-ups.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:57 +01:00
Sebastiaan van Stijn
a18dae049f daemon/containerd: registryResolver: remove IsInsecureRegistry
It's not called anywhere, so we can remove it from this interface.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:57 +01:00
Sebastiaan van Stijn
abcc70b9ef distribution: GetRepositories skip using Service.ResolveRepository
[Service.ResolveRepository] is a shallow wrapper around [newRepositoryInfo],
from which we only consume the `Name` field. That field is a direct result
of `reference.TrimNamed`, so we can replace this with that.

[Service.ResolveRepository]: ecb03c4cda/registry/service.go (L106-L111)
[newRepositoryInfo]: ecb03c4cda/registry/config.go (L392-L408)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:57 +01:00
Sebastiaan van Stijn
071d8b21e9 distribution: Push: skip using Service.ResolveRepository
[Service.ResolveRepository] is a shallow wrapper around [newRepositoryInfo],
from which we only consume the `Name` field. That field is a direct result
of `reference.TrimNamed`, so we can replace this with that.

[Service.ResolveRepository]: ecb03c4cda/registry/service.go (L106-L111)
[newRepositoryInfo]: ecb03c4cda/registry/config.go (L392-L408)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:57 +01:00
Sebastiaan van Stijn
8b6a045aa4 distribution; newPusher: don't require RepositoryInfo
This constructor only uses the name / reference, and doesn't
use any of the other properties provided in RepositoryInfo.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:56 +01:00
Sebastiaan van Stijn
8653af5854 distribution: pullEndpoints: skip using Service.ResolveRepository
[Service.ResolveRepository] is a shallow wrapper around [newRepositoryInfo],
from which we only consume the `Name` field. That field is a direct result
of `reference.TrimNamed`, so we can replace this with that.

[Service.ResolveRepository]: ecb03c4cda/registry/service.go (L106-L111)
[newRepositoryInfo]: ecb03c4cda/registry/config.go (L392-L408)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:56 +01:00
Sebastiaan van Stijn
20a2807caa distribution: pullEndpoints: don't return RepositoryInfo
we're only consuming the name returned.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:56 +01:00
Sebastiaan van Stijn
f1ecce6877 distribution: pullEndpoints: don't require RepositoryInfo
The callback only used the name / reference

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:56 +01:00
Sebastiaan van Stijn
d6afe88b3c distribution: newPuller: don't require RepositoryInfo
This constructor only uses the name / reference, and doesn't
use any of the other properties provided in RepositoryInfo.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:54 +01:00
Sebastiaan van Stijn
03918c5b07 distribution: layerDescriptor: don't require RepositoryInfo
This type only uses the name / reference, and doesn't use any of the
other properties provided in RepositoryInfo.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:55:04 +01:00
Sebastiaan van Stijn
c91318e6c0 distribution: newRepository: don't require RepositoryInfo
This constructor only uses the name / reference, and doesn't
use any of the other properties provided in RepositoryInfo.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:54:59 +01:00
Sebastiaan van Stijn
2e8bf8b0ab distribution: remove vars that shadowed imports or types
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-28 10:48:10 +01:00
Rob Murray
a420005d4e Merge pull request #49672 from jsternberg/containerd-prioritize-non-dangling
containerd: prioritize non-dangling images with image list
2025-03-27 17:34:25 +00:00
Sebastiaan van Stijn
d8fa2f8071 registry: deprecate APIEndpoint.Official field
This field was introduced in 19515a7ad8 when
the registry code was replaced for code vendored from docker/distribution.

It was used for v1 registries to update the "TrustStore" for signed manifests;
19515a7ad8/graph/pull.go (L89-L93)

Before that, it used the IndexInfo.Official field;
276c640be4/graph/pull.go (L94-L97)

And related to "v2" registries;
88fdcfef02

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-27 15:00:39 +01:00
Rob Murray
0ab6f07c31 Fix TestPassthrough
Doesn't look like it would ever have worked, but:
- init the dbus connection to avoid a segv
- include the chain name when creating the rule
- remove the test rule if it's created

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-27 12:15:16 +00:00
Rob Murray
2d643b6835 Firewalld: skip unit tests that run in their own netns
Firewalld runs in the host netns. So, tests running in
their own netns can't check firewalld's iptables rules.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-27 12:14:20 +00:00
Rob Murray
4fbfb618c3 Skip flaky part of TestAccessPublishedPortFromHost
With firewalld enabled in CI, TestAccessPublishedPortFromHost/userland-proxy=true/IPv6=true
consistently fails when trying to use a link-local address on
eth0 (it's ok for the ULL added by the test).

In a local moby dev container, it passes - although it sometimes
fails when making its request to the host's ::1.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-27 08:36:09 +00:00
Rob Murray
b8323abe0a TestIsolated for IPv6 is broken under firewalld
Skip the test for now.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-27 08:36:09 +00:00
Rob Murray
86eff82789 Firewalld: Skip tests that run dockerd in an L3Segment
The daemon runs in a separate netns, but when it wants to create
an iptables rule it sends a dbus message to firewalld - which is
running in the host's netns.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-27 08:36:09 +00:00
Rob Murray
dc963a00c1 Firewalld should use its nftables backend
Since commit cfc049c the dev container has been using iptables-nft,
but the Dockerfile configured firewalld to use its iptables backend
(if firewalld is enabled, which it accidentally hasn't been in CI).

The integration tests run ok for a while, then some things start
failing with the less than obvious message:

  Error: COMMAND_FAILED: UNKNOWN_ERROR: nonexistent or underflow of priority count

So, let firewalld use its default nftables backend.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-27 08:36:09 +00:00
Rob Murray
b8cacdf324 Add test util "FirewalldRunning"
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-27 08:36:09 +00:00
Rob Murray
cea56c1d9c Merge pull request #49671 from robmry/unit_test_with_firewalld
Run systemd/rootless when systemd/rootless unit testing
2025-03-27 08:34:31 +00:00
Sebastiaan van Stijn
6de8ba3bc5 Merge pull request #49688 from thaJeztah/disable_go_telemetry
Dockerfile: disable saving Golang telemetry in dev-container
2025-03-26 17:25:34 +01:00
Jonathan A. Sternberg
8f506a51e5 containerd: ensure overwritten images from load are left dangling
During a load, ensure any existing images are left as dangling images.
This affects the `docker load` command with the containerd snapshotter
backend.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2025-03-26 09:20:46 -05:00
Paweł Gronowski
264fc2fac8 Merge pull request #49705 from robmry/continue_if_bridge_port_down
Start containers, even when connected to a disabled bridge port
2025-03-26 13:08:03 +00:00
Paweł Gronowski
849c723078 Merge pull request #46941 from thaJeztah/govalidator
implement module compatibility check
2025-03-26 12:52:10 +00:00
Paweł Gronowski
82b25f0947 Merge pull request #49704 from thaJeztah/bump_image_spec
vendor: github.com/opencontainers/image-spec v1.1.1
2025-03-26 12:44:27 +00:00
Rob Murray
7b2e47846c Run systemd/rootless when systemd/rootless unit testing
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-26 12:13:18 +00:00
Paweł Gronowski
8d9e3502ab hack: Fix TestOverlay* test failure in pkg/archive
The pkg/archive/archive_linux_test.go tests create a test archive
content in a temporary directory. This also includes device nodes (using
mknod).
Running these tests in Docker-in-Docker (dind) with systemd was failing
with "operation not permitted" because the rootfs is remounted with
`nodev`.

This change aligns `hack/dind-systemd` with `hack/dind` by
conditionally mounting a `tmpfs` on `/tmp` (with dev enabled),
to make the mknod work.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-26 12:11:44 +00:00
Paweł Gronowski
fbe2330989 Merge pull request #49693 from vvoland/ifc-to-any
Update `interface{}` to `any`
2025-03-26 11:54:35 +00:00
Rob Murray
f5d84a45cc Start containers, even when connected to a disabled bridge port
Commit 9a6e96f ("Before sending ARPs/NAs, check the bridge is ready")
introduced a check that, if a container's veth is connected to a bridge,
the port is forwarding before sending unsolicited ARP/NA messages to
advertise the container's MAC/IP addresses.

It waited for up-to 200ms, but it seems that's not always enough.

If the port isn't forwarding, the ARP/NA messages will be silently
dropped. But, if it comes up within two seconds, one or both of the
resends will succeed.

So - keep the wait for 200ms but, if anything goes wrong with checking
the bridge port's state, or it's not forwarding after that time, just
log an info/warning level message and continue.

Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-26 11:46:38 +00:00
Sebastiaan van Stijn
072ea62fcc vendor: github.com/opencontainers/image-spec v1.1.1
full diff: https://github.com/opencontainers/image-spec/compare/v1.1.0...v1.1.1

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-26 10:01:40 +01:00
Sebastiaan van Stijn
454a7a7358 Merge pull request #49678 from vvoland/c8d-events-tag
c8d/builder: Fix missing `image tag` event with BuildKit
2025-03-25 20:36:26 +01:00
Paweł Gronowski
a60603bfa3 hack/validate: Add gocompat
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-25 16:10:42 +01:00
Sebastiaan van Stijn
2be7f48561 implement module compatibility check
This package imports all "importable" packages, i.e., packages that:

- are not applications ("main")
- are not internal
- and that have non-test go-files

We do this to verify that our code can be consumed as a dependency
in "module mode". When using a dependency that does not have a go.mod
(i.e.; is not a "module"), go implicitly generates a go.mod. Lacking
information from the dependency itself, it assumes "go1.16" language
(see [DefaultGoModVersion]). Starting with Go1.21, go downgrades the
language version used for such dependencies, which means that any
language feature used that is not supported by go1.16 results in a
compile error;

    # github.com/docker/cli/cli/context/store
    /go/pkg/mod/github.com/docker/cli@v25.0.0-beta.2+incompatible/cli/context/store/storeconfig.go:6:24: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
    /go/pkg/mod/github.com/docker/cli@v25.0.0-beta.2+incompatible/cli/context/store/store.go:74:12: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)

These errors do NOT occur when using GOPATH mode, nor do they occur
when using "pseudo module mode" (the "-mod=mod -modfile=vendor.mod"
approach used in this repository).

As a workaround for this situation, we must include "//go:build" comments
in any file that uses newer go-language features (such as the "any" type
or the "min()", "max()" builtins).

From the go toolchain docs (https://go.dev/doc/toolchain):

> The go line for each module sets the language version the compiler enforces
> when compiling packages in that module. The language version can be changed
> on a per-file basis by using a build constraint.
>
> For example, a module containing code that uses the Go 1.21 language version
> should have a go.mod file with a go line such as go 1.21 or go 1.21.3.
> If a specific source file should be compiled only when using a newer Go
> toolchain, adding //go:build go1.22 to that source file both ensures that
> only Go 1.22 and newer toolchains will compile the file and also changes
> the language version in that file to Go 1.22.

This file is a generated module that imports all packages provided in
the repository, which replicates an external consumer using our code
as a dependency in go-module mode, and verifies all files in those
packages have the correct "//go:build <go language version>" set.

To test this package:

    make -C ./internal/gocompat/
    GO111MODULE=off go generate .
    go mod tidy
    go test -v
    # github.com/docker/docker/libnetwork/options
    ../../libnetwork/options/options.go:45:25: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
    # github.com/docker/docker/libnetwork/internal/setmatrix
    ../../libnetwork/internal/setmatrix/setmatrix.go:13:16: type parameter requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/internal/setmatrix/setmatrix.go:13:18: predeclared comparable requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/internal/setmatrix/setmatrix.go:14:20: type instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/internal/setmatrix/setmatrix.go:20:10: type instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/internal/setmatrix/setmatrix.go:31:10: type instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/internal/setmatrix/setmatrix.go:43:10: type instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/internal/setmatrix/setmatrix.go:59:10: type instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/internal/setmatrix/setmatrix.go:80:10: type instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/internal/setmatrix/setmatrix.go:93:10: type instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/internal/setmatrix/setmatrix.go:104:10: type instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/internal/setmatrix/setmatrix.go:104:10: too many errors
    # github.com/docker/docker/libnetwork/config
    ../../libnetwork/config/config.go:35:47: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/config/config.go:47:41: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/config/config.go:63:55: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../libnetwork/config/config.go:95:63: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
    # github.com/docker/docker/testutil
    ../../testutil/helpers.go:80:9: predeclared any requires go1.18 or later (-lang was set to go1.16; check go.mod)
    # github.com/docker/docker/builder/builder-next/adapters/containerimage
    ../../builder/builder-next/adapters/containerimage/pull.go:72:4: type instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    ../../builder/builder-next/adapters/containerimage/pull.go:200:19: type instantiation requires go1.18 or later (-lang was set to go1.16; check go.mod)
    FAIL	gocompat [build failed]
    make: *** [Makefile:5: verify] Error 1

[DefaultGoModVersion]: 58c28ba286/src/cmd/go/internal/gover/version.go (L15-L24)
[2]: https://go.dev/doc/toolchain

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-25 16:10:42 +01:00
Sebastiaan van Stijn
6430e49a55 Merge pull request #49700 from vvoland/missing-buildtags
Add missing go1.22 build constraints
2025-03-25 14:53:08 +01:00
Paweł Gronowski
cc90726fb8 Add missing go1.22 build constraints
Some recent changes used a newer Go features.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-25 13:45:47 +01:00
Paweł Gronowski
19a0f886da testutil: Update to any from interface{}
Only files that have go build version enforcing tag

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-25 13:42:53 +01:00
Paweł Gronowski
f14c23a90f libnetwork: Update to any from interface{}
Only files that have go build version enforcing tag

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-25 13:42:51 +01:00
Paweł Gronowski
82ec984d10 daemon: Update to any from interface{}
Only files that have go build version enforcing tag

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-25 13:38:28 +01:00
Paweł Gronowski
003bf197d7 container: Update to any from interface{}
Only files that have go build version enforcing tag

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-25 13:38:24 +01:00
Paweł Gronowski
444a1597ff c8d/builder: Fix missing image tag event with BuildKit
The builder `Named` callback was not called with the containerd image
store integration enabled and BuildKit due to wrong imageexporter output
key being used.

We have a test `TestBuildEmitsEvents` that should have detected the bug,
but it wasn't actually working because the CLI version used in the
`integration-cli` didn't support BuildKit yet.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-25 12:02:52 +01:00
Sebastiaan van Stijn
330857ad0f Merge pull request #49698 from jsternberg/buildkit-0.20.2
vendor: github.com/moby/buildkit v0.20.2
2025-03-25 01:30:05 +01:00
Jonathan A. Sternberg
2fce935df2 vendor: github.com/moby/buildkit v0.20.2
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2025-03-24 15:53:53 -05:00
Akihiro Suda
ecb03c4cda Merge pull request #49691 from thaJeztah/bump_selinux
vendor: github.com/opencontainers/selinux v1.12.0
2025-03-24 20:18:38 +09:00
Akihiro Suda
accda3119d Merge pull request #49562 from thaJeztah/switch_cgroups
switch to github.com/opencontainers/cgroups
2025-03-24 20:08:41 +09:00
Paweł Gronowski
7c09e4e607 TestBuildEmitsEvents: Skip Windows only for buildkit
The test was always skipped on Windows, regardless if buildkit is used
or not.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-24 11:55:30 +01:00
Paweł Gronowski
99356b6e17 integration-cli/TestBuildEmitsEvents: Verify event count
Make sure that the events are not sent twice

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-03-24 11:55:28 +01:00
Paweł Gronowski
6a0f71cac9 Merge pull request #49686 from thaJeztah/attach_nits
daemon, api/router: minor cleanups in attach and logging code
2025-03-24 10:53:47 +00:00
Paweł Gronowski
e2011affd4 Merge pull request #49692 from thaJeztah/rm_aliases
remove some redundant import-aliases
2025-03-24 10:37:55 +00:00
Sebastiaan van Stijn
3e957c6240 remove some redundant import-aliases
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-24 00:43:31 +01:00
Sebastiaan van Stijn
4db84b197d switch to github.com/opencontainers/cgroups
The runc libcontainer/cgroups package was moved to a separate
module; switch our use of the runc module to use the new
location.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-24 00:36:25 +01:00
Sebastiaan van Stijn
697956a8c7 vendor: github.com/opencontainers/selinux v1.12.0
This release removes deprecated functions from the `label` package,
and improves documentation and error reporting of `SetCreateKey`.

Relevant changes:

-label: remove deprecated stuff
-Improve SetKeyCreate error reporting

full diff: https://github.com/opencontainers/selinux/compare/v1.11.1...v1.12.0

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-24 00:30:46 +01:00
Akihiro Suda
c1cd4e5eb4 Merge pull request #49683 from thaJeztah/vendor_ebpf
vendor: github.com/cilium/ebpf v0.17.3
2025-03-24 08:27:46 +09:00
Akihiro Suda
f6a642f588 Merge pull request #49689 from thaJeztah/dockerfile_update_registry
Dockerfile: update registry to v3.0.0-rc.4
2025-03-24 08:27:12 +09:00
Akihiro Suda
69a307600d Merge pull request #49690 from thaJeztah/bump_jwt
vendor: github.com/golang-jwt/jwt/v5 v5.2.2
2025-03-24 08:26:49 +09:00
Sebastiaan van Stijn
34bc972519 vendor: github.com/golang-jwt/jwt/v5 v5.2.2
Fixes [GHSA-mh63-6h87-95cp] / [CVE-2025-30204]

full diff: https://github.com/golang-jwt/jwt/compare/v5.2.1...v5.2.2

[GHSA-mh63-6h87-95cp]: https://github.com/golang-jwt/jwt/security/advisories/GHSA-mh63-6h87-95cp
[CVE-2025-30204]: https://www.cve.org/CVERecord?id=CVE-2025-30204

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-23 17:34:42 +01:00
Akihiro Suda
06e319e210 Merge pull request #49687 from thaJeztah/update_delve
Dockerfile: upgrade Delve to v1.24.1
2025-03-24 00:22:41 +09:00
Akihiro Suda
108d7d1004 Merge pull request #49681 from thaJeztah/vendor_runc
vendor: github.com/opencontainers/runc v1.2.6
2025-03-24 00:21:49 +09:00
Sebastiaan van Stijn
c02ca31fbc Merge pull request #49675 from AkihiroSuda/dockerfile-simple
Dockerfile.simple: avoid `Could not find installer for "proxy"`
2025-03-23 15:01:37 +01:00
Sebastiaan van Stijn
d01ee23c15 Dockerfile: update registry to v3.0.0-rc.4
release notes: https://github.com/distribution/distribution/releases/tag/v3.0.0-rc.4
full diff: https://github.com/distribution/distribution/compare/v3.0.0-rc.1...v3.0.0-rc.4

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-23 14:57:19 +01:00
Sebastiaan van Stijn
081987b647 Dockerfile: disable saving Golang telemetry in dev-container
Disable collecting local telemetry, as collected by Go and Delve;

- https://github.com/go-delve/delve/blob/v1.24.1/CHANGELOG.md#1231-2024-09-23
- https://go.dev/doc/telemetry#background

Telemetry is only collected, and not sent by default, so let's skip producing
it in the first place, as the dev-container is an ephemeral environment, and
this telemetry is not used.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-23 14:46:25 +01:00
Sebastiaan van Stijn
af14f3e7d3 Dockerfile: upgrade Delve to v1.24.1
Update to the latest version:

- https://github.com/go-delve/delve/releases/tag/v1.24.1
- https://github.com/go-delve/delve/blob/v1.24.1/CHANGELOG.md#1241-2025-03-05

Also update links to supported platforms. Delve v1.21.1 and higher now supports
linux/ppc64le (added in [delve@71f1220]), but this looks to be gated behind
an experimental build-tag. We could consider enabling this tag, but skipping
that for now.

[delve@71f1220]: 71f1220717

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-23 14:29:28 +01:00
Sebastiaan van Stijn
d0b4bdbd25 api/router: postContainersAttach, wsContainersAttach: minor cleanups
- remove intermediate variables that were only used once
- move variables closer to where used

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-23 13:29:28 +01:00
Sebastiaan van Stijn
73aa7e933c daemon: daemon.containerAttach: use structured logs
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-23 13:29:27 +01:00
Sebastiaan van Stijn
d494520aa0 daemon: daemon.ContainerAttach: use Println instead of Printf
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-23 13:21:23 +01:00
Sebastiaan van Stijn
183ca46099 daemon: daemon.ContainerLogs: move vars closer to where used
- remove intermediate variable that was only used once
- move "follow" variable to where it's used; keeping an intermediate
  variable for now, as the logic related to "follow" and "created"
  could use some comment / documentation.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-23 13:11:39 +01:00
Sebastiaan van Stijn
c164eec7e9 daemon: daemon.ContainerAttach: move vars closer to where used
- remove intermediate err vars
- move "multiplexed" variable closer to where used

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-23 13:11:39 +01:00
Sebastiaan van Stijn
f7853799fc daemon: daemon.containerAttach: remove redundant defers
Both these defers were defined in the closure, and would be executed
at the end of the goroutine; inline them to prevent them being confused
for being executed after the function starting the goroutine.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-23 13:11:39 +01:00
Sebastiaan van Stijn
80bf93c9d7 daemon: daemon.containerAttach: rename vars for clarity and prevent shadow
- rename var that shadowed argument
- use consistent name for container arg; We use `ctr` as short name in most
  places; use the same name to make the code slightly more readable.
- rename "logs" argument to prevent it being confused with a logs import
  and to more clearly indicate its a bool

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-23 13:11:29 +01:00
Akihiro Suda
e1e6d35277 Merge pull request #49682 from thaJeztah/bump_runc_binary_1.2.6
Dockerfile: update runc binary to v1.2.6
2025-03-22 03:21:17 +09:00
Sebastiaan van Stijn
daeb6fb0b7 vendor: github.com/cilium/ebpf v0.17.3
full diff: https://github.com/cilium/ebpf/compare/v0.16.0...v0.17.3

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-21 17:02:01 +01:00
Sebastiaan van Stijn
eeee17eaad Dockerfile: update runc binary to v1.2.6
This is the sixth patch release in the 1.2.z series of runc.
It primarily fixes an issue with runc exec vs time namespace,
and a compatibility issue with older kernels.

* Fix a stall issue that would happen if setting `O_CLOEXEC` with
  `CloseExecFrom` failed.
* `runc` now properly handles joining time namespaces (such as with
  `runc exec`). Previously we would attempt to set the time offsets
  when joining, which would fail.
* Handle `EINTR` retries correctly for socket-related direct
  `golang.org/x/sys/unix` system calls.
* We no longer use `F_SEAL_FUTURE_WRITE` when sealing the runc binary, as it
  turns out this had some unfortunate bugs in older kernel versions and was
  never necessary in the first place.
* Remove `Fexecve` helper from `libcontainer/system`. Runc 1.2.1 removed
  runc-dmz, but we forgot to remove this helper added only for that.
* Use Go 1.23 for official builds, run CI with Go 1.24 and drop Ubuntu 20.04
  from CI. We need to drop Ubuntu 20.04 from CI because Github Actions
  announced it's already deprecated and it will be discontinued soon.

full diff: https://github.com/opencontainers/runc/compare/v1.2.5...v1.2.6

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-21 16:54:24 +01:00
Sebastiaan van Stijn
c1c5f16b8b vendor: github.com/opencontainers/runc v1.2.6
This is the sixth patch release in the 1.2.z series of runc.
It primarily fixes an issue with runc exec vs time namespace,
and a compatibility issue with older kernels.

* Fix a stall issue that would happen if setting `O_CLOEXEC` with
  `CloseExecFrom` failed.
* `runc` now properly handles joining time namespaces (such as with
  `runc exec`). Previously we would attempt to set the time offsets
  when joining, which would fail.
* Handle `EINTR` retries correctly for socket-related direct
  `golang.org/x/sys/unix` system calls.
* We no longer use `F_SEAL_FUTURE_WRITE` when sealing the runc binary, as it
  turns out this had some unfortunate bugs in older kernel versions and was
  never necessary in the first place.
* Remove `Fexecve` helper from `libcontainer/system`. Runc 1.2.1 removed
  runc-dmz, but we forgot to remove this helper added only for that.
* Use Go 1.23 for official builds, run CI with Go 1.24 and drop Ubuntu 20.04
  from CI. We need to drop Ubuntu 20.04 from CI because Github Actions
  announced it's already deprecated and it will be discontinued soon.

full diff: https://github.com/opencontainers/runc/compare/v1.2.5...v1.2.6

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-21 16:49:42 +01:00
Sebastiaan van Stijn
be6e92a57b pkg/atomicwriter: use sequential file access on Windows
Using sequential file access ([FILE_FLAG_SEQUENTIAL_SCAN]) prevents
Windows from aggressively keeping files in the cache, freeing up system
memory for other tasks. On Linux, these changes have no effect, as the
sequential package use the standard (os.CreateTemp, os.OpenFile) on
non-Windows platforms. Refer to the [Win32 API documentation] for details
on sequential file access.

[Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN
[FILE_FLAG_SEQUENTIAL_SCAN]: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea#FILE_FLAG_SEQUENTIAL_SCAN

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-21 16:39:28 +01:00
Akihiro Suda
ef56b83597 Merge pull request #49670 from thaJeztah/integration_cli_fixes
integration-cli: minor fixes
2025-03-21 23:48:45 +09:00
Akihiro Suda
452ff75159 Dockerfile.simple: avoid Could not find installer for "proxy"
`Could not find installer for "proxy"` error had been ignored
due to lack of `set -e`

Signed-off-by: Akihiro Suda <akihiro.suda.cz@hco.ntt.co.jp>
2025-03-21 06:35:49 +09:00
Jonathan A. Sternberg
fa21996da5 containerd: prioritize non-dangling images with image list
When listing images, prioritize the tagged version. When computing the
unique images, the last returned image would be used as a base and repo
tags would be merged into it.

This makes it so `RepoDigests` has the correct value when there is both
a dangling and non-dangling version of the same image.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2025-03-20 14:59:33 -05:00
Sebastiaan van Stijn
126d4cf672 client: remove version-gate for JSON response errors
JSON errors were introduced in API 1.24, and daemons running older versions of
the API would return errors as plain-text. However, such API versions would
also send the corresponding content-type header (text/plain), so we don't
really need to make the code version-dependent; there's already fallbacks
in place to handle JSON-responses that don't use the expected format, in
which case we produce a generic status-code error.

Before this patch, the client would print JSON-responses as-is when the
daemon returned an "API version too old" error;

    DOCKER_API_VERSION=v1.10 docker info --format '{{.ID}}'
    Error response from daemon: {"message":"client version 1.10 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version"}

With this patch, the client detects that the response is JSON, and prints
a friendlier error-message to help the user discover their client is too
old;

    DOCKER_API_VERSION=v1.10 docker info --format '{{.ID}}'
    Error response from daemon: client version 1.10 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-20 20:25:11 +01:00
Sebastiaan van Stijn
230f178f8b api: return plain-text errors for deprecated API versions
Docker 25.0 (08e4e88482) deprecated API versions
older than v1.24, and support was removed in Docker 26.0.

As part of this deprecation, support for plain-text errors was also removed
in commit ffd877f948.

So while we no longer support API versions older 1.24 [api.MinSupportedAPIVersion],
a client may try to connect using an older version and expect a plain-text error
instead of a JSON error. This would result in an "API version too old" error
formatted in JSON being printed as-is.

    DOCKER_API_VERSION=v1.10 docker info --format '{{.ID}}'
    Error response from daemon: {"message":"client version 1.10 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version"}

    curl --unix-socket /var/run/docker.sock http://localhost/v1.10/info
    {"message":"client version 1.10 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version"}

Note that this was only a problem for old API versions; unsupported API versions
that were higher than the maximum version were already handled as JSON;

    DOCKER_API_VERSION=v1.99 docker info --format '{{.ID}}'
    Error response from daemon: client version 1.99 is too new. Maximum supported API version is 1.48

    curl --unix-socket /var/run/docker.sock http://localhost/v1.99/info
    {"message":"client version 1.99 is too new. Maximum supported API version is 1.48"}

Let's be nice, and return errors in plain-text to provide a more readable error
to help the user understand the API version they're using is no longer supported.

With this patch applied:

    DOCKER_API_VERSION=v1.10 docker info --format '{{.ID}}'
    Error response from daemon: client version 1.10 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version

    curl --unix-socket /var/run/docker.sock http://localhost/v1.10/info
    client version 1.10 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-20 20:25:05 +01:00
Sebastiaan van Stijn
c7fbe1c2ba integration-cli: fix duplicate close of body
request.ReadBody already closes the body;

    time="2025-03-20T19:08:25Z" level=error msg="subsequent attempt to close ReadCloserWrapper"

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-20 20:20:22 +01:00
Sebastiaan van Stijn
1c00755826 integration-cli: fix some unhandled errors
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-20 20:20:22 +01:00
Sebastiaan van Stijn
7b964974e7 Merge pull request #49619 from thaJeztah/atomicwriter_validate
pkg/atomicwriter: fix tempfiles cleanup, improve tests, and validate destination path
2025-03-20 18:24:42 +01:00
Paweł Gronowski
e4079dbbf1 Merge pull request #49660 from thaJeztah/journald_noshadow
daemon/logger/journald: rename func that shadowed builtin
2025-03-20 15:49:03 +00:00
Paweł Gronowski
770200d154 Merge pull request #49648 from robmry/combine_bridge_firewalld_reload_calls
Combine bridge firewalld reload calls
2025-03-20 15:42:51 +00:00
Sebastiaan van Stijn
8be5696c37 daemon/logger/journald: rename func that shadowed builtin
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-19 12:02:59 +01:00
Rob Murray
485cb90b77 Remove duplicate iptables-enabled checks
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-17 10:31:11 +00:00
Rob Murray
fce915897c Combine firewalld reload callbacks for IPv4/IPv6
Signed-off-by: Rob Murray <rob.murray@docker.com>
2025-03-17 10:30:45 +00:00
Sebastiaan van Stijn
1daeaec333 pkg/atomicwriter: validate destination path
- Disallow empty filenames
- Don't allow writing to a directory
- Return early if parent dir doesn't exist
- TBD: do we want to allow symlinks to be followed, or disallow?

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-10 18:23:02 +01:00
Sebastiaan van Stijn
084b7cec1a pkg/atomicwriter: add additional test-cases
- test errors returned for non-existing destination
- test that files are cleaned up after
- test writing to a symlinked file (to be fixed)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-10 17:58:51 +01:00
Sebastiaan van Stijn
ff061e28c1 pkg/atomicwriter: don't overwrite destination on close without write
Creating a writer (`atomicwriter.New()`) and closing it without a write
ever happening, would replace the destination file with an empty file.

This patch adds a check whether a write was performed (either successful
or unsuccessful); if no write happened, we cleanup the tempfile without
replacing the destination file.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-10 17:58:46 +01:00
Sebastiaan van Stijn
88a5bca43c pkg/atomicwriter: add separate tests for New()
We were testing this function implicitly through `TestWriteFile`, but
not verifying the behavior of `New` in isolation. Add separate tests
for this function.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-10 17:58:11 +01:00
Sebastiaan van Stijn
09e804f570 pkg/atomicwriter: refactor tests
- rename tests to match the function tested
- remove init func in favor or a test-helper
- rename some vars to prevent shadowing
- update example values to be more descriptive
- add a utility for asserting file content and mode

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-10 17:57:17 +01:00
Sebastiaan van Stijn
0823d76ec5 client: keep image refs in canonical format where possible
Using "familiarname" (e.g. "ubuntu") should be mostly done for presenting
image refernces to the user, but internally, we should use the canonical
format where possible ("docker.io/library/ubuntu").

There's still many places where we use the familiar (short) form, but
let's start with not converting references in the client.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-03-09 16:52:21 +01:00
785 changed files with 33299 additions and 13433 deletions

View File

@@ -21,7 +21,7 @@ on:
default: "graphdriver"
env:
GO_VERSION: "1.23.7"
GO_VERSION: "1.23.8"
GOTESTLIST_VERSION: v0.3.1
TESTSTAT_VERSION: v0.1.25
ITG_CLI_MATRIX_SIZE: 6
@@ -47,7 +47,6 @@ jobs:
script: |
let includes = [
{ mode: '' },
{ mode: 'rootless' },
{ mode: 'systemd' },
];
if ("${{ inputs.storage }}" == "snapshotter") {
@@ -84,9 +83,13 @@ jobs:
run: |
CACHE_DEV_SCOPE=dev
if [[ "${{ matrix.mode }}" == *"firewalld"* ]]; then
echo "DOCKER_FIREWALLD=true" >> $GITHUB_ENV
echo "FIREWALLD=true" >> $GITHUB_ENV
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}firewalld"
fi
if [[ "${{ matrix.mode }}" == *"systemd"* ]]; then
echo "SYSTEMD=true" >> $GITHUB_ENV
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}systemd"
fi
echo "CACHE_DEV_SCOPE=${CACHE_DEV_SCOPE}" >> $GITHUB_ENV
-
name: Set up Docker Buildx
@@ -219,7 +222,7 @@ jobs:
retention-days: 1
integration-flaky:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
timeout-minutes: 120 # guardrails timeout for the whole job
continue-on-error: ${{ github.event_name != 'pull_request' }}
steps:
@@ -264,14 +267,12 @@ jobs:
with:
script: |
let includes = [
{ os: 'ubuntu-20.04', mode: '' },
{ os: 'ubuntu-20.04', mode: 'rootless' },
{ os: 'ubuntu-20.04', mode: 'systemd' },
{ os: 'ubuntu-24.04', mode: '' },
{ os: 'ubuntu-22.04', mode: '' },
{ os: 'ubuntu-22.04', mode: 'rootless' },
{ os: 'ubuntu-22.04', mode: 'systemd' },
{ os: 'ubuntu-24.04', mode: '' },
// { os: 'ubuntu-24.04', mode: 'rootless' }, // FIXME: https://github.com/moby/moby/pull/49579#issuecomment-2698622223
{ os: 'ubuntu-24.04', mode: 'systemd' },
// { os: 'ubuntu-20.04', mode: 'rootless-systemd' }, // FIXME: https://github.com/moby/moby/issues/44084
// { os: 'ubuntu-24.04', mode: 'rootless-systemd' }, // FIXME: https://github.com/moby/moby/issues/44084
];
if ("${{ inputs.storage }}" == "snapshotter") {
@@ -318,7 +319,7 @@ jobs:
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}systemd"
fi
if [[ "${{ matrix.mode }}" == *"firewalld"* ]]; then
echo "DOCKER_FIREWALLD=true" >> $GITHUB_ENV
echo "FIREWALLD=true" >> $GITHUB_ENV
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}firewalld"
fi
echo "CACHE_DEV_SCOPE=${CACHE_DEV_SCOPE}" >> $GITHUB_ENV
@@ -485,7 +486,7 @@ jobs:
echo ${{ steps.set.outputs.matrix }}
integration-cli:
runs-on: ubuntu-20.04
runs-on: ubuntu-24.04
timeout-minutes: 120 # guardrails timeout for the whole job
continue-on-error: ${{ github.event_name != 'pull_request' }}
needs:
@@ -508,7 +509,7 @@ jobs:
run: |
CACHE_DEV_SCOPE=dev
if [[ "${{ matrix.mode }}" == *"firewalld"* ]]; then
echo "DOCKER_FIREWALLD=true" >> $GITHUB_ENV
echo "FIREWALLD=true" >> $GITHUB_ENV
CACHE_DEV_SCOPE="${CACHE_DEV_SCOPE}firewalld"
fi
echo "CACHE_DEV_SCOPE=${CACHE_DEV_SCOPE}" >> $GITHUB_ENV

View File

@@ -28,7 +28,7 @@ on:
default: false
env:
GO_VERSION: "1.23.7"
GO_VERSION: "1.23.8"
GOTESTLIST_VERSION: v0.3.1
TESTSTAT_VERSION: v0.1.25
WINDOWS_BASE_IMAGE: mcr.microsoft.com/windows/servercore

View File

@@ -23,7 +23,7 @@ on:
pull_request:
env:
GO_VERSION: "1.23.7"
GO_VERSION: "1.23.8"
TESTSTAT_VERSION: v0.1.25
DESTDIR: ./build
SETUP_BUILDX_VERSION: edge

View File

@@ -23,7 +23,7 @@ on:
pull_request:
env:
GO_VERSION: "1.23.7"
GO_VERSION: "1.23.8"
DESTDIR: ./build
SETUP_BUILDX_VERSION: edge
SETUP_BUILDKIT_IMAGE: moby/buildkit:latest

View File

@@ -154,3 +154,23 @@ jobs:
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ env.DESTDIR }}/govulncheck.out
build-dind:
runs-on: ubuntu-24.04
needs:
- validate-dco
steps:
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
version: ${{ env.SETUP_BUILDX_VERSION }}
driver-opts: image=${{ env.SETUP_BUILDKIT_IMAGE }}
buildkitd-flags: --debug
-
name: Build dind image
uses: docker/bake-action@v6
with:
targets: dind
set: |
*.output=type=cacheonly

View File

@@ -58,7 +58,7 @@ jobs:
- name: Update Go
uses: actions/setup-go@v5
with:
go-version: "1.23.7"
go-version: "1.23.8"
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:

View File

@@ -23,7 +23,7 @@ on:
pull_request:
env:
GO_VERSION: "1.23.7"
GO_VERSION: "1.23.8"
GIT_PAGER: "cat"
PAGER: "cat"
SETUP_BUILDX_VERSION: edge

View File

@@ -40,7 +40,7 @@ linters:
run:
# prevent golangci-lint from deducting the go version to lint for through go.mod,
# which causes it to fallback to go1.17 semantics.
go: "1.23.7"
go: "1.23.8"
concurrency: 2
# Only supported with go modules enabled (build flag -mod=vendor only valid when using modules)
# modules-download-mode: vendor
@@ -212,6 +212,11 @@ issues:
linters:
- staticcheck
# FIXME(thaJeztah): ignoring these transitional utilities until BuildKit is vendored with https://github.com/moby/moby/pull/49743
- text: "SA1019: idtools\\.(ToUserIdentityMapping|FromUserIdentityMapping) is deprecated"
linters:
- staticcheck
# Ignore "nested context in function literal (fatcontext)" as we intentionally set up tracing on a base-context for tests.
# FIXME(thaJeztah): see if there's a more iodiomatic way to do this.
- text: 'nested context in function literal'

View File

@@ -293,6 +293,7 @@ Brandon Liu <bdon@bdon.org>
Brandon Philips <brandon.philips@coreos.com>
Brandon Rhodes <brandon@rhodesmill.org>
Brendan Dixon <brendand@microsoft.com>
Brendon Smith <bws@bws.bio>
Brennan Kinney <5098581+polarathene@users.noreply.github.com>
Brent Salisbury <brent.salisbury@docker.com>
Brett Higgins <brhiggins@arbor.net>
@@ -347,6 +348,7 @@ Casey Bisson <casey.bisson@joyent.com>
Catalin Pirvu <pirvu.catalin94@gmail.com>
Ce Gao <ce.gao@outlook.com>
Cedric Davies <cedricda@microsoft.com>
Cesar Talledo <cesar.talledo@docker.com>
Cezar Sa Espinola <cezarsa@gmail.com>
Chad Swenson <chadswen@gmail.com>
Chance Zibolski <chance.zibolski@gmail.com>
@@ -1281,6 +1283,7 @@ Krasi Georgiev <krasi@vip-consult.solutions>
Krasimir Georgiev <support@vip-consult.co.uk>
Kris-Mikael Krister <krismikael@protonmail.com>
Kristian Haugene <kristian.haugene@capgemini.com>
Kristian Heljas <kristian@kristian.ee>
Kristina Zabunova <triara.xiii@gmail.com>
Krystian Wojcicki <kwojcicki@sympatico.ca>
Kunal Kushwaha <kushwaha_kunal_v7@lab.ntt.co.jp>
@@ -1712,6 +1715,7 @@ Patrick Hemmer <patrick.hemmer@gmail.com>
Patrick St. laurent <patrick@saint-laurent.us>
Patrick Stapleton <github@gdi2290.com>
Patrik Cyvoct <patrik@ptrk.io>
Patrik Leifert <patrikleifert@hotmail.com>
pattichen <craftsbear@gmail.com>
Paul "TBBle" Hampson <Paul.Hampson@Pobox.com>
Paul <paul9869@gmail.com>

View File

@@ -1,6 +1,6 @@
# syntax=docker/dockerfile:1.7
ARG GO_VERSION=1.23.7
ARG GO_VERSION=1.23.8
ARG BASE_DEBIAN_DISTRO="bookworm"
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
ARG XX_VERSION=1.6.1
@@ -13,7 +13,7 @@ ARG DOCKERCLI_REPOSITORY="https://github.com/docker/cli.git"
# cli version used for integration-cli tests
ARG DOCKERCLI_INTEGRATION_REPOSITORY="https://github.com/docker/cli.git"
ARG DOCKERCLI_INTEGRATION_VERSION=v17.06.2-ce
ARG DOCKERCLI_INTEGRATION_VERSION=v18.06.3-ce
# BUILDX_VERSION is the version of buildx to install in the dev container.
ARG BUILDX_VERSION=0.20.1
ARG COMPOSE_VERSION=v2.33.1
@@ -26,11 +26,16 @@ ARG DOCKER_STATIC=1
# https://hub.docker.com/r/distribution/distribution. This version of
# the registry is used to test schema 2 manifests. Generally, the version
# specified here should match a current release.
ARG REGISTRY_VERSION=3.0.0-rc.1
ARG REGISTRY_VERSION=3.0.0
# delve is currently only supported on linux/amd64 and linux/arm64;
# https://github.com/go-delve/delve/blob/v1.8.1/pkg/proc/native/support_sentinel.go#L1-L6
ARG DELVE_SUPPORTED=${TARGETPLATFORM#linux/amd64} DELVE_SUPPORTED=${DELVE_SUPPORTED#linux/arm64}
# https://github.com/go-delve/delve/blob/v1.24.1/pkg/proc/native/support_sentinel.go#L1
# https://github.com/go-delve/delve/blob/v1.24.1/pkg/proc/native/support_sentinel_linux.go#L1
#
# ppc64le support was added in v1.21.1, but is still experimental, and requires
# the "-tags exp.linuxppc64le" build-tag to be set:
# https://github.com/go-delve/delve/commit/71f12207175a1cc09668f856340d8a543c87dcca
ARG DELVE_SUPPORTED=${TARGETPLATFORM#linux/amd64} DELVE_SUPPORTED=${DELVE_SUPPORTED#linux/arm64} DELVE_SUPPORTED=${DELVE_SUPPORTED#linux/ppc64le}
ARG DELVE_SUPPORTED=${DELVE_SUPPORTED:+"unsupported"}
ARG DELVE_SUPPORTED=${DELVE_SUPPORTED:-"supported"}
@@ -47,6 +52,11 @@ COPY --from=build-dummy /build /build
# base
FROM --platform=$BUILDPLATFORM ${GOLANG_IMAGE} AS base
COPY --from=xx / /
# Disable collecting local telemetry, as collected by Go and Delve;
#
# - https://github.com/go-delve/delve/blob/v1.24.1/CHANGELOG.md#1231-2024-09-23
# - https://go.dev/doc/telemetry#background
RUN go telemetry off && [ "$(go telemetry)" = "off" ] || { echo "Failed to disable Go telemetry"; exit 1; }
RUN echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
RUN apt-get update && apt-get install --no-install-recommends -y file
ENV GO111MODULE=off
@@ -153,7 +163,7 @@ RUN git init . && git remote add origin "https://github.com/go-delve/delve.git"
# from the https://github.com/go-delve/delve repository.
# It can be used to run Docker with a possibility of
# attaching debugger to it.
ARG DELVE_VERSION=v1.23.0
ARG DELVE_VERSION=v1.24.1
RUN git fetch -q --depth 1 origin "${DELVE_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
FROM base AS delve-supported
@@ -279,7 +289,7 @@ RUN git init . && git remote add origin "https://github.com/opencontainers/runc.
# that is used. If you need to update runc, open a pull request in the containerd
# project first, and update both after that is merged. When updating RUNC_VERSION,
# consider updating runc in vendor.mod accordingly.
ARG RUNC_VERSION=v1.2.5
ARG RUNC_VERSION=v1.2.6
RUN git fetch -q --depth 1 origin "${RUNC_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
FROM base AS runc-build
@@ -498,7 +508,6 @@ RUN --mount=type=cache,sharing=locked,id=moby-dev-aptlib,target=/var/lib/apt \
--mount=type=cache,sharing=locked,id=moby-dev-aptcache,target=/var/cache/apt \
apt-get update && apt-get install -y --no-install-recommends \
firewalld
RUN sed -i 's/FirewallBackend=nftables/FirewallBackend=iptables/' /etc/firewalld/firewalld.conf
FROM dev-firewalld-${FIREWALLD} AS dev-base
RUN groupadd -r docker
@@ -648,6 +657,15 @@ FROM dev-base AS devcontainer
COPY --link . .
COPY --link --from=gopls /build/ /usr/local/bin/
# usage:
# > docker buildx bake dind
# > docker run -d --restart always --privileged --name devdind -p 12375:2375 docker-dind --debug --host=tcp://0.0.0.0:2375 --tlsverify=false
FROM docker:dind AS dind
COPY --link --from=dockercli /build/docker /usr/local/bin/
COPY --link --from=buildx /buildx /usr/local/libexec/docker/cli-plugins/docker-buildx
COPY --link --from=compose /docker-compose /usr/local/libexec/docker/cli-plugins/docker-compose
COPY --link --from=all / /usr/local/bin/
# usage:
# > make shell
# > SYSTEMD=true make shell

View File

@@ -5,7 +5,7 @@
# This represents the bare minimum required to build and test Docker.
ARG GO_VERSION=1.23.7
ARG GO_VERSION=1.23.8
ARG BASE_DEBIAN_DISTRO="bookworm"
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
@@ -35,10 +35,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
vim-common \
&& rm -rf /var/lib/apt/lists/*
# Install runc, containerd, tini and docker-proxy
# Install runc, containerd, and tini
# Please edit hack/dockerfile/install/<name>.installer to update them.
COPY hack/dockerfile/install hack/dockerfile/install
RUN for i in runc containerd tini proxy dockercli; \
RUN set -e; for i in runc containerd tini dockercli; \
do hack/dockerfile/install/install.sh $i; \
done
ENV PATH=/usr/local/cli:$PATH

View File

@@ -161,7 +161,7 @@ FROM ${WINDOWS_BASE_IMAGE}:${WINDOWS_BASE_IMAGE_TAG}
# Use PowerShell as the default shell
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
ARG GO_VERSION=1.23.7
ARG GO_VERSION=1.23.8
ARG GOTESTSUM_VERSION=v1.12.0
ARG GOWINRES_VERSION=v0.3.1
ARG CONTAINERD_VERSION=v1.7.27

View File

@@ -38,7 +38,6 @@ DOCKER_ENVS := \
-e DOCKERCLI_INTEGRATION_REPOSITORY \
-e DOCKER_DEBUG \
-e DOCKER_EXPERIMENTAL \
-e DOCKER_FIREWALLD \
-e DOCKER_GITCOMMIT \
-e DOCKER_GRAPHDRIVER \
-e DOCKER_LDFLAGS \
@@ -50,6 +49,7 @@ DOCKER_ENVS := \
-e DOCKER_USERLANDPROXY \
-e DOCKERD_ARGS \
-e DELVE_PORT \
-e FIREWALLD \
-e GITHUB_ACTIONS \
-e TEST_FORCE_VALIDATE \
-e TEST_INTEGRATION_DIR \
@@ -57,7 +57,6 @@ DOCKER_ENVS := \
-e TEST_INTEGRATION_FAIL_FAST \
-e TEST_SKIP_INTEGRATION \
-e TEST_SKIP_INTEGRATION_CLI \
-e TEST_IGNORE_CGROUP_CHECK \
-e TESTCOVERAGE \
-e TESTDEBUG \
-e TESTDIRS \
@@ -150,7 +149,7 @@ DOCKER_BUILD_ARGS += --build-arg=DOCKERCLI_INTEGRATION_REPOSITORY
ifdef DOCKER_SYSTEMD
DOCKER_BUILD_ARGS += --build-arg=SYSTEMD=true
endif
ifdef DOCKER_FIREWALLD
ifdef FIREWALLD
DOCKER_BUILD_ARGS += --build-arg=FIREWALLD=true
endif

View File

@@ -3,7 +3,7 @@ package api // import "github.com/docker/docker/api"
// Common constants for daemon and client.
const (
// DefaultVersion of the current REST API.
DefaultVersion = "1.48"
DefaultVersion = "1.49"
// MinSupportedAPIVersion is the minimum API version that can be supported
// by the API server, specified as "major.minor". Note that the daemon

View File

@@ -17,7 +17,7 @@ import (
// DebugRequestMiddleware dumps the request to logger
func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error) func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) (retErr error) {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
logger := log.G(ctx)
// Use a variable for fields to prevent overhead of repeatedly
@@ -28,25 +28,27 @@ func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWri
"request-url": r.RequestURI,
"vars": vars,
}
logger.WithFields(fields).Debugf("handling %s request", r.Method)
defer func() {
if retErr != nil {
handleWithLogs := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
logger.WithFields(fields).Debugf("handling %s request", r.Method)
err := handler(ctx, w, r, vars)
if err != nil {
// TODO(thaJeztah): unify this with Server.makeHTTPHandler, which also logs internal server errors as error-log. See https://github.com/moby/moby/pull/48740#discussion_r1816675574
fields["error-response"] = retErr
fields["status"] = httpstatus.FromError(retErr)
fields["error-response"] = err
fields["status"] = httpstatus.FromError(err)
logger.WithFields(fields).Debugf("error response for %s request", r.Method)
}
}()
return err
}
if r.Method != http.MethodPost {
return handler(ctx, w, r, vars)
return handleWithLogs(ctx, w, r, vars)
}
if err := httputils.CheckForJSON(r); err != nil {
return handler(ctx, w, r, vars)
return handleWithLogs(ctx, w, r, vars)
}
maxBodySize := 4096 // 4KB
if r.ContentLength > int64(maxBodySize) {
return handler(ctx, w, r, vars)
return handleWithLogs(ctx, w, r, vars)
}
body := r.Body
@@ -56,7 +58,7 @@ func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWri
b, err := bufReader.Peek(maxBodySize)
if err != io.EOF {
// either there was an error reading, or the buffer is full (in which case the request is too large)
return handler(ctx, w, r, vars)
return handleWithLogs(ctx, w, r, vars)
}
var postForm map[string]interface{}
@@ -74,7 +76,7 @@ func DebugRequestMiddleware(handler func(ctx context.Context, w http.ResponseWri
}
}
return handler(ctx, w, r, vars)
return handleWithLogs(ctx, w, r, vars)
}
}

View File

@@ -8,7 +8,7 @@ import (
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
containerpkg "github.com/docker/docker/container"
"github.com/docker/docker/pkg/archive"
"github.com/moby/go-archive"
)
// execBackend includes functions to implement to provide exec functionality.

View File

@@ -960,21 +960,17 @@ func (c *containerRouter) postContainersResize(ctx context.Context, w http.Respo
}
func (c *containerRouter) postContainersAttach(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
err := httputils.ParseForm(r)
if err != nil {
if err := httputils.ParseForm(r); err != nil {
return err
}
containerName := vars["name"]
_, upgrade := r.Header["Upgrade"]
detachKeys := r.FormValue("detachKeys")
hijacker, ok := w.(http.Hijacker)
if !ok {
return errdefs.InvalidParameter(errors.Errorf("error attaching to container %s, hijack connection missing", containerName))
}
contentType := types.MediaTypeRawStream
_, upgrade := r.Header["Upgrade"]
setupStreams := func(multiplexed bool, cancel func()) (io.ReadCloser, io.Writer, io.Writer, error) {
conn, _, err := hijacker.Hijack()
if err != nil {
@@ -1004,18 +1000,16 @@ func (c *containerRouter) postContainersAttach(ctx context.Context, w http.Respo
return ioutils.NewReadCloserWrapper(conn, closer), conn, conn, nil
}
attachConfig := &backend.ContainerAttachConfig{
if err := c.backend.ContainerAttach(containerName, &backend.ContainerAttachConfig{
GetStreams: setupStreams,
UseStdin: httputils.BoolValue(r, "stdin"),
UseStdout: httputils.BoolValue(r, "stdout"),
UseStderr: httputils.BoolValue(r, "stderr"),
Logs: httputils.BoolValue(r, "logs"),
Stream: httputils.BoolValue(r, "stream"),
DetachKeys: detachKeys,
DetachKeys: r.FormValue("detachKeys"),
MuxStreams: true,
}
if err = c.backend.ContainerAttach(containerName, attachConfig); err != nil {
}); err != nil {
log.G(ctx).WithError(err).Errorf("Handler for %s %s returned error", r.Method, r.URL.Path)
// Remember to close stream if error happens
conn, _, errHijack := hijacker.Hijack()
@@ -1037,9 +1031,6 @@ func (c *containerRouter) wsContainersAttach(ctx context.Context, w http.Respons
}
containerName := vars["name"]
var err error
detachKeys := r.FormValue("detachKeys")
done := make(chan struct{})
started := make(chan struct{})
@@ -1076,18 +1067,16 @@ func (c *containerRouter) wsContainersAttach(ctx context.Context, w http.Respons
useStderr = httputils.BoolValue(r, "stderr")
}
attachConfig := &backend.ContainerAttachConfig{
err := c.backend.ContainerAttach(containerName, &backend.ContainerAttachConfig{
GetStreams: setupStreams,
UseStdin: useStdin,
UseStdout: useStdout,
UseStderr: useStderr,
Logs: httputils.BoolValue(r, "logs"),
Stream: httputils.BoolValue(r, "stream"),
DetachKeys: detachKeys,
DetachKeys: r.FormValue("detachKeys"),
MuxStreams: false, // never multiplex, as we rely on websocket to manage distinct streams
}
err = c.backend.ContainerAttach(containerName, attachConfig)
})
close(done)
select {
case <-started:

View File

@@ -341,8 +341,22 @@ func (ir *imageRouter) getImagesByName(ctx context.Context, w http.ResponseWrite
manifests = httputils.BoolValue(r, "manifests")
}
var platform *ocispec.Platform
if r.Form.Get("platform") != "" && versions.GreaterThanOrEqualTo(httputils.VersionFromContext(ctx), "1.49") {
p, err := httputils.DecodePlatform(r.Form.Get("platform"))
if err != nil {
return errdefs.InvalidParameter(err)
}
platform = p
}
if manifests && platform != nil {
return errdefs.InvalidParameter(errors.New("conflicting options: manifests and platform options cannot both be set"))
}
imageInspect, err := ir.backend.ImageInspect(ctx, vars["name"], backend.ImageInspectOpts{
Manifests: manifests,
Platform: platform,
})
if err != nil {
return err

View File

@@ -12,7 +12,7 @@ import (
// to provide network specific functionality.
type Backend interface {
GetNetworks(filters.Args, backend.NetworkListConfig) ([]network.Inspect, error)
CreateNetwork(nc network.CreateRequest) (*network.CreateResponse, error)
CreateNetwork(ctx context.Context, nc network.CreateRequest) (*network.CreateResponse, error)
ConnectContainerToNetwork(ctx context.Context, containerName, networkName string, endpointConfig *network.EndpointSettings) error
DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error
DeleteNetwork(networkID string) error

View File

@@ -223,7 +223,7 @@ func (n *networkRouter) postNetworkCreate(ctx context.Context, w http.ResponseWr
// validate the configuration. The network will not be created but, if the
// configuration is valid, ManagerRedirectError will be returned and handled
// below.
nw, err := n.backend.CreateNetwork(create)
nw, err := n.backend.CreateNetwork(ctx, create)
if err != nil {
if _, ok := err.(libnetwork.ManagerRedirectError); !ok {
return err

View File

@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.22
package system // import "github.com/docker/docker/api/server/router/system"
import (
@@ -103,15 +106,23 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
if versions.LessThan(version, "1.47") {
// Field is omitted in API 1.48 and up, but should still be included
// in older versions, even if no values are set.
info.RegistryConfig.AllowNondistributableArtifactsCIDRs = []*registry.NetIPNet{}
info.RegistryConfig.AllowNondistributableArtifactsHostnames = []string{}
info.RegistryConfig.ExtraFields = map[string]any{
"AllowNondistributableArtifactsCIDRs": json.RawMessage(nil),
"AllowNondistributableArtifactsHostnames": json.RawMessage(nil),
}
}
if versions.LessThan(version, "1.49") {
// FirewallBackend field introduced in API v1.49.
info.FirewallBackend = nil
}
// TODO(thaJeztah): Expected commits are deprecated, and should no longer be set in API 1.49.
info.ContainerdCommit.Expected = info.ContainerdCommit.ID //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49.
info.RuncCommit.Expected = info.RuncCommit.ID //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49.
info.InitCommit.Expected = info.InitCommit.ID //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49.
if versions.LessThan(version, "1.49") {
// Expected commits are omitted in API 1.49, but should still be
// included in older versions.
info.ContainerdCommit.Expected = info.ContainerdCommit.ID //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49.
info.RuncCommit.Expected = info.RuncCommit.ID //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49.
info.InitCommit.Expected = info.InitCommit.ID //nolint:staticcheck // ignore SA1019: field is deprecated, but still used on API < v1.49.
}
if versions.GreaterThanOrEqualTo(version, "1.42") {
info.KernelMemory = false
}

View File

@@ -10,9 +10,12 @@ import (
"github.com/docker/docker/api/server/middleware"
"github.com/docker/docker/api/server/router"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/dockerversion"
"github.com/docker/docker/internal/otelutil"
"github.com/gorilla/mux"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel/baggage"
)
// versionMatcher defines a variable matcher to be parsed by the router
@@ -42,7 +45,10 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc, operation string) ht
// use intermediate variable to prevent "should not use basic type
// string as key in context.WithValue" golint errors
ctx := context.WithValue(r.Context(), dockerversion.UAStringKey{}, r.Header.Get("User-Agent"))
ua := r.Header.Get("User-Agent")
ctx := baggage.ContextWithBaggage(context.WithValue(r.Context(), dockerversion.UAStringKey{}, ua), otelutil.MustNewBaggage(
otelutil.MustNewMemberRaw(otelutil.TriggerKey, "api"),
))
r = r.WithContext(ctx)
handlerFunc := s.handlerWithGlobalMiddlewares(handler)
@@ -57,9 +63,20 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc, operation string) ht
if statusCode >= 500 {
log.G(ctx).Errorf("Handler for %s %s returned error: %v", r.Method, r.URL.Path, err)
}
_ = httputils.WriteJSON(w, statusCode, &types.ErrorResponse{
Message: err.Error(),
})
// While we no longer support API versions older 1.24 [api.MinSupportedAPIVersion],
// a client may try to connect using an older version and expect a plain-text error
// instead of a JSON error. This would result in an "API version too old" error
// formatted in JSON being printed as-is.
//
// Let's be nice, and return errors in plain-text to provide a more readable error
// to help the user understand the API version they're using is no longer supported.
if v := vars["version"]; v != "" && versions.LessThan(v, "1.24") {
http.Error(w, err.Error(), statusCode)
} else {
_ = httputils.WriteJSON(w, statusCode, &types.ErrorResponse{
Message: err.Error(),
})
}
}
}), operation).ServeHTTP
}

View File

@@ -19,10 +19,10 @@ produces:
consumes:
- "application/json"
- "text/plain"
basePath: "/v1.48"
basePath: "/v1.49"
info:
title: "Docker Engine API"
version: "1.48"
version: "1.49"
x-logo:
url: "https://docs.docker.com/assets/images/logo-docker-main.png"
description: |
@@ -55,8 +55,8 @@ info:
the URL is not supported by the daemon, a HTTP `400 Bad Request` error message
is returned.
If you omit the version-prefix, the current version of the API (v1.48) is used.
For example, calling `/info` is the same as calling `/v1.48/info`. Using the
If you omit the version-prefix, the current version of the API (v1.49) is used.
For example, calling `/info` is the same as calling `/v1.49/info`. Using the
API without a version-prefix is deprecated and will be removed in a future release.
Engine releases in the near future should support this version of the API,
@@ -6856,6 +6856,8 @@ definitions:
description: "The network pool size"
type: "integer"
example: "24"
FirewallBackend:
$ref: "#/definitions/FirewallInfo"
Warnings:
description: |
List of warnings / informational messages about missing features, or
@@ -6939,6 +6941,37 @@ definitions:
default: "plugins.moby"
example: "plugins.moby"
FirewallInfo:
description: |
Information about the daemon's firewalling configuration.
This field is currently only used on Linux, and omitted on other platforms.
type: "object"
x-nullable: true
properties:
Driver:
description: |
The name of the firewall backend driver.
type: "string"
example: "nftables"
Info:
description: |
Information about the firewall backend, provided as
"label" / "value" pairs.
<p><br /></p>
> **Note**: The information returned in this field, including the
> formatting of values and labels, should not be considered stable,
> and may change without notice.
type: "array"
items:
type: "array"
items:
type: "string"
example:
- ["ReloadedAt", "2025-01-01T00:00:00Z"]
# PluginsInfo is a temp struct holding Plugins name
# registered with docker daemon. It is used by Info struct
PluginsInfo:
@@ -6984,32 +7017,6 @@ definitions:
type: "object"
x-nullable: true
properties:
AllowNondistributableArtifactsCIDRs:
description: |
List of IP ranges to which nondistributable artifacts can be pushed,
using the CIDR syntax [RFC 4632](https://tools.ietf.org/html/4632).
<p><br /></p>
> **Deprecated**: Pushing nondistributable artifacts is now always enabled
> and this field is always `null`. This field will be removed in a API v1.49.
type: "array"
items:
type: "string"
example: []
AllowNondistributableArtifactsHostnames:
description: |
List of registry hostnames to which nondistributable artifacts can be
pushed, using the format `<hostname>[:<port>]` or `<IP address>[:<port>]`.
<p><br /></p>
> **Deprecated**: Pushing nondistributable artifacts is now always enabled
> and this field is always `null`. This field will be removed in a API v1.49.
type: "array"
items:
type: "string"
example: []
InsecureRegistryCIDRs:
description: |
List of IP ranges of insecure registries, using the CIDR syntax
@@ -7179,13 +7186,6 @@ definitions:
description: "Actual commit ID of external tool."
type: "string"
example: "cfb82a876ecc11b5ca0977d1733adbe58599088a"
Expected:
description: |
Commit ID of external tool expected by dockerd as set at build time.
**Deprecated**: This field is deprecated and will be omitted in a API v1.49.
type: "string"
example: "2d41c047c83e09a6d61d464906feb2a2f3c52aa4"
SwarmInfo:
description: |
@@ -10491,13 +10491,9 @@ paths:
### Image tarball format
An image tarball contains one directory per image layer (named using its long ID), each containing these files:
An image tarball contains [Content as defined in the OCI Image Layout Specification](https://github.com/opencontainers/image-spec/blob/v1.1.1/image-layout.md#content).
- `VERSION`: currently `1.0` - the file format version
- `json`: detailed layer information, similar to `docker inspect layer_id`
- `layer.tar`: A tarfile containing the filesystem changes in this layer
The `layer.tar` file contains `aufs` style `.wh..wh.aufs` files and directories for storing attribute changes and deletions.
Additionally, includes the manifest.json file associated with a backwards compatible docker save format.
If the tarball defines a repository, the tarball should also include a `repositories` file at the root that contains a list of repository and tag names mapped to layer IDs.
@@ -10537,6 +10533,7 @@ paths:
If not provided, the full multi-platform image will be saved.
Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}`
tags: ["Image"]
/images/get:
get:
summary: "Export several images"
@@ -10571,6 +10568,16 @@ paths:
type: "array"
items:
type: "string"
- name: "platform"
type: "string"
in: "query"
description: |
JSON encoded OCI platform describing a platform which will be used
to select a platform-specific image to be saved if the image is
multi-platform.
If not provided, the full multi-platform image will be saved.
Example: `{"os": "linux", "architecture": "arm", "variant": "v5"}`
tags: ["Image"]
/images/load:
post:

View File

@@ -153,6 +153,7 @@ type GetImageOpts struct {
// ImageInspectOpts holds parameters to inspect an image.
type ImageInspectOpts struct {
Manifests bool
Platform *ocispec.Platform
}
// CommitConfig is the configuration for creating an image as part of a build.

View File

@@ -128,11 +128,12 @@ type InspectResponse struct {
// compatibility.
Descriptor *ocispec.Descriptor `json:"Descriptor,omitempty"`
// Manifests is a list of image manifests available in this image. It
// Manifests is a list of image manifests available in this image. It
// provides a more detailed view of the platform-specific image manifests or
// other image-attached data like build attestations.
//
// Only available if the daemon provides a multi-platform image store.
// Only available if the daemon provides a multi-platform image store, the client
// requests manifests AND does not request a specific platform.
//
// WARNING: This is experimental and may change at any time without any backward
// compatibility.

View File

@@ -106,6 +106,11 @@ type LoadOptions struct {
type InspectOptions struct {
// Manifests returns the image manifests.
Manifests bool
// Platform selects the specific platform of a multi-platform image to inspect.
//
// This option is only available for API version 1.49 and up.
Platform *ocispec.Platform
}
// SaveOptions holds parameters to save images.

View File

@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.22
package registry // import "github.com/docker/docker/api/types/registry"
import (
@@ -15,23 +18,26 @@ type ServiceConfig struct {
InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"`
IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"`
Mirrors []string
// ExtraFields is for internal use to include deprecated fields on older API versions.
ExtraFields map[string]any `json:"-"`
}
// MarshalJSON implements a custom marshaler to include legacy fields
// in API responses.
func (sc ServiceConfig) MarshalJSON() ([]byte, error) {
tmp := map[string]interface{}{
"InsecureRegistryCIDRs": sc.InsecureRegistryCIDRs,
"IndexConfigs": sc.IndexConfigs,
"Mirrors": sc.Mirrors,
func (sc *ServiceConfig) MarshalJSON() ([]byte, error) {
type tmp ServiceConfig
base, err := json.Marshal((*tmp)(sc))
if err != nil {
return nil, err
}
if sc.AllowNondistributableArtifactsCIDRs != nil {
tmp["AllowNondistributableArtifactsCIDRs"] = nil
var merged map[string]any
_ = json.Unmarshal(base, &merged)
for k, v := range sc.ExtraFields {
merged[k] = v
}
if sc.AllowNondistributableArtifactsHostnames != nil {
tmp["AllowNondistributableArtifactsHostnames"] = nil
}
return json.Marshal(tmp)
return json.Marshal(merged)
}
// NetIPNet is the net.IPNet type, which can be marshalled and

View File

@@ -1,3 +1,6 @@
// FIXME(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.22
package registry
import (
@@ -20,8 +23,10 @@ func TestServiceConfigMarshalLegacyFields(t *testing.T) {
// used for API versions < 1.49.
t.Run("with legacy fields", func(t *testing.T) {
b, err := json.Marshal(&ServiceConfig{
AllowNondistributableArtifactsCIDRs: []*NetIPNet{},
AllowNondistributableArtifactsHostnames: []string{},
ExtraFields: map[string]any{
"AllowNondistributableArtifactsCIDRs": json.RawMessage(nil),
"AllowNondistributableArtifactsHostnames": json.RawMessage(nil),
},
})
assert.NilError(t, err)
const expected = `{"AllowNondistributableArtifactsCIDRs":null,"AllowNondistributableArtifactsHostnames":null,"IndexConfigs":null,"InsecureRegistryCIDRs":null,"Mirrors":null}`

View File

@@ -73,6 +73,7 @@ type Info struct {
SecurityOptions []string
ProductLicense string `json:",omitempty"`
DefaultAddressPools []NetworkAddressPool `json:",omitempty"`
FirewallBackend *FirewallInfo `json:"FirewallBackend,omitempty"`
CDISpecDirs []string
Containerd *ContainerdInfo `json:",omitempty"`
@@ -143,7 +144,7 @@ type Commit struct {
// Expected is the commit ID of external tool expected by dockerd as set at build time.
//
// Deprecated: this field is no longer used in API v1.49, but kept for backward-compatibility with older API versions.
Expected string
Expected string `json:",omitempty"`
}
// NetworkAddressPool is a temp struct used by [Info] struct.
@@ -151,3 +152,11 @@ type NetworkAddressPool struct {
Base string
Size int
}
// FirewallInfo describes the firewall backend.
type FirewallInfo struct {
// Driver is the name of the firewall backend driver.
Driver string `json:"Driver"`
// Info is a list of label/value pairs, containing information related to the firewall.
Info [][2]string `json:"Info,omitempty"`
}

View File

@@ -13,11 +13,11 @@ import (
cerrdefs "github.com/containerd/errdefs"
"github.com/docker/docker/daemon/graphdriver"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/identity"
"github.com/moby/buildkit/snapshot"
"github.com/moby/buildkit/util/leaseutil"
"github.com/moby/locker"
"github.com/moby/sys/user"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
bolt "go.etcd.io/bbolt"
@@ -36,7 +36,7 @@ type Opt struct {
GraphDriver graphdriver.Driver
LayerStore layer.Store
Root string
IdentityMapping idtools.IdentityMapping
IdentityMapping user.IdentityMapping
}
type graphIDRegistrar interface {
@@ -106,7 +106,7 @@ func (s *snapshotter) Name() string {
return "default"
}
func (s *snapshotter) IdentityMapping() *idtools.IdentityMapping {
func (s *snapshotter) IdentityMapping() *user.IdentityMapping {
// Returning a non-nil but empty *IdentityMapping breaks BuildKit:
// https://github.com/moby/moby/pull/39444
if s.opt.IdentityMapping.Empty() {
@@ -494,7 +494,7 @@ type mountable struct {
acquire func() ([]mount.Mount, func() error, error)
release func() error
refCount int
idmap idtools.IdentityMapping
idmap user.IdentityMapping
}
func (m *mountable) Mount() ([]mount.Mount, func() error, error) {
@@ -538,7 +538,7 @@ func (m *mountable) releaseMount() error {
return m.release()
}
func (m *mountable) IdentityMapping() *idtools.IdentityMapping {
func (m *mountable) IdentityMapping() *user.IdentityMapping {
// Returning a non-nil but empty *IdentityMapping breaks BuildKit:
// https://github.com/moby/moby/pull/39444
if m.idmap.Empty() {

View File

@@ -26,7 +26,6 @@ import (
"github.com/docker/docker/errdefs"
"github.com/docker/docker/libnetwork"
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/streamformatter"
controlapi "github.com/moby/buildkit/api/services/control"
"github.com/moby/buildkit/client"
@@ -35,6 +34,7 @@ import (
"github.com/moby/buildkit/session"
"github.com/moby/buildkit/util/entitlements"
"github.com/moby/buildkit/util/tracing"
"github.com/moby/sys/user"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
"google.golang.org/grpc"
@@ -89,7 +89,7 @@ type Opt struct {
RegistryHosts docker.RegistryHosts
BuilderConfig config.BuilderConfig
Rootless bool
IdentityMapping idtools.IdentityMapping
IdentityMapping user.IdentityMapping
DNSConfig config.DNSConfig
ApparmorProfile string
UseSnapshotter bool

View File

@@ -11,7 +11,6 @@ import (
"github.com/containerd/log"
"github.com/docker/docker/daemon/config"
"github.com/docker/docker/libnetwork"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/stringid"
"github.com/moby/buildkit/executor"
"github.com/moby/buildkit/executor/oci"
@@ -22,12 +21,13 @@ import (
"github.com/moby/buildkit/solver/llbsolver/cdidevices"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/network"
"github.com/moby/sys/user"
"github.com/opencontainers/runtime-spec/specs-go"
)
const networkName = "bridge"
func newExecutor(root, cgroupParent string, net *libnetwork.Controller, dnsConfig *oci.DNSConfig, rootless bool, idmap idtools.IdentityMapping, apparmorProfile string, cdiManager *cdidevices.Manager) (executor.Executor, error) {
func newExecutor(root, cgroupParent string, net *libnetwork.Controller, dnsConfig *oci.DNSConfig, rootless bool, idmap user.IdentityMapping, apparmorProfile string, cdiManager *cdidevices.Manager) (executor.Executor, error) {
netRoot := filepath.Join(root, "net")
networkProviders := map[pb.NetMode]network.Provider{
pb.NetMode_UNSET: &bridgeProvider{Controller: net, Root: netRoot},

View File

@@ -9,14 +9,14 @@ import (
"github.com/docker/docker/daemon/config"
"github.com/docker/docker/libnetwork"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/buildkit/executor"
"github.com/moby/buildkit/executor/oci"
resourcetypes "github.com/moby/buildkit/executor/resources/types"
"github.com/moby/buildkit/solver/llbsolver/cdidevices"
"github.com/moby/sys/user"
)
func newExecutor(_, _ string, _ *libnetwork.Controller, _ *oci.DNSConfig, _ bool, _ idtools.IdentityMapping, _ string, _ *cdidevices.Manager) (executor.Executor, error) {
func newExecutor(_, _ string, _ *libnetwork.Controller, _ *oci.DNSConfig, _ bool, _ user.IdentityMapping, _ string, _ *cdidevices.Manager) (executor.Executor, error) {
return &stubExecutor{}, nil
}

View File

@@ -52,6 +52,7 @@ func (e *imageExporterMobyWrapper) Resolve(ctx context.Context, id int, exporter
if _, has := exporterAttrs[string(exptypes.OptKeyDanglingPrefix)]; !has {
exporterAttrs[string(exptypes.OptKeyDanglingPrefix)] = "moby-dangling"
}
exporterAttrs[string(exptypes.OptKeyDanglingEmptyOnly)] = "true"
inst, err := e.exp.Resolve(ctx, id, exporterAttrs)
if err != nil {
@@ -82,21 +83,33 @@ func (i *imageExporterInstanceWrapper) Export(ctx context.Context, src *exporter
}
if i.callbacks.Named != nil {
for _, name := range strings.Split(out[string(exptypes.OptKeyName)], ",") {
ref, err := reference.ParseNormalizedNamed(name)
if err != nil {
// Shouldn't happen, but log if it does and continue.
log.G(ctx).WithFields(log.Fields{
"name": name,
"error": err,
}).Warn("image named with invalid reference produced by buildkit")
continue
}
namedTagged := reference.TagNameOnly(ref).(reference.NamedTagged)
i.callbacks.Named(ctx, namedTagged, desc)
}
i.processNamedCallback(ctx, out, desc)
}
return out, ref, nil
}
func (i *imageExporterInstanceWrapper) processNamedCallback(ctx context.Context, out map[string]string, desc ocispec.Descriptor) {
// TODO(vvoland): Change to exptypes.ExporterImageNameKey when BuildKit v0.21 is vendored.
imageName := out["image.name"]
if imageName == "" {
log.G(ctx).Warn("image named with empty image.name produced by buildkit")
return
}
for _, name := range strings.Split(imageName, ",") {
ref, err := reference.ParseNormalizedNamed(name)
if err != nil {
// Shouldn't happen, but log if it does and continue.
log.G(ctx).WithFields(log.Fields{
"name": name,
"error": err,
}).Warn("image named with invalid reference produced by buildkit")
continue
}
if namedTagged, ok := reference.TagNameOnly(ref).(reference.NamedTagged); ok {
i.callbacks.Named(ctx, namedTagged, desc)
}
}
}

View File

@@ -16,12 +16,12 @@ import (
"github.com/docker/docker/builder"
"github.com/docker/docker/builder/remotecontext"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/streamformatter"
"github.com/docker/docker/pkg/stringid"
"github.com/moby/buildkit/frontend/dockerfile/instructions"
"github.com/moby/buildkit/frontend/dockerfile/parser"
"github.com/moby/buildkit/frontend/dockerfile/shell"
"github.com/moby/sys/user"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"golang.org/x/sync/syncmap"
@@ -47,13 +47,13 @@ const (
// BuildManager is shared across all Builder objects
type BuildManager struct {
idMapping idtools.IdentityMapping
idMapping user.IdentityMapping
backend builder.Backend
pathCache pathCache // TODO: make this persistent
}
// NewBuildManager creates a BuildManager
func NewBuildManager(b builder.Backend, identityMapping idtools.IdentityMapping) (*BuildManager, error) {
func NewBuildManager(b builder.Backend, identityMapping user.IdentityMapping) (*BuildManager, error) {
bm := &BuildManager{
backend: b,
pathCache: &syncmap.Map{},
@@ -103,7 +103,7 @@ type builderOptions struct {
Backend builder.Backend
ProgressWriter backend.ProgressWriter
PathCache pathCache
IDMapping idtools.IdentityMapping
IDMapping user.IdentityMapping
}
// Builder is a Dockerfile builder
@@ -118,7 +118,7 @@ type Builder struct {
docker builder.Backend
idMapping idtools.IdentityMapping
idMapping user.IdentityMapping
disableCommit bool
imageSources *imageSources
pathCache pathCache

View File

@@ -17,14 +17,14 @@ import (
"github.com/docker/docker/builder"
"github.com/docker/docker/builder/remotecontext"
"github.com/docker/docker/builder/remotecontext/urlutil"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/longpath"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/streamformatter"
"github.com/docker/docker/pkg/system"
"github.com/moby/buildkit/frontend/dockerfile/instructions"
"github.com/moby/go-archive"
"github.com/moby/sys/symlink"
"github.com/moby/sys/user"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
@@ -446,9 +446,15 @@ func downloadSource(output io.Writer, stdout io.Writer, srcURL string) (remote b
return lc, filename, err
}
type identity struct {
UID int
GID int
SID string
}
type copyFileOptions struct {
decompress bool
identity *idtools.Identity
identity *identity
archiver *archive.Archiver
}
@@ -498,7 +504,7 @@ func performCopyForInfo(dest copyInfo, source copyInfo, options copyFileOptions)
return copyFile(archiver, srcPath, destPath, options.identity)
}
func copyDirectory(archiver *archive.Archiver, source, dest string, identity *idtools.Identity) error {
func copyDirectory(archiver *archive.Archiver, source, dest string, identity *identity) error {
destExists, err := isExistingDirectory(dest)
if err != nil {
return errors.Wrapf(err, "failed to query destination path")
@@ -513,13 +519,13 @@ func copyDirectory(archiver *archive.Archiver, source, dest string, identity *id
return nil
}
func copyFile(archiver *archive.Archiver, source, dest string, identity *idtools.Identity) error {
func copyFile(archiver *archive.Archiver, source, dest string, identity *identity) error {
if identity == nil {
if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil {
return err
}
} else {
if err := idtools.MkdirAllAndChownNew(filepath.Dir(dest), 0o755, *identity); err != nil {
if err := user.MkdirAllAndChown(filepath.Dir(dest), 0o755, identity.UID, identity.GID, user.WithOnlyNew); err != nil {
return errors.Wrapf(err, "failed to create new directory")
}
}

View File

@@ -7,11 +7,9 @@ import (
"path"
"path/filepath"
"strings"
"github.com/docker/docker/pkg/idtools"
)
func fixPermissions(source, destination string, identity idtools.Identity, overrideSkip bool) error {
func fixPermissions(source, destination string, id identity, overrideSkip bool) error {
var (
skipChownRoot bool
err error
@@ -39,7 +37,7 @@ func fixPermissions(source, destination string, identity idtools.Identity, overr
}
fullpath = filepath.Join(destination, cleaned)
return os.Lchown(fullpath, identity.UID, identity.GID)
return os.Lchown(fullpath, id.UID, id.GID)
})
}

View File

@@ -8,7 +8,6 @@ import (
winio "github.com/Microsoft/go-winio"
"github.com/docker/docker/internal/usergroup"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/system"
"github.com/moby/sys/reexec"
"github.com/pkg/errors"
@@ -24,12 +23,12 @@ func init() {
reexec.Register("windows-fix-permissions", fixPermissionsReexec)
}
func fixPermissions(source, destination string, identity idtools.Identity, _ bool) error {
if identity.SID == "" {
func fixPermissions(source, destination string, id identity, _ bool) error {
if id.SID == "" {
return nil
}
cmd := reexec.Command("windows-fix-permissions", source, destination, identity.SID)
cmd := reexec.Command("windows-fix-permissions", source, destination, id.SID)
output, err := cmd.CombinedOutput()
return errors.Wrapf(err, "failed to exec windows-fix-permissions: %s", output)

View File

@@ -7,8 +7,8 @@ import (
"testing"
"github.com/docker/docker/builder/remotecontext"
"github.com/docker/docker/pkg/archive"
"github.com/moby/buildkit/frontend/dockerfile/instructions"
"github.com/moby/go-archive"
"github.com/moby/sys/reexec"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"

View File

@@ -19,10 +19,10 @@ import (
"github.com/docker/docker/builder"
networkSettings "github.com/docker/docker/daemon/network"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/stringid"
"github.com/docker/go-connections/nat"
"github.com/moby/go-archive"
"github.com/moby/go-archive/chrootarchive"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
@@ -152,12 +152,13 @@ func (b *Builder) performCopy(ctx context.Context, req dispatchRequest, inst cop
return err
}
identity := b.idMapping.RootPair()
uid, gid := b.idMapping.RootPair()
id := identity{UID: uid, GID: gid}
// if a chown was requested, perform the steps to get the uid, gid
// translated (if necessary because of user namespaces), and replace
// the root pair with the chown pair for copy operations
if inst.chownStr != "" {
identity, err = parseChownFlag(ctx, b, state, inst.chownStr, destInfo.root, b.idMapping)
id, err = parseChownFlag(ctx, b, state, inst.chownStr, destInfo.root, b.idMapping)
if err != nil {
if b.options.Platform != "windows" {
return errors.Wrapf(err, "unable to convert uid/gid chown string to host mapping")
@@ -173,7 +174,7 @@ func (b *Builder) performCopy(ctx context.Context, req dispatchRequest, inst cop
archiver: b.getArchiver(),
}
if !inst.preserveOwnership {
opts.identity = &identity
opts.identity = &id
}
if err := performCopyForInfo(destInfo, info, opts); err != nil {
return errors.Wrapf(err, "failed to copy files")

View File

@@ -6,17 +6,16 @@ import (
"strconv"
"strings"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/sys/symlink"
"github.com/moby/sys/user"
"github.com/pkg/errors"
)
func parseChownFlag(ctx context.Context, builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
func parseChownFlag(ctx context.Context, builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping user.IdentityMapping) (identity, error) {
var userStr, grpStr string
parts := strings.Split(chown, ":")
if len(parts) > 2 {
return idtools.Identity{}, errors.New("invalid chown string format: " + chown)
return identity{}, errors.New("invalid chown string format: " + chown)
}
if len(parts) == 1 {
// if no group specified, use the user spec as group as well
@@ -27,27 +26,27 @@ func parseChownFlag(ctx context.Context, builder *Builder, state *dispatchState,
passwdPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "passwd"), ctrRootPath)
if err != nil {
return idtools.Identity{}, errors.Wrap(err, "can't resolve /etc/passwd path in container rootfs")
return identity{}, errors.Wrap(err, "can't resolve /etc/passwd path in container rootfs")
}
groupPath, err := symlink.FollowSymlinkInScope(filepath.Join(ctrRootPath, "etc", "group"), ctrRootPath)
if err != nil {
return idtools.Identity{}, errors.Wrap(err, "can't resolve /etc/group path in container rootfs")
return identity{}, errors.Wrap(err, "can't resolve /etc/group path in container rootfs")
}
uid, err := lookupUser(userStr, passwdPath)
if err != nil {
return idtools.Identity{}, errors.Wrap(err, "can't find uid for user "+userStr)
return identity{}, errors.Wrap(err, "can't find uid for user "+userStr)
}
gid, err := lookupGroup(grpStr, groupPath)
if err != nil {
return idtools.Identity{}, errors.Wrap(err, "can't find gid for group "+grpStr)
return identity{}, errors.Wrap(err, "can't find gid for group "+grpStr)
}
// convert as necessary because of user namespaces
chownPair, err := identityMapping.ToHost(idtools.Identity{UID: uid, GID: gid})
uid, gid, err = identityMapping.ToHost(uid, gid)
if err != nil {
return idtools.Identity{}, errors.Wrap(err, "unable to convert uid/gid to host mapping")
return identity{}, errors.Wrap(err, "unable to convert uid/gid to host mapping")
}
return chownPair, nil
return identity{UID: uid, GID: gid}, nil
}
func lookupUser(userStr, filepath string) (int, error) {

View File

@@ -7,7 +7,7 @@ import (
"testing"
"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/sys/user"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
@@ -28,15 +28,15 @@ othergrp:x:6666:
`,
}
// test mappings for validating use of maps
idMaps := []idtools.IDMap{
idMaps := []user.IDMap{
{
ContainerID: 0,
HostID: 100000,
Size: 65536,
ID: 0,
ParentID: 100000,
Count: 65536,
},
}
remapped := idtools.IdentityMapping{UIDMaps: idMaps, GIDMaps: idMaps}
unmapped := idtools.IdentityMapping{}
remapped := user.IdentityMapping{UIDMaps: idMaps, GIDMaps: idMaps}
unmapped := user.IdentityMapping{}
contextDir, cleanup := createTestTempDir(t, "", "builder-chown-parse-test")
defer cleanup()
@@ -54,9 +54,9 @@ othergrp:x:6666:
builder *Builder
name string
chownStr string
idMapping idtools.IdentityMapping
idMapping user.IdentityMapping
state *dispatchState
expected idtools.Identity
expected identity
}{
{
builder: &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
@@ -64,7 +64,7 @@ othergrp:x:6666:
chownStr: "1",
idMapping: unmapped,
state: &dispatchState{},
expected: idtools.Identity{UID: 1, GID: 1},
expected: identity{UID: 1, GID: 1},
},
{
builder: &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
@@ -72,7 +72,7 @@ othergrp:x:6666:
chownStr: "0:1",
idMapping: unmapped,
state: &dispatchState{},
expected: idtools.Identity{UID: 0, GID: 1},
expected: identity{UID: 0, GID: 1},
},
{
builder: &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
@@ -80,7 +80,7 @@ othergrp:x:6666:
chownStr: "0",
idMapping: remapped,
state: &dispatchState{},
expected: idtools.Identity{UID: 100000, GID: 100000},
expected: identity{UID: 100000, GID: 100000},
},
{
builder: &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
@@ -88,7 +88,7 @@ othergrp:x:6666:
chownStr: "1:33",
idMapping: remapped,
state: &dispatchState{},
expected: idtools.Identity{UID: 100001, GID: 100033},
expected: identity{UID: 100001, GID: 100033},
},
{
builder: &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
@@ -96,7 +96,7 @@ othergrp:x:6666:
chownStr: "bin:5555",
idMapping: unmapped,
state: &dispatchState{},
expected: idtools.Identity{UID: 1, GID: 5555},
expected: identity{UID: 1, GID: 5555},
},
{
builder: &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
@@ -104,7 +104,7 @@ othergrp:x:6666:
chownStr: "0:unicorn",
idMapping: remapped,
state: &dispatchState{},
expected: idtools.Identity{UID: 100000, GID: 101002},
expected: identity{UID: 100000, GID: 101002},
},
{
builder: &Builder{options: &types.ImageBuildOptions{Platform: "linux"}},
@@ -112,7 +112,7 @@ othergrp:x:6666:
chownStr: "unicorn",
idMapping: remapped,
state: &dispatchState{},
expected: idtools.Identity{UID: 101001, GID: 101002},
expected: identity{UID: 101001, GID: 101002},
},
} {
t.Run(testcase.name, func(t *testing.T) {
@@ -127,7 +127,7 @@ othergrp:x:6666:
builder *Builder
name string
chownStr string
idMapping idtools.IdentityMapping
idMapping user.IdentityMapping
state *dispatchState
descr string
}{

View File

@@ -14,8 +14,8 @@ import (
"github.com/docker/docker/builder/remotecontext"
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/archive"
"github.com/docker/go-connections/nat"
"github.com/moby/go-archive"
"github.com/opencontainers/go-digest"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"

View File

@@ -12,27 +12,28 @@ import (
"github.com/docker/docker/api/types/mount"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/internal/usergroup"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/jsonmessage"
"github.com/moby/sys/user"
"golang.org/x/sys/windows"
)
func parseChownFlag(ctx context.Context, builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
func parseChownFlag(ctx context.Context, builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping user.IdentityMapping) (identity, error) {
if builder.options.Platform == "windows" {
return getAccountIdentity(ctx, builder, chown, ctrRootPath, state)
}
return identityMapping.RootPair(), nil
uid, gid := identityMapping.RootPair()
return identity{UID: uid, GID: gid}, nil
}
func getAccountIdentity(ctx context.Context, builder *Builder, accountName string, ctrRootPath string, state *dispatchState) (idtools.Identity, error) {
func getAccountIdentity(ctx context.Context, builder *Builder, accountName string, ctrRootPath string, state *dispatchState) (identity, error) {
// If this is potentially a string SID then attempt to convert it to verify
// this, otherwise continue looking for the account.
if strings.HasPrefix(accountName, "S-") || strings.HasPrefix(accountName, "s-") {
sid, err := windows.StringToSid(accountName)
if err == nil {
return idtools.Identity{SID: sid.String()}, nil
return identity{SID: sid.String()}, nil
}
}
@@ -41,14 +42,14 @@ func getAccountIdentity(ctx context.Context, builder *Builder, accountName strin
// If this is a SID that is built-in and hence the same across all systems then use that.
if err == nil && (accType == windows.SidTypeAlias || accType == windows.SidTypeWellKnownGroup) {
return idtools.Identity{SID: sid.String()}, nil
return identity{SID: sid.String()}, nil
}
// Check if the account name is one unique to containers.
if strings.EqualFold(accountName, "ContainerAdministrator") {
return idtools.Identity{SID: usergroup.ContainerAdministratorSidString}, nil
return identity{SID: usergroup.ContainerAdministratorSidString}, nil
} else if strings.EqualFold(accountName, "ContainerUser") {
return idtools.Identity{SID: usergroup.ContainerUserSidString}, nil
return identity{SID: usergroup.ContainerUserSidString}, nil
}
// All other lookups failed, so therefore determine if the account in
@@ -56,7 +57,7 @@ func getAccountIdentity(ctx context.Context, builder *Builder, accountName strin
return lookupNTAccount(ctx, builder, accountName, state)
}
func lookupNTAccount(ctx context.Context, builder *Builder, accountName string, state *dispatchState) (idtools.Identity, error) {
func lookupNTAccount(ctx context.Context, builder *Builder, accountName string, state *dispatchState) (identity, error) {
source, _ := filepath.Split(os.Args[0])
target := "C:\\Docker"
@@ -64,7 +65,7 @@ func lookupNTAccount(ctx context.Context, builder *Builder, accountName string,
optionsPlatform, err := platforms.Parse(builder.options.Platform)
if err != nil {
return idtools.Identity{}, errdefs.InvalidParameter(err)
return identity{}, errdefs.InvalidParameter(err)
}
runConfig := copyRunConfig(state.runConfig,
@@ -85,7 +86,7 @@ func lookupNTAccount(ctx context.Context, builder *Builder, accountName string,
container, err := builder.containerManager.Create(ctx, runConfig, hostConfig)
if err != nil {
return idtools.Identity{}, err
return identity{}, err
}
stdout := new(bytes.Buffer)
@@ -93,15 +94,15 @@ func lookupNTAccount(ctx context.Context, builder *Builder, accountName string,
if err := builder.containerManager.Run(ctx, container.ID, stdout, stderr); err != nil {
if err, ok := err.(*statusCodeError); ok {
return idtools.Identity{}, &jsonmessage.JSONError{
return identity{}, &jsonmessage.JSONError{
Message: stderr.String(),
Code: err.StatusCode(),
}
}
return idtools.Identity{}, err
return identity{}, err
}
accountSid := stdout.String()
return idtools.Identity{SID: accountSid}, nil
return identity{SID: accountSid}, nil
}

View File

@@ -6,11 +6,11 @@ import (
"path/filepath"
"github.com/docker/docker/builder"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/longpath"
"github.com/docker/docker/pkg/system"
"github.com/docker/docker/pkg/tarsum"
"github.com/moby/go-archive/chrootarchive"
"github.com/moby/go-archive/compression"
"github.com/moby/sys/symlink"
"github.com/pkg/errors"
)
@@ -66,7 +66,7 @@ func FromArchive(tarStream io.Reader) (builder.Source, error) {
}
}()
decompressedStream, err := archive.DecompressStream(tarStream)
decompressedStream, err := compression.DecompressStream(tarStream)
if err != nil {
return nil, err
}

View File

@@ -6,8 +6,8 @@ import (
"hash"
"os"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/tarsum"
"github.com/moby/go-archive"
)
// NewFileHash returns new hash that is used for the builder cache keys

View File

@@ -7,7 +7,7 @@ import (
"github.com/containerd/log"
"github.com/docker/docker/builder"
"github.com/docker/docker/builder/remotecontext/git"
"github.com/docker/docker/pkg/archive"
"github.com/moby/go-archive"
)
// MakeGitContext returns a Context from gitURL that is cloned in a temporary directory.

View File

@@ -6,7 +6,7 @@ import (
"testing"
"github.com/docker/docker/builder"
"github.com/docker/docker/pkg/archive"
"github.com/moby/go-archive"
"github.com/moby/sys/reexec"
"github.com/pkg/errors"
"gotest.tools/v3/skip"

View File

@@ -32,7 +32,7 @@ func (cli *Client) ContainerCommit(ctx context.Context, containerID string, opti
if tagged, ok := ref.(reference.Tagged); ok {
tag = tagged.Tag()
}
repository = reference.FamiliarName(ref)
repository = ref.Name()
}
query := url.Values{}

View File

@@ -33,13 +33,15 @@ func TestContainerCommitError(t *testing.T) {
}
func TestContainerCommit(t *testing.T) {
expectedURL := "/commit"
expectedContainerID := "container_id"
specifiedReference := "repository_name:tag"
expectedRepositoryName := "repository_name"
expectedTag := "tag"
expectedComment := "comment"
expectedAuthor := "author"
const (
expectedURL = "/commit"
expectedContainerID = "container_id"
specifiedReference = "repository_name:tag"
expectedRepositoryName = "docker.io/library/repository_name"
expectedTag = "tag"
expectedComment = "comment"
expectedAuthor = "author"
)
expectedChanges := []string{"change1", "change2"}
client := &Client{

View File

@@ -21,7 +21,7 @@ func (cli *Client) ImageCreate(ctx context.Context, parentReference string, opti
}
query := url.Values{}
query.Set("fromImage", reference.FamiliarName(ref))
query.Set("fromImage", ref.Name())
query.Set("tag", getAPITagFromNamedRef(ref))
if options.Platform != "" {
query.Set("platform", strings.ToLower(options.Platform))

View File

@@ -25,11 +25,14 @@ func TestImageCreateError(t *testing.T) {
}
func TestImageCreate(t *testing.T) {
expectedURL := "/images/create"
expectedImage := "test:5000/my_image"
expectedTag := "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
expectedReference := fmt.Sprintf("%s@%s", expectedImage, expectedTag)
expectedRegistryAuth := "eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsiYXV0aCI6ImRHOTBid289IiwiZW1haWwiOiJqb2huQGRvZS5jb20ifX0="
const (
expectedURL = "/images/create"
expectedImage = "docker.io/test/my_image"
expectedTag = "sha256:ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
specifiedReference = "test/my_image:latest@" + expectedTag
expectedRegistryAuth = "eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsiYXV0aCI6ImRHOTBid289IiwiZW1haWwiOiJqb2huQGRvZS5jb20ifX0="
)
client := &Client{
client: newMockClient(func(r *http.Request) (*http.Response, error) {
if !strings.HasPrefix(r.URL.Path, expectedURL) {
@@ -58,7 +61,7 @@ func TestImageCreate(t *testing.T) {
}),
}
createResponse, err := client.ImageCreate(context.Background(), expectedReference, image.CreateOptions{
createResponse, err := client.ImageCreate(context.Background(), specifiedReference, image.CreateOptions{
RegistryAuth: expectedRegistryAuth,
})
if err != nil {

View File

@@ -32,6 +32,17 @@ func (cli *Client) ImageInspect(ctx context.Context, imageID string, inspectOpts
query.Set("manifests", "1")
}
if opts.apiOptions.Platform != nil {
if err := cli.NewVersionError(ctx, "1.49", "platform"); err != nil {
return image.InspectResponse{}, err
}
platform, err := encodePlatform(opts.apiOptions.Platform)
if err != nil {
return image.InspectResponse{}, err
}
query.Set("platform", platform)
}
resp, err := cli.get(ctx, "/images/"+imageID+"/json", query, nil)
defer ensureReaderClosed(resp)
if err != nil {

View File

@@ -4,6 +4,7 @@ import (
"bytes"
"github.com/docker/docker/api/types/image"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
// ImageInspectOption is a type representing functional options for the image inspect operation.
@@ -36,6 +37,17 @@ func ImageInspectWithManifests(manifests bool) ImageInspectOption {
})
}
// ImageInspectWithPlatform sets platform API option for the image inspect operation.
// This option is only available for API version 1.49 and up.
// With this option set, the image inspect operation will return information for the
// specified platform variant of the multi-platform image.
func ImageInspectWithPlatform(platform *ocispec.Platform) ImageInspectOption {
return imageInspectOptionFunc(func(clientOpts *imageInspectOpts) error {
clientOpts.apiOptions.Platform = platform
return nil
})
}
// ImageInspectWithAPIOpts sets the API options for the image inspect operation.
func ImageInspectWithAPIOpts(opts image.InspectOptions) ImageInspectOption {
return imageInspectOptionFunc(func(clientOpts *imageInspectOpts) error {

View File

@@ -14,6 +14,7 @@ import (
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/errdefs"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
@@ -79,3 +80,47 @@ func TestImageInspect(t *testing.T) {
t.Fatalf("expected `%v`, got %v", expectedTags, imageInspect.RepoTags)
}
}
func TestImageInspectWithPlatform(t *testing.T) {
expectedURL := "/images/image_id/json"
requestedPlatform := &ocispec.Platform{
OS: "linux",
Architecture: "arm64",
}
expectedPlatform, err := encodePlatform(requestedPlatform)
assert.NilError(t, err)
client := &Client{
client: newMockClient(func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
// Check if platform parameter is passed correctly
platform := req.URL.Query().Get("platform")
if platform != expectedPlatform {
return nil, fmt.Errorf("Expected platform '%s', got '%s'", expectedPlatform, platform)
}
content, err := json.Marshal(image.InspectResponse{
ID: "image_id",
Architecture: "arm64",
Os: "linux",
})
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: io.NopCloser(bytes.NewReader(content)),
}, nil
}),
}
imageInspect, err := client.ImageInspect(context.Background(), "image_id", ImageInspectWithPlatform(requestedPlatform))
assert.NilError(t, err)
assert.Equal(t, imageInspect.ID, "image_id")
assert.Equal(t, imageInspect.Architecture, "arm64")
assert.Equal(t, imageInspect.Os, "linux")
}

View File

@@ -26,7 +26,7 @@ func (cli *Client) ImagePull(ctx context.Context, refStr string, options image.P
}
query := url.Values{}
query.Set("fromImage", reference.FamiliarName(ref))
query.Set("fromImage", ref.Name())
if !options.All {
query.Set("tag", getAPITagFromNamedRef(ref))
}

View File

@@ -74,7 +74,7 @@ func TestImagePullWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T)
}
func TestImagePullWithPrivilegedFuncNoError(t *testing.T) {
expectedURL := "/images/create"
const expectedURL = "/images/create"
client := &Client{
client: newMockClient(func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
@@ -92,8 +92,8 @@ func TestImagePullWithPrivilegedFuncNoError(t *testing.T) {
}
query := req.URL.Query()
fromImage := query.Get("fromImage")
if fromImage != "myimage" {
return nil, fmt.Errorf("fromimage not set in URL query properly. Expected '%s', got %s", "myimage", fromImage)
if fromImage != "docker.io/library/myimage" {
return nil, fmt.Errorf("fromimage not set in URL query properly. Expected '%s', got %s", "docker.io/library/myimage", fromImage)
}
tag := query.Get("tag")
if tag != "latest" {
@@ -125,8 +125,10 @@ func TestImagePullWithPrivilegedFuncNoError(t *testing.T) {
}
func TestImagePullWithoutErrors(t *testing.T) {
expectedURL := "/images/create"
expectedOutput := "hello world"
const (
expectedURL = "/images/create"
expectedOutput = "hello world"
)
pullCases := []struct {
all bool
reference string
@@ -136,61 +138,88 @@ func TestImagePullWithoutErrors(t *testing.T) {
{
all: false,
reference: "myimage",
expectedImage: "myimage",
expectedImage: "docker.io/library/myimage",
expectedTag: "latest",
},
{
all: false,
reference: "myimage:tag",
expectedImage: "myimage",
expectedImage: "docker.io/library/myimage",
expectedTag: "tag",
},
{
all: true,
reference: "myimage",
expectedImage: "myimage",
expectedImage: "docker.io/library/myimage",
expectedTag: "",
},
{
all: true,
reference: "myimage:anything",
expectedImage: "myimage",
expectedImage: "docker.io/library/myimage",
expectedTag: "",
},
{
reference: "myname/myimage",
expectedImage: "docker.io/myname/myimage",
expectedTag: "latest",
},
{
reference: "docker.io/myname/myimage",
expectedImage: "docker.io/myname/myimage",
expectedTag: "latest",
},
{
reference: "index.docker.io/myname/myimage:tag",
expectedImage: "docker.io/myname/myimage",
expectedTag: "tag",
},
{
reference: "localhost/myname/myimage",
expectedImage: "localhost/myname/myimage",
expectedTag: "latest",
},
{
reference: "registry.example.com:5000/myimage:tag",
expectedImage: "registry.example.com:5000/myimage",
expectedTag: "tag",
},
}
for _, pullCase := range pullCases {
client := &Client{
client: newMockClient(func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
fromImage := query.Get("fromImage")
if fromImage != pullCase.expectedImage {
return nil, fmt.Errorf("fromimage not set in URL query properly. Expected '%s', got %s", pullCase.expectedImage, fromImage)
}
tag := query.Get("tag")
if tag != pullCase.expectedTag {
return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", pullCase.expectedTag, tag)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: io.NopCloser(bytes.NewReader([]byte(expectedOutput))),
}, nil
}),
}
resp, err := client.ImagePull(context.Background(), pullCase.reference, image.PullOptions{
All: pullCase.all,
t.Run(pullCase.reference, func(t *testing.T) {
client := &Client{
client: newMockClient(func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
fromImage := query.Get("fromImage")
if fromImage != pullCase.expectedImage {
return nil, fmt.Errorf("fromimage not set in URL query properly. Expected '%s', got %s", pullCase.expectedImage, fromImage)
}
tag := query.Get("tag")
if tag != pullCase.expectedTag {
return nil, fmt.Errorf("tag not set in URL query properly. Expected '%s', got %s", pullCase.expectedTag, tag)
}
return &http.Response{
StatusCode: http.StatusOK,
Body: io.NopCloser(bytes.NewReader([]byte(expectedOutput))),
}, nil
}),
}
resp, err := client.ImagePull(context.Background(), pullCase.reference, image.PullOptions{
All: pullCase.all,
})
if err != nil {
t.Fatal(err)
}
body, err := io.ReadAll(resp)
if err != nil {
t.Fatal(err)
}
if string(body) != expectedOutput {
t.Fatalf("expected '%s', got %s", expectedOutput, string(body))
}
})
if err != nil {
t.Fatal(err)
}
body, err := io.ReadAll(resp)
if err != nil {
t.Fatal(err)
}
if string(body) != expectedOutput {
t.Fatalf("expected '%s', got %s", expectedOutput, string(body))
}
}
}

View File

@@ -29,7 +29,6 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options image.Pu
return nil, errors.New("cannot push a digest reference")
}
name := reference.FamiliarName(ref)
query := url.Values{}
if !options.All {
ref = reference.TagNameOnly(ref)
@@ -52,13 +51,13 @@ func (cli *Client) ImagePush(ctx context.Context, image string, options image.Pu
query.Set("platform", string(pJson))
}
resp, err := cli.tryImagePush(ctx, name, query, options.RegistryAuth)
resp, err := cli.tryImagePush(ctx, ref.Name(), query, options.RegistryAuth)
if errdefs.IsUnauthorized(err) && options.PrivilegeFunc != nil {
newAuthHeader, privilegeErr := options.PrivilegeFunc(ctx)
if privilegeErr != nil {
return nil, privilegeErr
}
resp, err = cli.tryImagePush(ctx, name, query, newAuthHeader)
resp, err = cli.tryImagePush(ctx, ref.Name(), query, newAuthHeader)
}
if err != nil {
return nil, err

View File

@@ -79,7 +79,7 @@ func TestImagePushWithUnauthorizedErrorAndAnotherUnauthorizedError(t *testing.T)
}
func TestImagePushWithPrivilegedFuncNoError(t *testing.T) {
expectedURL := "/images/myimage/push"
const expectedURL = "/images/docker.io/myname/myimage/push"
client := &Client{
client: newMockClient(func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
@@ -109,7 +109,7 @@ func TestImagePushWithPrivilegedFuncNoError(t *testing.T) {
privilegeFunc := func(_ context.Context) (string, error) {
return "IAmValid", nil
}
resp, err := client.ImagePush(context.Background(), "myimage:tag", image.PushOptions{
resp, err := client.ImagePush(context.Background(), "myname/myimage:tag", image.PushOptions{
RegistryAuth: "NotValid",
PrivilegeFunc: privilegeFunc,
})
@@ -126,8 +126,10 @@ func TestImagePushWithPrivilegedFuncNoError(t *testing.T) {
}
func TestImagePushWithoutErrors(t *testing.T) {
expectedOutput := "hello world"
expectedURLFormat := "/images/%s/push"
const (
expectedURLFormat = "/images/%s/push"
expectedOutput = "hello world"
)
testCases := []struct {
all bool
reference string
@@ -137,27 +139,52 @@ func TestImagePushWithoutErrors(t *testing.T) {
{
all: false,
reference: "myimage",
expectedImage: "myimage",
expectedImage: "docker.io/library/myimage",
expectedTag: "latest",
},
{
all: false,
reference: "myimage:tag",
expectedImage: "myimage",
expectedImage: "docker.io/library/myimage",
expectedTag: "tag",
},
{
all: true,
reference: "myimage",
expectedImage: "myimage",
expectedImage: "docker.io/library/myimage",
expectedTag: "",
},
{
all: true,
reference: "myimage:anything",
expectedImage: "myimage",
expectedImage: "docker.io/library/myimage",
expectedTag: "",
},
{
reference: "myname/myimage",
expectedImage: "docker.io/myname/myimage",
expectedTag: "latest",
},
{
reference: "docker.io/myname/myimage",
expectedImage: "docker.io/myname/myimage",
expectedTag: "latest",
},
{
reference: "index.docker.io/myname/myimage:tag",
expectedImage: "docker.io/myname/myimage",
expectedTag: "tag",
},
{
reference: "localhost/myname/myimage",
expectedImage: "localhost/myname/myimage",
expectedTag: "latest",
},
{
reference: "registry.example.com:5000/myimage:tag",
expectedImage: "registry.example.com:5000/myimage",
expectedTag: "tag",
},
}
for _, tc := range testCases {
t.Run(fmt.Sprintf("%s,all-tags=%t", tc.reference, tc.all), func(t *testing.T) {

View File

@@ -26,7 +26,7 @@ func (cli *Client) ImageTag(ctx context.Context, source, target string) error {
ref = reference.TagNameOnly(ref)
query := url.Values{}
query.Set("repo", reference.FamiliarName(ref))
query.Set("repo", ref.Name())
if tagged, ok := ref.(reference.Tagged); ok {
query.Set("tag", tagged.Tag())
}

View File

@@ -95,7 +95,7 @@ func TestImageTagHexSource(t *testing.T) {
}
func TestImageTag(t *testing.T) {
expectedURL := "/images/image_id/tag"
const expectedURL = "/images/image_id/tag"
tagCases := []struct {
reference string
expectedQueryParams map[string]string
@@ -103,37 +103,37 @@ func TestImageTag(t *testing.T) {
{
reference: "repository:tag1",
expectedQueryParams: map[string]string{
"repo": "repository",
"repo": "docker.io/library/repository",
"tag": "tag1",
},
}, {
reference: "another_repository:latest",
expectedQueryParams: map[string]string{
"repo": "another_repository",
"repo": "docker.io/library/another_repository",
"tag": "latest",
},
}, {
reference: "another_repository",
expectedQueryParams: map[string]string{
"repo": "another_repository",
"repo": "docker.io/library/another_repository",
"tag": "latest",
},
}, {
reference: "test/another_repository",
expectedQueryParams: map[string]string{
"repo": "test/another_repository",
"repo": "docker.io/test/another_repository",
"tag": "latest",
},
}, {
reference: "test/another_repository:tag1",
expectedQueryParams: map[string]string{
"repo": "test/another_repository",
"repo": "docker.io/test/another_repository",
"tag": "tag1",
},
}, {
reference: "test/test/another_repository:tag1",
expectedQueryParams: map[string]string{
"repo": "test/test/another_repository",
"repo": "docker.io/test/test/another_repository",
"tag": "tag1",
},
}, {

View File

@@ -237,7 +237,7 @@ func (cli *Client) checkResponseErr(serverResp *http.Response) (retErr error) {
}
var daemonErr error
if serverResp.Header.Get("Content-Type") == "application/json" && (cli.version == "" || versions.GreaterThan(cli.version, "1.23")) {
if serverResp.Header.Get("Content-Type") == "application/json" {
var errorResponse types.ErrorResponse
if err := json.Unmarshal(body, &errorResponse); err != nil {
return errors.Wrap(err, "Error reading JSON")

View File

@@ -132,12 +132,15 @@ func TestResponseErrors(t *testing.T) {
expected: `Error response from daemon: Some error occurred`,
},
{
// API versions before 1.24 did not support JSON errors, and return response as-is.
// API versions before 1.24 did not support JSON errors. Technically,
// we no longer downgrade to older API versions, but we make an
// exception for errors so that older clients would print a more
// readable error.
doc: "JSON error on old API",
apiVersion: "1.23",
contentType: "application/json",
response: `{"message":"Some error occurred"}`,
expected: `Error response from daemon: {"message":"Some error occurred"}`,
contentType: "text/plain; charset=utf-8",
response: `client version 1.10 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version`,
expected: `Error response from daemon: client version 1.10 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version`,
},
{
doc: "plain-text error",

View File

@@ -13,12 +13,9 @@ import (
// installCommonConfigFlags adds flags to the pflag.FlagSet to configure the daemon
func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
var (
allowNonDistributable = opts.NewNamedListOptsRef("allow-nondistributable-artifacts", &conf.AllowNondistributableArtifacts, registry.ValidateIndexName)
registryMirrors = opts.NewNamedListOptsRef("registry-mirrors", &conf.Mirrors, registry.ValidateMirror)
insecureRegistries = opts.NewNamedListOptsRef("insecure-registries", &conf.InsecureRegistries, registry.ValidateIndexName)
registryMirrors = opts.NewNamedListOptsRef("registry-mirrors", &conf.Mirrors, registry.ValidateMirror)
insecureRegistries = opts.NewNamedListOptsRef("insecure-registries", &conf.InsecureRegistries, registry.ValidateIndexName)
)
flags.Var(allowNonDistributable, "allow-nondistributable-artifacts", "Allow push of nondistributable artifacts to registry")
_ = flags.MarkDeprecated("allow-nondistributable-artifacts", "Pushing nondistributable artifacts is now enabled by default. ")
flags.Var(registryMirrors, "registry-mirror", "Preferred Docker registry mirror")
flags.Var(insecureRegistries, "insecure-registry", "Enable insecure registry communication")
@@ -77,6 +74,9 @@ func installCommonConfigFlags(conf *config.Config, flags *pflag.FlagSet) {
flags.Var(opts.NewNamedListOptsRef("cdi-spec-dirs", &conf.CDISpecDirs, nil), "cdi-spec-dir", "CDI specification directories to use")
// Deprecated flags / options
allowNonDistributable := opts.NewNamedListOptsRef("allow-nondistributable-artifacts", &([]string{}), registry.ValidateIndexName)
flags.Var(allowNonDistributable, "allow-nondistributable-artifacts", "Allow push of nondistributable artifacts to registry")
_ = flags.MarkDeprecated("allow-nondistributable-artifacts", "Pushing nondistributable artifacts is now enabled by default. ")
// TODO(thaJeztah): option is used to produce error when used; remove in next release
flags.StringVar(&conf.CorsHeaders, "api-cors-header", "", "Set CORS headers in the Engine API; deprecated: this feature was deprecated in 27.0, and now removed")

View File

@@ -661,11 +661,6 @@ func loadDaemonCliConfig(opts *daemonOptions) (*config.Config, error) {
return nil, err
}
if len(conf.AllowNondistributableArtifacts) > 0 {
// TODO(thaJeztah): move to config.Validate and change into an error for v29.0 and remove in v30.0.
log.G(context.TODO()).Warn(`DEPRECATED: The "allow-nondistributable-artifacts" config parameter is deprecated and always enabled; this option will be removed in the next release`)
}
return conf, nil
}

View File

@@ -5,7 +5,7 @@ import (
"path/filepath"
containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/pkg/archive"
"github.com/moby/go-archive"
"github.com/pkg/errors"
)

View File

@@ -30,15 +30,15 @@ import (
"github.com/docker/docker/image"
libcontainerdtypes "github.com/docker/docker/libcontainerd/types"
"github.com/docker/docker/oci"
"github.com/docker/docker/pkg/atomicwriter"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/restartmanager"
"github.com/docker/docker/volume"
volumemounts "github.com/docker/docker/volume/mounts"
"github.com/docker/go-units"
agentexec "github.com/moby/swarmkit/v2/agent/exec"
"github.com/moby/sys/atomicwriter"
"github.com/moby/sys/signal"
"github.com/moby/sys/symlink"
"github.com/moby/sys/user"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"go.opentelemetry.io/otel"
@@ -320,7 +320,7 @@ func (container *Container) CommitInMemory(store *ViewDB) error {
}
// SetupWorkingDirectory sets up the container's working directory as set in container.Config.WorkingDir
func (container *Container) SetupWorkingDirectory(rootIdentity idtools.Identity) error {
func (container *Container) SetupWorkingDirectory(uid int, gid int) error {
if container.Config.WorkingDir == "" {
return nil
}
@@ -331,7 +331,7 @@ func (container *Container) SetupWorkingDirectory(rootIdentity idtools.Identity)
return err
}
if err := idtools.MkdirAllAndChownNew(pth, 0o755, rootIdentity); err != nil {
if err := user.MkdirAllAndChown(pth, 0o755, uid, gid, user.WithOnlyNew); err != nil {
pthInfo, err2 := os.Stat(pth)
if err2 == nil && pthInfo != nil && !pthInfo.IsDir() {
return errors.Errorf("Cannot mkdir: %s is not a directory", container.Config.WorkingDir)

View File

@@ -435,7 +435,7 @@ type containerByIDIndexer struct{}
const terminator = "\x00"
// FromObject implements the memdb.SingleIndexer interface for Container objects
func (e *containerByIDIndexer) FromObject(obj interface{}) (bool, []byte, error) {
func (e *containerByIDIndexer) FromObject(obj any) (bool, []byte, error) {
c, ok := obj.(*Container)
if !ok {
return false, nil, fmt.Errorf("%T is not a Container", obj)
@@ -445,7 +445,7 @@ func (e *containerByIDIndexer) FromObject(obj interface{}) (bool, []byte, error)
}
// FromArgs implements the memdb.Indexer interface
func (e *containerByIDIndexer) FromArgs(args ...interface{}) ([]byte, error) {
func (e *containerByIDIndexer) FromArgs(args ...any) ([]byte, error) {
if len(args) != 1 {
return nil, fmt.Errorf("must provide only a single argument")
}
@@ -457,7 +457,7 @@ func (e *containerByIDIndexer) FromArgs(args ...interface{}) ([]byte, error) {
return []byte(arg + terminator), nil
}
func (e *containerByIDIndexer) PrefixFromArgs(args ...interface{}) ([]byte, error) {
func (e *containerByIDIndexer) PrefixFromArgs(args ...any) ([]byte, error) {
val, err := e.FromArgs(args...)
if err != nil {
return nil, err
@@ -470,7 +470,7 @@ func (e *containerByIDIndexer) PrefixFromArgs(args ...interface{}) ([]byte, erro
// namesByNameIndexer is used to index container name associations by name.
type namesByNameIndexer struct{}
func (e *namesByNameIndexer) FromObject(obj interface{}) (bool, []byte, error) {
func (e *namesByNameIndexer) FromObject(obj any) (bool, []byte, error) {
n, ok := obj.(nameAssociation)
if !ok {
return false, nil, fmt.Errorf(`%T does not have type "nameAssociation"`, obj)
@@ -480,7 +480,7 @@ func (e *namesByNameIndexer) FromObject(obj interface{}) (bool, []byte, error) {
return true, []byte(n.name + terminator), nil
}
func (e *namesByNameIndexer) FromArgs(args ...interface{}) ([]byte, error) {
func (e *namesByNameIndexer) FromArgs(args ...any) ([]byte, error) {
if len(args) != 1 {
return nil, fmt.Errorf("must provide only a single argument")
}
@@ -495,7 +495,7 @@ func (e *namesByNameIndexer) FromArgs(args ...interface{}) ([]byte, error) {
// namesByContainerIDIndexer is used to index container names by container ID.
type namesByContainerIDIndexer struct{}
func (e *namesByContainerIDIndexer) FromObject(obj interface{}) (bool, []byte, error) {
func (e *namesByContainerIDIndexer) FromObject(obj any) (bool, []byte, error) {
n, ok := obj.(nameAssociation)
if !ok {
return false, nil, fmt.Errorf(`%T does not have type "nameAssociation"`, obj)
@@ -505,7 +505,7 @@ func (e *namesByContainerIDIndexer) FromObject(obj interface{}) (bool, []byte, e
return true, []byte(n.containerID + terminator), nil
}
func (e *namesByContainerIDIndexer) FromArgs(args ...interface{}) ([]byte, error) {
func (e *namesByContainerIDIndexer) FromArgs(args ...any) ([]byte, error) {
if len(args) != 1 {
return nil, fmt.Errorf("must provide only a single argument")
}

View File

@@ -143,7 +143,15 @@ init() {
# instruction: iptables dependency check
faced_iptables_error=""
if ! command -v iptables > /dev/null 2>&1 && [ ! -f /sbin/iptables ] && [ ! -f /usr/sbin/iptables ]; then
# Many OSs now use iptables-nft by default so, check for module nf_tables by default. But,
# if "iptables --version" worked and reported "legacy", check for module ip_tables instead.
iptables_module="nf_tables"
iptables_command=$(PATH=$PATH:/sbin:/usr/sbin command -v iptables 2> /dev/null) || :
if [ -n "$iptables_command" ]; then
iptables_version=$($iptables_command --version 2> /dev/null) || :
case $iptables_version in
*legacy*) iptables_module="ip_tables" ;;
esac
faced_iptables_error=1
if [ -z "$OPT_SKIP_IPTABLES" ]; then
if command -v apt-get > /dev/null 2>&1; then
@@ -178,14 +186,14 @@ init() {
fi
# instruction: ip_tables module dependency check
if ! grep -q ip_tables /proc/modules 2> /dev/null && ! grep -q ip_tables /lib/modules/$(uname -r)/modules.builtin 2> /dev/null; then
if ! grep -q $iptables_module /proc/modules 2> /dev/null && ! grep -q $iptables_module /lib/modules/$(uname -r)/modules.builtin 2> /dev/null; then
faced_iptables_error=1
if [ -z "$OPT_SKIP_IPTABLES" ]; then
instructions=$(
cat <<- EOI
${instructions}
# Load ip_tables module
modprobe ip_tables
# Load $iptables_module module
modprobe $iptables_module
EOI
)
fi

28
contrib/otel/README.md Normal file
View File

@@ -0,0 +1,28 @@
# Sample stack for testing OTEL functionality with moby
To easily test the OTEL functionality present in moby, you can spin up a small demo compose stack that includes:
- an OTEL collector container;
- a Jaeger container to visualize traces;
- an alternative Aspire Dashboard container to visualize traces;
The OTEL collector is configured to export Traces to both the Jaeger and Aspire containers.
The `contrib/otel` directory contains the compose file with the services configured, along with a basic configuration file for the OTEL collector.
## How can I use it?
1. Export the env var used to override the OTLP endpoint:
`export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318` (if running in a devcontainer or in other ways, you might have to change how you pass this env var to the daemon);
2. Start the moby engine you want to get traces from (make sure it gets the env var declared above);
3. Start the otel compose stack by running `docker compose up -d` in the `contrib/otel/` directory;
4. Make some calls to the engine using the Docker CLI to send some traces to the endpoint;
5. Browse Jaeger at `http://localhost:16686` or the Aspire Dashboard at `http://localhost:18888/traces`;
6. To see some traces from the engine, select `dockerd` in the top left dropdown
> **Note**: The precise steps may vary based on how you're working on the codebase (buiding a binary and executing natively, running/debugging in a devcontainer, etc... )
## Cleanup?
Simply run `docker compose down` in the `contrib/otel/` directory.
You can also run `unset OTEL_EXPORTER_OTLP_ENDPOINT` to get rid of the OTLP env var from your environment

31
contrib/otel/compose.yaml Normal file
View File

@@ -0,0 +1,31 @@
name: moby-otel
services:
jaeger:
image: jaegertracing/all-in-one:latest
restart: always
ports:
- 16686:16686
aspire-dashboard:
image: mcr.microsoft.com/dotnet/nightly/aspire-dashboard
restart: always
ports:
- 0.0.0.0:18888:18888
environment:
DOTNET_DASHBOARD_UNSECURED_ALLOW_ANONYMOUS: 'true'
otelcol:
image: otel/opentelemetry-collector-contrib:latest
restart: always
depends_on:
- jaeger
- aspire-dashboard
ports:
- 4318:4318 # default otlp http port
develop:
watch:
- action: sync+restart
path: ./otelcol.yaml
target: /etc/otelcol-contrib/config.yaml

23
contrib/otel/otelcol.yaml Normal file
View File

@@ -0,0 +1,23 @@
# Receive signals over gRPC and HTTP
# moby currently uses http
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
exporters:
otlp/jaeger:
endpoint: jaeger:4317
tls::insecure: true
otlp/aspire:
endpoint: aspire-dashboard:18889
tls::insecure: true
service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlp/jaeger, otlp/aspire]

View File

@@ -1,7 +1,7 @@
package daemon // import "github.com/docker/docker/daemon"
import (
"github.com/docker/docker/pkg/archive"
"github.com/moby/go-archive"
)
// defaultTarCopyOptions is the setting that is used when unpacking an archive

View File

@@ -10,8 +10,7 @@ import (
"github.com/docker/docker/container"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
"github.com/moby/go-archive"
"github.com/moby/sys/user"
)
@@ -27,7 +26,7 @@ func (daemon *Daemon) tarCopyOptions(ctr *container.Container, noOverwriteDirNon
return &archive.TarOptions{
NoOverwriteDirNonDir: noOverwriteDirNonDir,
ChownOpts: &idtools.Identity{UID: uid, GID: gid},
ChownOpts: &archive.ChownOpts{UID: uid, GID: gid},
}, nil
}

View File

@@ -12,9 +12,9 @@ import (
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/container"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/ioutils"
volumemounts "github.com/docker/docker/volume/mounts"
"github.com/moby/go-archive"
"github.com/pkg/errors"
)

View File

@@ -10,9 +10,9 @@ import (
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/container"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/chrootarchive"
"github.com/docker/docker/pkg/ioutils"
"github.com/moby/go-archive"
"github.com/moby/go-archive/chrootarchive"
)
// containerStatPath stats the filesystem resource at the specified path in this

View File

@@ -33,12 +33,10 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, req *backend.Containe
return err
}
if ctr.IsPaused() {
err := fmt.Errorf("container %s is paused, unpause the container before attach", prefixOrName)
return errdefs.Conflict(err)
return errdefs.Conflict(fmt.Errorf("container %s is paused, unpause the container before attach", prefixOrName))
}
if ctr.IsRestarting() {
err := fmt.Errorf("container %s is restarting, wait until the container is running", prefixOrName)
return errdefs.Conflict(err)
return errdefs.Conflict(fmt.Errorf("container %s is restarting, wait until the container is running", prefixOrName))
}
cfg := stream.AttachConfig{
@@ -51,8 +49,6 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, req *backend.Containe
}
ctr.StreamConfig.AttachStreams(&cfg)
multiplexed := !ctr.Config.Tty && req.MuxStreams
clientCtx, closeNotify := context.WithCancel(context.Background())
defer closeNotify()
go func() {
@@ -68,6 +64,7 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, req *backend.Containe
}
}()
multiplexed := !ctr.Config.Tty && req.MuxStreams
inStream, outStream, errStream, err := req.GetStreams(multiplexed, closeNotify)
if err != nil {
return err
@@ -91,7 +88,7 @@ func (daemon *Daemon) ContainerAttach(prefixOrName string, req *backend.Containe
}
if err := daemon.containerAttach(ctr, &cfg, req.Logs, req.Stream); err != nil {
fmt.Fprintf(outStream, "Error attaching: %s\n", err)
_, _ = fmt.Fprintln(outStream, "Error attaching:", err)
}
return nil
}
@@ -124,16 +121,19 @@ func (daemon *Daemon) ContainerAttachRaw(prefixOrName string, stdin io.ReadClose
return daemon.containerAttach(ctr, &cfg, false, doStream)
}
func (daemon *Daemon) containerAttach(c *container.Container, cfg *stream.AttachConfig, logs, doStream bool) error {
if logs {
logDriver, logCreated, err := daemon.getLogger(c)
func (daemon *Daemon) containerAttach(ctr *container.Container, cfg *stream.AttachConfig, enableLogs, doStream bool) error {
if enableLogs {
logDriver, logCreated, err := daemon.getLogger(ctr)
if err != nil {
return err
}
if logCreated {
defer func() {
if err = logDriver.Close(); err != nil {
log.G(context.TODO()).Errorf("Error closing logger: %v", err)
log.G(context.TODO()).WithFields(log.Fields{
"error": err,
"container": ctr.ID,
}).Error("Error closing logger")
}
}()
}
@@ -141,13 +141,13 @@ func (daemon *Daemon) containerAttach(c *container.Container, cfg *stream.Attach
if !ok {
return logger.ErrReadLogsNotSupported{}
}
logs := cLog.ReadLogs(context.TODO(), logger.ReadConfig{Tail: -1})
defer logs.ConsumerGone()
logWatcher := cLog.ReadLogs(context.TODO(), logger.ReadConfig{Tail: -1})
defer logWatcher.ConsumerGone()
LogLoop:
for {
select {
case msg, ok := <-logs.Msg:
case msg, ok := <-logWatcher.Msg:
if !ok {
break LogLoop
}
@@ -157,14 +157,17 @@ func (daemon *Daemon) containerAttach(c *container.Container, cfg *stream.Attach
if msg.Source == "stderr" && cfg.Stderr != nil {
cfg.Stderr.Write(msg.Line)
}
case err := <-logs.Err:
log.G(context.TODO()).Errorf("Error streaming logs: %v", err)
case err := <-logWatcher.Err:
log.G(context.TODO()).WithFields(log.Fields{
"error": err,
"container": ctr.ID,
}).Error("Error streaming logs")
break LogLoop
}
}
}
daemon.LogContainerEvent(c, events.ActionAttach)
daemon.LogContainerEvent(ctr, events.ActionAttach)
if !doStream {
return nil
@@ -173,33 +176,38 @@ func (daemon *Daemon) containerAttach(c *container.Container, cfg *stream.Attach
if cfg.Stdin != nil {
r, w := io.Pipe()
go func(stdin io.ReadCloser) {
defer w.Close()
defer log.G(context.TODO()).Debug("Closing buffered stdin pipe")
io.Copy(w, stdin)
log.G(context.TODO()).WithFields(log.Fields{
"container": ctr.ID,
}).Debug("Closing buffered stdin pipe")
w.Close()
}(cfg.Stdin)
cfg.Stdin = r
}
if !c.Config.OpenStdin {
if !ctr.Config.OpenStdin {
cfg.Stdin = nil
}
if c.Config.StdinOnce && !c.Config.Tty {
if ctr.Config.StdinOnce && !ctr.Config.Tty {
// Wait for the container to stop before returning.
waitChan := c.Wait(context.Background(), container.WaitConditionNotRunning)
waitChan := ctr.Wait(context.Background(), container.WaitConditionNotRunning)
defer func() {
<-waitChan // Ignore returned exit code.
}()
}
ctx := c.AttachContext()
err := <-c.StreamConfig.CopyStreams(ctx, cfg)
ctx := ctr.AttachContext()
err := <-ctr.StreamConfig.CopyStreams(ctx, cfg)
if err != nil {
var ierr term.EscapeError
if errors.Is(err, context.Canceled) || errors.As(err, &ierr) {
daemon.LogContainerEvent(c, events.ActionDetach)
daemon.LogContainerEvent(ctr, events.ActionDetach)
} else {
log.G(ctx).Errorf("attach failed with error: %v", err)
log.G(ctx).WithFields(log.Fields{
"error": err,
"container": ctr.ID,
}).Error("attach failed with error")
}
}

View File

@@ -6,7 +6,7 @@ import (
"time"
"github.com/docker/docker/internal/metrics"
"github.com/docker/docker/pkg/archive"
"github.com/moby/go-archive"
)
// ContainerChanges returns a list of container fs changes

View File

@@ -6,7 +6,7 @@ import (
"path/filepath"
"strings"
"github.com/docker/docker/pkg/atomicwriter"
"github.com/moby/sys/atomicwriter"
)
// convertKVStringsToMap converts ["key=value"] to {"key":"value"}

View File

@@ -91,8 +91,10 @@ var flatOptions = map[string]bool{
var skipValidateOptions = map[string]bool{
"features": true,
"builder": true,
// Corresponding flag has been removed because it was already unusable
"deprecated-key-path": true,
// Deprecated options that are safe to ignore if present.
"deprecated-key-path": true,
"allow-nondistributable-artifacts": true,
}
// skipDuplicates contains configuration keys that

View File

@@ -365,3 +365,34 @@ func TestDaemonConfigurationHostGatewayIP(t *testing.T) {
})
}
}
// TestDaemonLegacyOptions verifies that loading config files containing
// deprecated / legacy options does not prevent the daemon from loading
// the config (some options may have an explicit error, and can be tested
// separately).
func TestDaemonLegacyOptions(t *testing.T) {
tests := []struct {
name string
configJSON string
}{
{
name: "deprecated-key-path",
configJSON: `{"deprecated-key-path": "/etc/docker/key.json"}`,
},
{
name: "allow-nondistributable-artifacts",
configJSON: `{"allow-nondistributable-artifacts": ["127.0.0.0/8", "10.10.1.11:5000", "10.10.1.22:5000", "registry.example.com", "registry.example.com"]}`,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
configFile := makeConfigFile(t, tc.configJSON)
flags := pflag.NewFlagSet("test", pflag.ContinueOnError)
c, err := New()
assert.NilError(t, err)
_, err = MergeDaemonConfigurations(c, flags, configFile)
assert.NilError(t, err)
})
}
}

View File

@@ -19,10 +19,10 @@ import (
"github.com/docker/docker/errdefs"
"github.com/docker/docker/libnetwork"
"github.com/docker/docker/libnetwork/drivers/bridge"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/process"
"github.com/docker/docker/pkg/stringid"
"github.com/moby/sys/mount"
"github.com/moby/sys/user"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"go.opentelemetry.io/otel"
@@ -251,14 +251,14 @@ func (daemon *Daemon) setupIPCDirs(ctr *container.Container) error {
fallthrough
case ipcMode.IsShareable():
rootIDs := daemon.idMapping.RootPair()
uid, gid := daemon.idMapping.RootPair()
if !ctr.HasMountFor("/dev/shm") {
shmPath, err := ctr.ShmResourcePath()
if err != nil {
return err
}
if err := idtools.MkdirAllAndChown(shmPath, 0o700, rootIDs); err != nil {
if err := user.MkdirAllAndChown(shmPath, 0o700, uid, gid); err != nil {
return err
}
@@ -266,7 +266,7 @@ func (daemon *Daemon) setupIPCDirs(ctr *container.Container) error {
if err := unix.Mount("shm", shmPath, "tmpfs", uintptr(unix.MS_NOEXEC|unix.MS_NOSUID|unix.MS_NODEV), label.FormatMountLabel(shmproperty, ctr.GetMountLabel())); err != nil {
return fmt.Errorf("mounting shm tmpfs: %s", err)
}
if err := os.Chown(shmPath, rootIDs.UID, rootIDs.GID); err != nil {
if err := os.Chown(shmPath, uid, gid); err != nil {
return err
}
ctr.ShmPath = shmPath
@@ -298,7 +298,7 @@ func (daemon *Daemon) setupSecretDir(ctr *container.Container) (setupErr error)
}
// retrieve possible remapped range start for root UID, GID
rootIDs := daemon.idMapping.RootPair()
ruid, rgid := daemon.idMapping.RootPair()
for _, s := range ctr.SecretReferences {
// TODO (ehazlett): use type switch when more are supported
@@ -313,7 +313,7 @@ func (daemon *Daemon) setupSecretDir(ctr *container.Container) (setupErr error)
if err != nil {
return errors.Wrap(err, "error getting secret file path")
}
if err := idtools.MkdirAllAndChown(filepath.Dir(fPath), 0o700, rootIDs); err != nil {
if err := user.MkdirAllAndChown(filepath.Dir(fPath), 0o700, ruid, rgid); err != nil {
return errors.Wrap(err, "error creating secret mount path")
}
@@ -338,7 +338,7 @@ func (daemon *Daemon) setupSecretDir(ctr *container.Container) (setupErr error)
return err
}
if err := os.Chown(fPath, rootIDs.UID+uid, rootIDs.GID+gid); err != nil {
if err := os.Chown(fPath, ruid+uid, rgid+gid); err != nil {
return errors.Wrap(err, "error setting ownership for secret")
}
if err := os.Chmod(fPath, s.File.Mode); err != nil {
@@ -364,7 +364,7 @@ func (daemon *Daemon) setupSecretDir(ctr *container.Container) (setupErr error)
if err != nil {
return errors.Wrap(err, "error getting config file path for container")
}
if err := idtools.MkdirAllAndChown(filepath.Dir(fPath), 0o700, rootIDs); err != nil {
if err := user.MkdirAllAndChown(filepath.Dir(fPath), 0o700, ruid, rgid); err != nil {
return errors.Wrap(err, "error creating config mount path")
}
@@ -389,7 +389,7 @@ func (daemon *Daemon) setupSecretDir(ctr *container.Container) (setupErr error)
return err
}
if err := os.Chown(fPath, rootIDs.UID+uid, rootIDs.GID+gid); err != nil {
if err := os.Chown(fPath, ruid+uid, rgid+gid); err != nil {
return errors.Wrap(err, "error setting ownership for config")
}
if err := os.Chmod(fPath, configRef.File.Mode); err != nil {
@@ -404,18 +404,18 @@ func (daemon *Daemon) setupSecretDir(ctr *container.Container) (setupErr error)
// In practice this is using a tmpfs mount and is used for both "configs" and "secrets"
func (daemon *Daemon) createSecretsDir(ctr *container.Container) error {
// retrieve possible remapped range start for root UID, GID
rootIDs := daemon.idMapping.RootPair()
uid, gid := daemon.idMapping.RootPair()
dir, err := ctr.SecretMountPath()
if err != nil {
return errors.Wrap(err, "error getting container secrets dir")
}
// create tmpfs
if err := idtools.MkdirAllAndChown(dir, 0o700, rootIDs); err != nil {
if err := user.MkdirAllAndChown(dir, 0o700, uid, gid); err != nil {
return errors.Wrap(err, "error creating secret local mount path")
}
tmpfsOwnership := fmt.Sprintf("uid=%d,gid=%d", rootIDs.UID, rootIDs.GID)
tmpfsOwnership := fmt.Sprintf("uid=%d,gid=%d", uid, gid)
if err := mount.Mount("tmpfs", dir, "tmpfs", "nodev,nosuid,noexec,"+tmpfsOwnership); err != nil {
return errors.Wrap(err, "unable to setup secret mount")
}
@@ -430,8 +430,8 @@ func (daemon *Daemon) remountSecretDir(ctr *container.Container) error {
if err := label.Relabel(dir, ctr.MountLabel, false); err != nil {
log.G(context.TODO()).WithError(err).WithField("dir", dir).Warn("Error while attempting to set selinux label")
}
rootIDs := daemon.idMapping.RootPair()
tmpfsOwnership := fmt.Sprintf("uid=%d,gid=%d", rootIDs.UID, rootIDs.GID)
uid, gid := daemon.idMapping.RootPair()
tmpfsOwnership := fmt.Sprintf("uid=%d,gid=%d", uid, gid)
// remount secrets ro
if err := mount.Mount("tmpfs", dir, "tmpfs", "remount,ro,"+tmpfsOwnership); err != nil {
@@ -577,5 +577,6 @@ func (daemon *Daemon) setupContainerMountsRoot(ctr *container.Container) error {
if err != nil {
return err
}
return idtools.MkdirAllAndChown(p, 0o710, idtools.Identity{UID: idtools.CurrentIdentity().UID, GID: daemon.IdentityMapping().RootPair().GID})
_, gid := daemon.IdentityMapping().RootPair()
return user.MkdirAllAndChown(p, 0o710, os.Getuid(), gid)
}

View File

@@ -30,12 +30,11 @@ import (
"github.com/docker/docker/image"
dimage "github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/progress"
"github.com/docker/docker/pkg/streamformatter"
"github.com/docker/docker/pkg/stringid"
registrypkg "github.com/docker/docker/registry"
imagespec "github.com/moby/docker-image-spec/specs-go/v1"
"github.com/moby/go-archive"
"github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/identity"
"github.com/opencontainers/image-spec/specs-go"
@@ -144,12 +143,7 @@ func (i *ImageService) pullForBuilder(ctx context.Context, name string, authConf
pullRegistryAuth := &registry.AuthConfig{}
if len(authConfigs) > 0 {
// The request came with a full auth config, use it
repoInfo, err := i.registryService.ResolveRepository(ref)
if err != nil {
return nil, err
}
resolvedConfig := registrypkg.ResolveAuthConfig(authConfigs, repoInfo.Index)
resolvedConfig := i.registryService.ResolveAuthConfig(authConfigs, ref)
pullRegistryAuth = &resolvedConfig
}

View File

@@ -7,8 +7,8 @@ import (
"github.com/containerd/containerd/v2/core/mount"
"github.com/containerd/log"
"github.com/docker/docker/container"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/stringid"
"github.com/moby/go-archive"
)
func (i *ImageService) Changes(ctx context.Context, ctr *container.Container) ([]archive.Change, error) {

View File

@@ -18,8 +18,8 @@ import (
"github.com/containerd/log"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/archive"
imagespec "github.com/moby/docker-image-spec/specs-go/v1"
"github.com/moby/go-archive"
"github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/identity"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -152,8 +152,8 @@ func (i *ImageService) createDiff(ctx context.Context, name string, sn snapshots
if !i.idMapping.Empty() {
// The rootfs of the container is remapped if an id mapping exists, we
// need to "unremap" it before committing the snapshot
rootPair := i.idMapping.RootPair()
usernsID := fmt.Sprintf("%s-%d-%d-%s", name, rootPair.UID, rootPair.GID, uniquePart())
uid, gid := i.idMapping.RootPair()
usernsID := fmt.Sprintf("%s-%d-%d-%s", name, uid, gid, uniquePart())
remappedID := usernsID + remapSuffix
baseName := name

View File

@@ -18,8 +18,8 @@ import (
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/daemon/images"
"github.com/docker/docker/errdefs"
dockerarchive "github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/streamformatter"
"github.com/moby/go-archive/compression"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
@@ -230,7 +230,7 @@ func (i *ImageService) leaseContent(ctx context.Context, store content.Store, de
// complement of ExportImage. The input stream is an uncompressed tar
// ball containing images and metadata.
func (i *ImageService) LoadImage(ctx context.Context, inTar io.ReadCloser, platform *ocispec.Platform, outStream io.Writer, quiet bool) error {
decompressed, err := dockerarchive.DecompressStream(inTar)
decompressed, err := compression.DecompressStream(inTar)
if err != nil {
return errors.Wrap(err, "failed to decompress input tar archive")
}
@@ -248,8 +248,21 @@ func (i *ImageService) LoadImage(ctx context.Context, inTar io.ReadCloser, platf
if nameFromArchive == "" {
return false
}
_, err := reference.ParseNormalizedNamed(nameFromArchive)
return err == nil
ref, err := reference.ParseNormalizedNamed(nameFromArchive)
if err != nil {
return false
}
// Look up if there is an existing image with this name and ensure a dangling image exists.
if img, err := i.images.Get(ctx, ref.String()); err == nil {
if err := i.ensureDanglingImage(ctx, img); err != nil {
log.G(ctx).WithError(err).Warnf("failed to keep the previous image for %s as dangling", img.Name)
}
} else if !errdefs.IsNotFound(err) {
log.G(ctx).WithError(err).Warn("failed to retrieve image: %w", err)
}
return true
}),
}

View File

@@ -20,10 +20,10 @@ import (
"github.com/docker/docker/builder/dockerfile"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/image"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/pools"
"github.com/google/uuid"
imagespec "github.com/moby/docker-image-spec/specs-go/v1"
"github.com/moby/go-archive/compression"
"github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -168,17 +168,17 @@ func saveArchive(ctx context.Context, cs content.Store, layerReader io.Reader) (
bufRd := p.Get(layerReader)
defer p.Put(bufRd)
compression, err := detectCompression(bufRd)
comp, err := detectCompression(bufRd)
if err != nil {
return "", "", "", err
}
var uncompressedReader io.Reader = bufRd
switch compression {
case archive.Gzip, archive.Zstd:
switch comp {
case compression.Gzip, compression.Zstd:
// If the input is already a compressed layer, just save it as is.
mediaType := ocispec.MediaTypeImageLayerGzip
if compression == archive.Zstd {
if comp == compression.Zstd {
mediaType = ocispec.MediaTypeImageLayerZstd
}
@@ -188,19 +188,17 @@ func saveArchive(ctx context.Context, cs content.Store, layerReader io.Reader) (
}
return compressedDigest, uncompressedDigest, mediaType, nil
case archive.Bzip2, archive.Xz:
r, err := archive.DecompressStream(bufRd)
case compression.Bzip2, compression.Xz:
r, err := compression.DecompressStream(bufRd)
if err != nil {
return "", "", "", errdefs.InvalidParameter(err)
}
defer r.Close()
uncompressedReader = r
fallthrough
case archive.Uncompressed:
case compression.None:
mediaType := ocispec.MediaTypeImageLayerGzip
compression := archive.Gzip
compressedDigest, uncompressedDigest, err := compressAndWriteBlob(ctx, cs, compression, mediaType, uncompressedReader)
compressedDigest, uncompressedDigest, err := compressAndWriteBlob(ctx, cs, compression.Gzip, mediaType, uncompressedReader)
if err != nil {
return "", "", "", err
}
@@ -228,7 +226,7 @@ func writeCompressedBlob(ctx context.Context, cs content.Store, mediaType string
digester := digest.Canonical.Digester()
// Decompress the piped blob.
decompressedStream, err := archive.DecompressStream(pr)
decompressedStream, err := compression.DecompressStream(pr)
if err == nil {
// Feed the digester with decompressed data.
_, err = io.Copy(digester.Hash(), decompressedStream)
@@ -249,12 +247,12 @@ func writeCompressedBlob(ctx context.Context, cs content.Store, mediaType string
}
// compressAndWriteBlob compresses the uncompressedReader and stores it in the content store.
func compressAndWriteBlob(ctx context.Context, cs content.Store, compression archive.Compression, mediaType string, uncompressedLayerReader io.Reader) (digest.Digest, digest.Digest, error) {
func compressAndWriteBlob(ctx context.Context, cs content.Store, comp compression.Compression, mediaType string, uncompressedLayerReader io.Reader) (digest.Digest, digest.Digest, error) {
pr, pw := io.Pipe()
defer pr.Close()
defer pw.Close()
compressor, err := archive.CompressStream(pw, compression)
compressor, err := compression.CompressStream(pw, comp)
if err != nil {
return "", "", errdefs.InvalidParameter(err)
}
@@ -312,7 +310,7 @@ func (i *ImageService) unpackImage(ctx context.Context, snapshotter string, img
}
// detectCompression detects the reader compression type.
func detectCompression(bufRd *bufio.Reader) (archive.Compression, error) {
func detectCompression(bufRd *bufio.Reader) (compression.Compression, error) {
bs, err := bufRd.Peek(10)
if err != nil && err != io.EOF {
// Note: we'll ignore any io.EOF error because there are some odd
@@ -321,10 +319,10 @@ func detectCompression(bufRd *bufio.Reader) (archive.Compression, error) {
// cases we'll just treat it as a non-compressed stream and
// that means just create an empty layer.
// See Issue 18170
return archive.Uncompressed, errdefs.Unknown(err)
return compression.None, errdefs.Unknown(err)
}
return archive.DetectCompression(bs), nil
return compression.Detect(bs), nil
}
// fillUncompressedLabel sets the uncompressed digest label on the compressed blob metadata

View File

@@ -23,8 +23,7 @@ import (
)
func (i *ImageService) ImageInspect(ctx context.Context, refOrID string, opts backend.ImageInspectOpts) (*imagetypes.InspectResponse, error) {
// TODO: Pass in opts
var requestedPlatform *ocispec.Platform
requestedPlatform := opts.Platform
c8dImg, err := i.resolveImage(ctx, refOrID)
if err != nil {
@@ -60,7 +59,6 @@ func (i *ImageService) ImageInspect(ctx context.Context, refOrID string, opts ba
return nil, err
}
//nolint:govet // TODO: requestedPlatform is always nil, but should be passed by the caller
if multi.Best == nil && requestedPlatform != nil {
return nil, &errPlatformNotFound{
imageRef: refOrID,
@@ -87,6 +85,10 @@ func (i *ImageService) ImageInspect(ctx context.Context, refOrID string, opts ba
repoTags, repoDigests := collectRepoTagsAndDigests(ctx, tagged)
if requestedPlatform != nil {
target = multi.Best.Target()
}
resp := &imagetypes.InspectResponse{
ID: target.Digest.String(),
RepoTags: repoTags,

View File

@@ -61,4 +61,38 @@ func TestImageInspect(t *testing.T) {
})
}
})
t.Run("inspect image with platform parameter", func(t *testing.T) {
ctx := logtest.WithT(ctx, t)
service := fakeImageService(t, ctx, cs)
multiPlatformImage := toContainerdImage(t, func(dir string) (*ocispec.Index, error) {
idx, _, err := specialimage.MultiPlatform(dir, "multiplatform:latest", []ocispec.Platform{
{OS: "linux", Architecture: "amd64"},
{OS: "linux", Architecture: "arm64"},
})
return idx, err
})
_, err := service.images.Create(ctx, multiPlatformImage)
assert.NilError(t, err)
// Test with amd64 platform
amd64Platform := &ocispec.Platform{OS: "linux", Architecture: "amd64"}
inspectAmd64, err := service.ImageInspect(ctx, multiPlatformImage.Name, backend.ImageInspectOpts{
Platform: amd64Platform,
})
assert.NilError(t, err)
assert.Equal(t, inspectAmd64.Architecture, "amd64")
assert.Equal(t, inspectAmd64.Os, "linux")
// Test with arm64 platform
arm64Platform := &ocispec.Platform{OS: "linux", Architecture: "arm64"}
inspectArm64, err := service.ImageInspect(ctx, multiPlatformImage.Name, backend.ImageInspectOpts{
Platform: arm64Platform,
})
assert.NilError(t, err)
assert.Equal(t, inspectArm64.Architecture, "arm64")
assert.Equal(t, inspectArm64.Os, "linux")
})
}

View File

@@ -130,11 +130,13 @@ func (i *ImageService) Images(ctx context.Context, opts imagetypes.ListOptions)
}
dgst := img.Target.Digest
uniqueImages[dgst] = img
if isDangling {
if _, ok := uniqueImages[dgst]; !ok {
uniqueImages[dgst] = img
}
continue
}
uniqueImages[dgst] = img
ref, err := reference.ParseNormalizedNamed(img.Name)
if err != nil {

View File

@@ -14,7 +14,7 @@ import (
"github.com/containerd/platforms"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/internal/testutils/specialimage"
"github.com/docker/docker/pkg/archive"
"github.com/moby/go-archive"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"

View File

@@ -117,13 +117,12 @@ func (i *ImageService) pullTag(ctx context.Context, ref reference.Named, platfor
}
jobs := newJobs()
h := c8dimages.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
if c8dimages.IsLayerType(desc.MediaType) {
opts = append(opts, containerd.WithImageHandler(c8dimages.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
if showBlobProgress(desc) {
jobs.Add(desc)
}
return nil, nil
})
opts = append(opts, containerd.WithImageHandler(h))
})))
pp := &pullProgress{
store: i.content,
@@ -229,7 +228,7 @@ func (i *ImageService) pullTag(ctx context.Context, ref reference.Named, platfor
return errdefs.NotFound(fmt.Errorf("no matching manifest for %s in the manifest list entries: %w", platformStr, err))
}
}
return err
return translateRegistryError(ctx, err)
}
logger := log.G(ctx).WithFields(log.Fields{

View File

@@ -149,19 +149,13 @@ func (i *ImageService) pushRef(ctx context.Context, targetRef reference.Named, p
return err
}
addLayerJobs := c8dimages.HandlerFunc(
func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
switch {
case c8dimages.IsIndexType(desc.MediaType),
c8dimages.IsManifestType(desc.MediaType),
c8dimages.IsConfigType(desc.MediaType):
default:
jobsQueue.Add(desc)
}
addLayerJobs := c8dimages.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
if showBlobProgress(desc) {
jobsQueue.Add(desc)
}
return nil, nil
},
)
return nil, nil
})
handlerWrapper := func(h c8dimages.Handler) c8dimages.Handler {
return c8dimages.Handlers(addLayerJobs, h)
@@ -197,7 +191,7 @@ func (i *ImageService) pushRef(ctx context.Context, targetRef reference.Named, p
if err != nil {
if !cerrdefs.IsNotFound(err) {
return errdefs.System(err)
return translateRegistryError(ctx, err)
}
progress.Aux(out, auxprogress.ContentMissing{
ContentMissing: true,

View File

@@ -13,7 +13,6 @@ import (
"github.com/containerd/containerd/v2/core/snapshots"
"github.com/containerd/continuity/fs"
"github.com/containerd/continuity/sysx"
"github.com/docker/docker/pkg/idtools"
)
const (
@@ -54,12 +53,12 @@ func (i *ImageService) remapRootFS(ctx context.Context, mounts []mount.Mount) er
return fmt.Errorf("cannot get underlying data for %s", path)
}
ids, err := i.idMapping.ToHost(idtools.Identity{UID: int(stat.Uid), GID: int(stat.Gid)})
uid, gid, err := i.idMapping.ToHost(int(stat.Uid), int(stat.Gid))
if err != nil {
return err
}
return chownWithCaps(path, ids.UID, ids.GID)
return chownWithCaps(path, uid, gid)
})
})
}
@@ -82,7 +81,7 @@ func (i *ImageService) copyAndUnremapRootFS(ctx context.Context, dst, src []moun
return fmt.Errorf("cannot get underlying data for %s", path)
}
uid, gid, err := i.idMapping.ToContainer(idtools.Identity{UID: int(stat.Uid), GID: int(stat.Gid)})
uid, gid, err := i.idMapping.ToContainer(int(stat.Uid), int(stat.Gid))
if err != nil {
return err
}
@@ -105,7 +104,7 @@ func (i *ImageService) unremapRootFS(ctx context.Context, mounts []mount.Mount)
return fmt.Errorf("cannot get underlying data for %s", path)
}
uid, gid, err := i.idMapping.ToContainer(idtools.Identity{UID: int(stat.Uid), GID: int(stat.Gid)})
uid, gid, err := i.idMapping.ToContainer(int(stat.Uid), int(stat.Gid))
if err != nil {
return err
}

View File

@@ -337,3 +337,25 @@ func (combined combinedProgress) UpdateProgress(ctx context.Context, ongoing *jo
}
return nil
}
// showBlobProgress determines if the progress of pulling/pushing blob should be shown.
// Only indexes, manifests, and configs are hidden to align with the pre-containerd behavior.
// They are small enough JSON files so it's fine to not show them.
// We mostly care about bigger content like layers or other blobs.
func showBlobProgress(desc ocispec.Descriptor) bool {
switch {
case c8dimages.IsLayerType(desc.MediaType):
// Fast path: we always show progress for layers.
//
// Note: We can't just plainly check for c8dimages.IsLayerType alone
// because it wouldn't account for other potentially big blobs like
// artifacts or non-standard images.
return true
case c8dimages.IsIndexType(desc.MediaType),
c8dimages.IsManifestType(desc.MediaType),
c8dimages.IsConfigType(desc.MediaType):
return false
default:
return true
}
}

View File

@@ -0,0 +1,78 @@
package containerd
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/containerd/containerd/v2/core/remotes/docker"
remoteerrors "github.com/containerd/containerd/v2/core/remotes/errors"
cerrdefs "github.com/containerd/errdefs"
"github.com/containerd/log"
)
func translateRegistryError(ctx context.Context, err error) error {
// Check for registry specific error
var derrs docker.Errors
if !errors.As(err, &derrs) {
var remoteErr remoteerrors.ErrUnexpectedStatus
if errors.As(err, &remoteErr) {
if jerr := json.Unmarshal(remoteErr.Body, &derrs); jerr != nil {
log.G(ctx).WithError(derrs).Debug("unable to unmarshal registry error")
return fmt.Errorf("%w: %w", cerrdefs.ErrUnknown, err)
}
} else {
var derr docker.Error
if errors.As(err, &derr) {
derrs = append(derrs, derr)
} else {
return err
}
}
}
var errs []error
for _, err := range derrs {
var derr docker.Error
if errors.As(err, &derr) {
var message string
if derr.Message != "" {
message = derr.Message
} else {
message = derr.Code.Message()
}
if detail, ok := derr.Detail.(string); ok {
message = fmt.Sprintf("%s - %s", message, detail)
}
switch derr.Code {
case docker.ErrorCodeUnsupported:
err = cerrdefs.ErrNotImplemented.WithMessage(message)
case docker.ErrorCodeUnauthorized:
err = cerrdefs.ErrUnauthenticated.WithMessage(message)
case docker.ErrorCodeDenied:
err = cerrdefs.ErrPermissionDenied.WithMessage(message)
case docker.ErrorCodeUnavailable:
err = cerrdefs.ErrUnavailable.WithMessage(message)
case docker.ErrorCodeTooManyRequests:
err = cerrdefs.ErrResourceExhausted.WithMessage(message)
default:
err = cerrdefs.ErrUnknown.WithMessage(message)
}
} else {
errs = append(errs, cerrdefs.ErrUnknown.WithMessage(err.Error()))
}
errs = append(errs, err)
}
switch len(errs) {
case 0:
err = cerrdefs.ErrUnknown.WithMessage(err.Error())
case 1:
err = errs[0]
default:
err = errors.Join(errs...)
}
return fmt.Errorf("error from registry: %w", err)
}

View File

@@ -14,14 +14,13 @@ import (
cerrdefs "github.com/containerd/errdefs"
"github.com/containerd/log"
"github.com/containerd/platforms"
"github.com/distribution/reference"
"github.com/docker/docker/container"
daemonevents "github.com/docker/docker/daemon/events"
dimages "github.com/docker/docker/daemon/images"
"github.com/docker/docker/daemon/snapshotter"
"github.com/docker/docker/distribution"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/registry"
"github.com/moby/sys/user"
"github.com/pkg/errors"
)
@@ -34,32 +33,25 @@ type ImageService struct {
snapshotterServices map[string]snapshots.Snapshotter
snapshotter string
registryHosts docker.RegistryHosts
registryService registryResolver
registryService distribution.RegistryResolver
eventsService *daemonevents.Events
pruneRunning atomic.Bool
refCountMounter snapshotter.Mounter
idMapping idtools.IdentityMapping
idMapping user.IdentityMapping
// defaultPlatformOverride is used in tests to override the host platform.
defaultPlatformOverride platforms.MatchComparer
}
type registryResolver interface {
IsInsecureRegistry(host string) bool
ResolveRepository(name reference.Named) (*registry.RepositoryInfo, error)
LookupPullEndpoints(hostname string) ([]registry.APIEndpoint, error)
LookupPushEndpoints(hostname string) ([]registry.APIEndpoint, error)
}
type ImageServiceConfig struct {
Client *containerd.Client
Containers container.Store
Snapshotter string
RegistryHosts docker.RegistryHosts
Registry registryResolver
Registry distribution.RegistryResolver
EventsService *daemonevents.Events
RefCountMounter snapshotter.Mounter
IDMapping idtools.IdentityMapping
IDMapping user.IdentityMapping
}
// NewService creates a new ImageService.

View File

@@ -1,9 +1,14 @@
// TODO(thaJeztah): remove once we are a module; the go:build directive prevents go from downgrading language version to go1.16:
//go:build go1.22
package daemon // import "github.com/docker/docker/daemon"
import (
"context"
"fmt"
"os"
"strings"
"sync"
"time"
"github.com/containerd/log"
@@ -19,11 +24,15 @@ import (
"github.com/docker/docker/image"
"github.com/docker/docker/internal/metrics"
"github.com/docker/docker/internal/multierror"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/internal/otelutil"
"github.com/docker/docker/runconfig"
"github.com/moby/sys/user"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/selinux/go-selinux"
"github.com/tonistiigi/go-archvariant"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
)
type createOpts struct {
@@ -56,7 +65,15 @@ func (daemon *Daemon) ContainerCreateIgnoreImagesArgsEscaped(ctx context.Context
})
}
func (daemon *Daemon) containerCreate(ctx context.Context, daemonCfg *configStore, opts createOpts) (containertypes.CreateResponse, error) {
func (daemon *Daemon) containerCreate(ctx context.Context, daemonCfg *configStore, opts createOpts) (_ containertypes.CreateResponse, retErr error) {
ctx, span := otel.Tracer("").Start(ctx, "daemon.containerCreate", trace.WithAttributes(
labelsAsOTelAttributes(opts.params.Config.Labels)...,
))
defer func() {
otelutil.RecordStatus(span, retErr)
span.End()
}()
start := time.Now()
if opts.params.Config == nil {
return containertypes.CreateResponse{}, errdefs.InvalidParameter(runconfig.ErrEmptyConfig)
@@ -122,6 +139,31 @@ func (daemon *Daemon) containerCreate(ctx context.Context, daemonCfg *configStor
return containertypes.CreateResponse{ID: ctr.ID, Warnings: warnings}, nil
}
var (
containerLabelsFilter []string
containerLabelsFilterOnce sync.Once
)
func labelsAsOTelAttributes(labels map[string]string) []attribute.KeyValue {
containerLabelsFilterOnce.Do(func() {
containerLabelsFilter = strings.Split(os.Getenv("DOCKER_CONTAINER_LABELS_FILTER"), ",")
})
// This env var is a comma-separated list of labels to be included in the
// OTel span attributes. The labels are prefixed with "label." to avoid
// collision with other attributes.
//
// Note that, this is an experimental env var that might be removed
// unceremoniously at any point in time.
attrs := make([]attribute.KeyValue, 0, len(containerLabelsFilter))
for _, k := range containerLabelsFilter {
if v, ok := labels[k]; ok {
attrs = append(attrs, attribute.String("label."+k, v))
}
}
return attrs
}
// Create creates a new container from the given configuration with a given name.
func (daemon *Daemon) create(ctx context.Context, daemonCfg *config.Config, opts createOpts) (retC *container.Container, retErr error) {
var (
@@ -186,17 +228,18 @@ func (daemon *Daemon) create(ctx context.Context, daemonCfg *config.Config, opts
ctr.ImageManifest = imgManifest
// Set RWLayer for container after mount labels have been set
rwLayer, err := daemon.imageService.CreateLayer(ctr, setupInitLayer(daemon.idMapping))
rwLayer, err := daemon.imageService.CreateLayer(ctr, setupInitLayer(daemon.idMapping.RootPair()))
if err != nil {
return nil, errdefs.System(err)
}
ctr.RWLayer = rwLayer
current := idtools.CurrentIdentity()
if err := idtools.MkdirAndChown(ctr.Root, 0o710, idtools.Identity{UID: current.UID, GID: daemon.IdentityMapping().RootPair().GID}); err != nil {
cuid := os.Getuid()
_, gid := daemon.IdentityMapping().RootPair()
if err := user.MkdirAndChown(ctr.Root, 0o710, cuid, gid); err != nil {
return nil, err
}
if err := idtools.MkdirAndChown(ctr.CheckpointDir(), 0o700, current); err != nil {
if err := user.MkdirAndChown(ctr.CheckpointDir(), 0o700, cuid, os.Getegid()); err != nil {
return nil, err
}

View File

@@ -14,6 +14,7 @@ import (
"github.com/docker/docker/container"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/oci"
"github.com/docker/docker/pkg/idtools"
volumemounts "github.com/docker/docker/volume/mounts"
volumeopts "github.com/docker/docker/volume/service/opts"
"github.com/opencontainers/selinux/go-selinux/label"
@@ -27,8 +28,7 @@ func (daemon *Daemon) createContainerOSSpecificSettings(ctx context.Context, con
}
defer daemon.Unmount(container)
rootIDs := daemon.idMapping.RootPair()
if err := container.SetupWorkingDirectory(rootIDs); err != nil {
if err := container.SetupWorkingDirectory(daemon.idMapping.RootPair()); err != nil {
return err
}
@@ -107,8 +107,8 @@ func (daemon *Daemon) populateVolume(ctx context.Context, c *container.Container
}
return err
}
volumePath, cleanup, err := mnt.Setup(ctx, c.MountLabel, daemon.idMapping.RootPair(), nil)
uid, gid := daemon.idMapping.RootPair()
volumePath, cleanup, err := mnt.Setup(ctx, c.MountLabel, idtools.Identity{UID: uid, GID: gid}, nil)
if err != nil {
if errdefs.IsNotFound(err) {
return nil

View File

@@ -75,6 +75,7 @@ import (
"github.com/moby/buildkit/util/grpcerrors"
"github.com/moby/buildkit/util/tracing"
"github.com/moby/locker"
"github.com/moby/sys/user"
"github.com/moby/sys/userns"
"github.com/pkg/errors"
"go.etcd.io/bbolt"
@@ -113,7 +114,7 @@ type Daemon struct {
sysInfoOnce sync.Once
sysInfo *sysinfo.SysInfo
shutdown bool
idMapping idtools.IdentityMapping
idMapping user.IdentityMapping
PluginStore *plugin.Store // TODO: remove
pluginManager *plugin.Manager
linkIndex *linkIndex
@@ -263,7 +264,7 @@ func (daemon *Daemon) restore(cfg *configStore) error {
removeContainers := make(map[string]*container.Container)
restartContainers := make(map[*container.Container]chan struct{})
activeSandboxes := make(map[string]interface{})
activeSandboxes := make(map[string]any)
for _, c := range containers {
group.Add(1)
@@ -791,7 +792,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
if err != nil {
return nil, err
}
rootIDs := idMapping.RootPair()
uid, gid := idMapping.RootPair()
// set up the tmpDir to use a canonical path
tmp, err := prepareTempDir(config.Root)
@@ -878,10 +879,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
}
daemonRepo := filepath.Join(cfgStore.Root, "containers")
if err := idtools.MkdirAllAndChown(daemonRepo, 0o710, idtools.Identity{
UID: idtools.CurrentIdentity().UID,
GID: rootIDs.GID,
}); err != nil {
if err := user.MkdirAllAndChown(daemonRepo, 0o710, os.Getuid(), gid); err != nil {
return nil, err
}
@@ -967,7 +965,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
var (
shim string
shimOpts interface{}
shimOpts any
)
if runtime.GOOS != "windows" {
shim, shimOpts, err = rts.Get("")
@@ -999,7 +997,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
}
log.G(ctx).Debugf("Using default logging driver %s", d.defaultLogConfig.Type)
d.volumes, err = volumesservice.NewVolumeService(cfgStore.Root, d.PluginStore, rootIDs, d)
d.volumes, err = volumesservice.NewVolumeService(cfgStore.Root, d.PluginStore, idtools.Identity{UID: uid, GID: gid}, d)
if err != nil {
return nil, err
}
@@ -1423,7 +1421,7 @@ func prepareTempDir(rootDir string) (string, error) {
}
}
}
return tmpDir, idtools.MkdirAllAndChown(tmpDir, 0o700, idtools.CurrentIdentity())
return tmpDir, user.MkdirAllAndChown(tmpDir, 0o700, os.Getuid(), os.Getegid())
}
func (daemon *Daemon) setGenericResources(conf *config.Config) error {
@@ -1446,7 +1444,7 @@ func isBridgeNetworkDisabled(conf *config.Config) bool {
return conf.BridgeConfig.Iface == config.DisableNetworkBridge
}
func (daemon *Daemon) networkOptions(conf *config.Config, pg plugingetter.PluginGetter, hostID string, activeSandboxes map[string]interface{}) ([]nwconfig.Option, error) {
func (daemon *Daemon) networkOptions(conf *config.Config, pg plugingetter.PluginGetter, hostID string, activeSandboxes map[string]any) ([]nwconfig.Option, error) {
options := []nwconfig.Option{
nwconfig.OptionDataDir(filepath.Join(conf.Root, config.LibnetDataPath)),
nwconfig.OptionExecRoot(conf.GetExecRoot()),
@@ -1545,7 +1543,8 @@ func CreateDaemonRoot(config *config.Config) error {
if err != nil {
return err
}
return setupDaemonRoot(config, realRoot, idMapping.RootPair())
uid, gid := idMapping.RootPair()
return setupDaemonRoot(config, realRoot, uid, gid)
}
// RemapContainerdNamespaces returns the right containerd namespaces to use:
@@ -1561,16 +1560,16 @@ func RemapContainerdNamespaces(config *config.Config) (ns string, pluginNs strin
if idMapping.Empty() {
return config.ContainerdNamespace, config.ContainerdPluginNamespace, nil
}
root := idMapping.RootPair()
uid, gid := idMapping.RootPair()
ns = config.ContainerdNamespace
if _, ok := config.ValuesSet["containerd-namespace"]; !ok {
ns = fmt.Sprintf("%s-%d.%d", config.ContainerdNamespace, root.UID, root.GID)
ns = fmt.Sprintf("%s-%d.%d", config.ContainerdNamespace, uid, gid)
}
pluginNs = config.ContainerdPluginNamespace
if _, ok := config.ValuesSet["containerd-plugin-namespace"]; !ok {
pluginNs = fmt.Sprintf("%s-%d.%d", config.ContainerdPluginNamespace, root.UID, root.GID)
pluginNs = fmt.Sprintf("%s-%d.%d", config.ContainerdPluginNamespace, uid, gid)
}
return ns, pluginNs, nil
@@ -1600,7 +1599,7 @@ func (daemon *Daemon) GetAttachmentStore() *network.AttachmentStore {
}
// IdentityMapping returns uid/gid mapping or a SID (in the case of Windows) for the builder
func (daemon *Daemon) IdentityMapping() idtools.IdentityMapping {
func (daemon *Daemon) IdentityMapping() user.IdentityMapping {
return daemon.idMapping
}

Some files were not shown because too many files have changed in this diff Show More