If a container was started with
- a numeric uid
- both a user and group (username:groupname)
- uid and gid (uid:gid)
The copy action failed, because the "username:groupname"
was looked up using getent.
This patch;
- splits `user` and `group` before looking up
- if numeric `uid` or `gid` is used and lookup fails,
the `uid` / `gid` is used as-is
The code also looked up the user and group on the host
instead of in the container when using getent; this patch
fixes the lookup to only use the container's /etc/passwd
and /etc/group instead.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
integration/container/run_linux_test.go:459:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
(thanks Go)
Signed-off-by: Tianon Gravi <admwiggin@gmail.com>
This requires changes in the CLI to support fully, but matches our other boolean option handling (`no-new-privileges`).
Signed-off-by: Tianon Gravi <admwiggin@gmail.com>
This makes `WritableCgroups` a pointer so we can error when it's specified in invalid configurations (both rootless and user namespaces).
Signed-off-by: Tianon Gravi <admwiggin@gmail.com>
The StatsResponse type was a compatibility-wrapper introduced in
d3379946ec to differentiate responses
for API < 1.21 and API >= 1.21. API versions lower than 1.24 are
deprecated, and we should merge StatsResponse and Stats, but let's
start with using the StatsResponse in our tests.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This test was testing errors produced by runc; both the "maximum" and
"minimum" values originate from the OCI runtime;
d48d9cfefc/libcontainer/cgroups/fs/cpu.go (L66-L83)
docker run --cpu-shares=1 alpine
docker: Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error setting cgroup config for procHooks process: the minimum allowed cpu-shares is 2: unknown.
Happy path for this setting is covered by TestRunWithCPUShares, and
various other tests, so we validate that the options take effect;
f5af46d4d5/integration-cli/docker_cli_run_unix_test.go (L494-L503)
This patch:
- removes the test and migrates it to an integration test
- removes the checks for errors that might be produced by runc
- updates our validation for invalid (negative) values to happen
when creating the contaienr; the existing check that happened when
creating the OCI spec is preserved, so that configs of existing containers
are still validated.
- updates validateResources to return the correct error-type
- updated unit-test to validate
With this patch:
make TEST_FILTER='TestCreateInvalidHostConfig' TEST_SKIP_INTEGRATION_CLI=1 test-integration
--- PASS: TestCreateInvalidHostConfig (0.00s)
--- PASS: TestCreateInvalidHostConfig/invalid_IpcMode (0.00s)
--- PASS: TestCreateInvalidHostConfig/invalid_CPUShares (0.00s)
--- PASS: TestCreateInvalidHostConfig/invalid_PidMode (0.00s)
--- PASS: TestCreateInvalidHostConfig/invalid_PidMode_without_container_ID (0.00s)
--- PASS: TestCreateInvalidHostConfig/invalid_Annotations (0.00s)
--- PASS: TestCreateInvalidHostConfig/invalid_UTSMode (0.00s)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This test originally added in 4352da7803,
and was a bit involved as it involved building an image, and had some
dubious test-cases, such as using `wrongimage:<ID of other image>` as
reference, and expecting that to produce a "not found" error. Possibly
this format was supported in the past, but currently it fails equally with
`correctimage:<ID of image>`.
This patch rewrites the test to an integration test, and removes the test
from integration-cli. It also removes TestCreate64ByteHexID, as it was
duplicated by this test.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
If we have an error type that we're checking a substring against, we
should really be checking using ErrorContains to indicate the right
semantics to assert.
Mostly done using these transforms:
find . -type f -name "*_test.go" | \
xargs gofmt -w -r 'assert.Assert(t, is.ErrorContains(e, s)) -> assert.ErrorContains(t, e, s)'
find . -type f -name "*_test.go" | \
xargs gofmt -w -r 'assert.Assert(t, is.Contains(err.Error(), s)) -> assert.ErrorContains(t, err, s)'
find . -type f -name "*_test.go" | \
xargs gofmt -w -r 'assert.Check(t, is.Contains(err.Error(), s)) -> assert.Check(t, is.ErrorContains(err, s))'
As well as some small fixups to helpers that were doing
strings.Contains explicitly.
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
If a values is non-nil when we don't expect it, it would be quite
helpful to get an error message explaining what happened.
find . -type f -name "*_test.go" | \
xargs gofmt -w -r "assert.Assert(t, a == nil) -> assert.Assert(t, is.Nil(a))"
find . -type f -name "*_test.go" | \
xargs gofmt -w -r "assert.Check(t, a == nil) -> assert.Check(t, is.Nil(a))"
Signed-off-by: Aleksa Sarai <cyphar@cyphar.com>
Set the daemon.json config as a string-literal in the tests, instead of
using a map[string]interface{} as intermediary format.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
`ImageManifestDescriptor` will contain an OCI descriptor of
platform-specific manifest of the image that was picked when creating
the container.
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Some other tests on this file where skipped with this same line. Let's
skip this one, that seems to be flaky too.
Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
integration/container/attach_test.go:39:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/container_test.go:28:3: The copy of the 'for' variable "ep" can be deleted (Go 1.22+) (copyloopvar)
ep := ep
^
integration/container/create_test.go:57:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/create_test.go:120:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/create_test.go:406:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/create_test.go:583:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/exec_test.go:218:4: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/kill_test.go:70:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/kill_test.go:110:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/logs_test.go:130:3: The copy of the 'for' variable "tC" can be deleted (Go 1.22+) (copyloopvar)
tC := tC
^
integration/container/overlayfs_linux_test.go:59:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/resize_test.go:107:4: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/restart_test.go:78:5: The copy of the 'for' variable "stopDaemon" can be deleted (Go 1.22+) (copyloopvar)
stopDaemon := stopDaemon
^
integration/container/restart_test.go:188:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/run_linux_test.go:341:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/stop_linux_test.go:58:3: The copy of the 'for' variable "d" can be deleted (Go 1.22+) (copyloopvar)
d := d
^
integration/container/wait_test.go:40:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/wait_test.go:83:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/wait_test.go:133:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
integration/container/wait_test.go:205:3: The copy of the 'for' variable "tc" can be deleted (Go 1.22+) (copyloopvar)
tc := tc
^
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Anonymous volumes get a unique, 64-character name, and intended to be a new
volume (not an existing one). While it's theoretically possible for this name
to exist in other volume drivers, this would be very unlikely, so we should
not need to check other drivers to have this volume.
This patch uses the default ("local") volume-driver for anonymous volumes,
unless the user explicitly asked for a specific driver to use. Setting the
driver skips looking up existing volumes in other drivers.
Before this patch:
DEBU[2024-10-26T15:51:12.681547126Z] container mounted via snapshotter: /var/lib/docker/rootfs/overlayfs/7e947822249514b6239657a0c54d091d90e0fed4b09da472f3f6258f2b4920bc container=7e947822249514b6239657a0c54d091d90e0fed4b09da472f3f6258f2b4920bc
DEBU[2024-10-26T15:51:12.681616084Z] Creating anonymous volume volume-name=fd46d688247c3e7d39d9bae4532d6b2dc69e82e354c4a3bf305c50bbfb9ebc6c
DEBU[2024-10-26T15:51:12.681638959Z] Probing all drivers for volume volume-name=fd46d688247c3e7d39d9bae4532d6b2dc69e82e354c4a3bf305c50bbfb9ebc6c
DEBU[2024-10-26T15:51:12.681688917Z] Registering new volume reference driver=local volume-name=fd46d688247c3e7d39d9bae4532d6b2dc69e82e354c4a3bf305c50bbfb9ebc6c
With this patch:
DEBU[2024-10-27T17:28:28.574956716Z] container mounted via snapshotter: /var/lib/docker/rootfs/overlayfs/7085cb3991b61cbb79edffcb6980ad926f99f6b6b3be617cc3e3b92673cc2eb8 container=7085cb3991b61cbb79edffcb6980ad926f99f6b6b3be617cc3e3b92673cc2eb8
DEBU[2024-10-27T17:28:28.575002549Z] Creating anonymous volume driver=local volume-name=db11c053566362499103213542402af2770a6622fe7a90b9a938a5bed84ca937
DEBU[2024-10-27T17:28:28.575016299Z] Registering new volume reference driver=local volume-name=db11c053566362499103213542402af2770a6622fe7a90b9a938a5bed84ca937
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
`Parser.ParseMountRaw()` labels anonymous volumes with a `AnonymousLabel` label
(`com.docker.volume.anonymous`) label based on whether a volume has a name
(named volume) or no name (anonymous) (see [1]).
However both `VolumesService.Create()` (see [1]) and `Parser.ParseMountRaw()`
(see [2], [3]) were generating a random name for anonymous volumes. The latter
is called before `VolumesService.Create()` is called, resulting in such volumes
not being labeled as anonymous.
Generating the name was originally done in Create (fc7b904dce),
but duplicated in b3b7eb2723 with the introduction
of the new Mounts field in HostConfig. Duplicating this effort didn't have a
real effect until (`Create` would just skip generating the name), until
618f26ccbc introduced the `AnonymousLabel` in
(v24.0.0, backported to v23.0.0).
Parsing generally should not fill in defaults / generate names, so this patch;
- Removes generating volume names from `Parser.ParseMountRaw()`
- Adds a debug-log entry to `VolumesService.Create()`
- Touches up some logs to use structured logs for easier correlating logs
With this patch applied:
docker run --rm --mount=type=volume,target=/toto hello-world
DEBU[2024-10-24T22:50:36.359990376Z] creating anonymous volume volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02
DEBU[2024-10-24T22:50:36.360069209Z] probing all drivers for volume volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02
DEBU[2024-10-24T22:50:36.360341209Z] Registering new volume reference driver=local volume-name=0cfd63d4df363571e7b3e9c04e37c74054cc16ff1d00d9a005232d83e92eda02
[1]: 032721ff75/volume/service/service.go (L72-L83)
[2]: 032721ff75/volume/mounts/linux_parser.go (L330-L336)
[3]: 032721ff75/volume/mounts/windows_parser.go (L394-L400)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
TestAttachDisconnectLeak starts its own daemon with iptables disabled,
but disabling ip6tables was missed when we enabled ip6tables by default.
TestNetworkStateCleanupOnDaemonStart also starts its own daemon, with
iptables and ip6tables both enabled. It isn't trying to test anything
iptables related.
These tests run in parallel, so they both modify ip6tables in the host
namespace - and could break each other by adding/removing chains at
awkward moments.
Disable iptables and ip6tables in both tests.
Signed-off-by: Rob Murray <rob.murray@docker.com>
If we fail to start an exec, the deferred error-handling block in [L181-L193](c7e42d855e/daemon/exec.go (L181-L193))
would set the exit code to `126` (`EACCES`). However, if we get far enough along
attempting to start the exec, we set the exit code according to the error returned
from starting the task [L288-L291](c7e42d855e/daemon/exec.go (L288-L291)).
For some situations (such as `docker exec [some-container]
missing-binary`), the 2nd block returns the correct exit code (`127`)
but that then gets overwritten by the 1st block.
This commit changes that logic to only set the default exit code `126`
if the exit code has not been set yet.
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
This moves the `ContainerJSONBase`, `ContainerJSON` and `ContainerNode`
types to the api/types/container package and deprecates the old location.
- `ContainerJSONBase` was renamed to `InspectBase`
- `ContainerJSON` was rnamed to `InspectResponse`
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This moves the `Container` type to the containere package, rename
it to `Summary`, and deprecates the old location.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This moves the `Health` and `HealthcheckResult` types to the container package,
as well as the related `NoHealthcheck`, `Starting`, `Healthy`, and `Unhealthy`
consts.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This populates the "Image" field on containerd containers, but only when
using the containerd image store.
This allows containerd clients to look up the image information.
Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Signed-off-by: Bjorn Neergaard <bjorn.neergaard@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This package was originally added in 46833ee1c3
for use in the devicemapper graphdriver. The devicemapper graphdriver was
deprecated and has been removed. The only remaining consumer is an integration
test.
Deprecate the package and mark it for removal in the next release.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
When the container stops or during `restore`, `daemon.releaseNetwork` is
used to clear all net-related state carried by a container. However, the
fields `SandboxID` and `SandboxKey` are never cleared. On the next start,
these fields will be replaced with new values. There's no point in
preserving these data since they became invalid as soon as the container
stopped.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>
When the daemon crashes, the host unexpectedly reboot, or the daemon
restarts with live-restore enabled, running containers might stop and the
on-disk state for containers might diverge from reality. All these
situations are currently handled by the daemon's `restore` method.
That method calls `daemon.Cleanup()` for all the dead containers. In
turn, `Cleanup` calls `daemon.releaseNetwork()`. However, this last
method won't do anything because it expects the `netController` to be
initialized when it's called. That's not the case in the `restore` code
path -- the `netController` is initialized _after_ cleaning up dead
containers.
There's a chicken-egg problem here, and fixing that would require some
important architectural changes (eg. change the way libnet's controller
is initialized).
Since `releaseNetwork()` early exits, dead containers won't ever have
their networking state cleaned. This led to bugs in Docker Desktop,
among other things.
Fix that by calling `releaseNetwork` after initializing the
`netController`.
Signed-off-by: Albin Kerouanton <albinker@gmail.com>