Commit Graph

49 Commits

Author SHA1 Message Date
Sebastiaan van Stijn
0df791cb72 explicitly access Container.State instead of through embedded struct
The Container.State struct holds the container's state, and most of
its fields are expected to change dynamically. Some o these state-changes
are explicit, for example, setting the container to be "stopped". Other
state changes can be more explicit, for example due to the containers'
process exiting or being "OOM" killed by the kernel.

The distinction between explicit ("desired") state changes and "state"
("actual state") is sometimes vague; for some properties, we clearly
separated them, for example if a user requested the container to be
stopped or restarted, we store state in the Container object itself;

    HasBeenManuallyStopped   bool // used for unless-stopped restart policy
    HasBeenManuallyRestarted bool `json:"-"` // used to distinguish restart caused by restart policy from the manual one

Other properties are more ambiguous. such as "HasBeenStartedBefore" and
"RestartCount", which are stored on the Container (and persisted to
disk), but may be more related to "actual" state, and likely should
not be persisted;

    RestartCount             int
    HasBeenStartedBefore     bool

Given that (per the above) concurrency must be taken into account, most
changes to the `container.State` struct should be protected; here's where
things get blurry. While the `State` type provides various accessor methods,
only some of them take concurrency into account; for example, [State.IsRunning]
and [State.GetPID] acquire a lock, whereas [State.ExitCodeValue] does not.
Even the (commonly used) [State.StateString] has no locking at all.

The way to handle this is error-prone; [container.State] contains a mutex,
and it's exported. Given that its embedded in the [container.Container]
struct, it's also exposed as an exported mutex for the container. The
assumption here is that by "merging" the two, the caller to acquire a lock
when either the container _or_ its state must be mutated. However, because
some methods on `container.State` handle their own locking, consumers must
be deeply familiar with the internals; if both changes to the `Container`
AND `Container.State` must be made. This gets amplified more as some
(exported!) methods, such as [container.SetRunning] mutate multiple fields,
but don't acquire a lock (so expect the caller to hold one), but their
(also exported) counterpart (e.g. [State.IsRunning]) do.

It should be clear from the above, that this needs some architectural
changes; a clearer separation between "desired" and "actual" state (opening
the potential to update the container's config without manually touching
its `State`), possibly a method to obtain a read-only copy of the current
state (for those querying state), and reviewing which fields belong where
(and should be persisted to disk, or only remain in memory).

This PR preserves the status quo; it makes no structural changes, other
than exposing where we access the container's state. Where previously the
State fields and methods were referred to as "part of the container"
(e.g. `ctr.IsRunning()` or `ctr.Running`), we now explicitly reference
the embedded `State` (`ctr.State.IsRunning`, `ctr.State.Running`).

The exception (for now) is the mutex, which is still referenced through
the embedded struct (`ctr.Lock()` instead of `ctr.State.Lock()`), as this
is (mostly) by design to protect the container, and what's in it (including
its `State`).

[State.IsRunning]: c4afa77157/daemon/container/state.go (L205-L209)
[State.GetPID]: c4afa77157/daemon/container/state.go (L211-L216)
[State.ExitCodeValue]: c4afa77157/daemon/container/state.go (L218-L228)
[State.StateString]: c4afa77157/daemon/container/state.go (L102-L131)
[container.State]: c4afa77157/daemon/container/state.go (L15-L23)
[container.Container]: c4afa77157/daemon/container/container.go (L67-L75)
[container.SetRunning]: c4afa77157/daemon/container/state.go (L230-L277)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-09-19 16:02:14 +02:00
Austin Vazquez
749ec81706 Merge pull request #50799 from thaJeztah/touchup_delete
image delete: inline some variables, and touch-up TODOs
2025-09-04 12:27:30 -07:00
Austin Vazquez
853aed171b api/types/image: move image option types to client
Signed-off-by: Austin Vazquez <austin.vazquez@docker.com>
2025-08-26 15:38:44 -05:00
Sebastiaan van Stijn
6fbea5f5c1 image delete: inline some variables, and touch-up TODOs
- inline / scope some variables
- touch up various TODOs to help find back context

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-08-23 18:34:05 +02:00
Sebastiaan van Stijn
cf15d5bbc6 remove obsolete //go:build tags
These are no longer needed as these are now part of a module.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-08-01 00:49:22 +02:00
Derek McGowan
f74e5d48b3 Create github.com/moby/moby/v2 module
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-07-31 10:13:29 -07:00
Sebastiaan van Stijn
ca1c5ee08f pkg/stringid: move to daemon, and provide copy in client
The stringid package is used in many places; while it's trivial
to implement a similar utility, let's just provide it as a utility
package in the client, removing the daemon-specific logic.

For integration tests, I opted to use the implementation in the
client, as those should not ideally not make assumptions about
the daemon implementation.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-07-25 13:39:32 +02:00
Derek McGowan
f24455c90b Move image to daemon/internal/image
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-07-24 12:11:02 -07:00
Derek McGowan
afd6487b2e Create github.com/moby/moby/api module
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-07-21 09:30:05 -07:00
Derek McGowan
5419eb1efc Move container to daemon/container
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-06-27 14:27:21 -07:00
Derek McGowan
0b2582dc8f Move internal/metrics to daemon/internal/metrics
Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-06-27 14:25:45 -07:00
Paweł Gronowski
072483f9d7 c8d/delete: Require --force when deleting platforms
When deleting specific platforms from a multi-platform image, there's
potential risk as platform-specific content might be shared across
images/containers.

For now, require `force` parameter to make the user aware.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-05-26 17:43:10 +02:00
Paweł Gronowski
30da69d694 c8d/delete: Support deleting specific platforms
This change adds the ability to delete a specific platform from a
multi-platform image.

Previously, image deletion was an all-or-nothing operation - when
deleting a multi-platform image, all platforms would be removed
together. This change allows users to selectively remove individual
platforms from a multi-architecture image while keeping other platforms
intact.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-05-26 17:43:10 +02:00
Paweł Gronowski
acf6b6542e daemon/images: Make ImageDelete take opts struct
Pass whole `RemoveOptions` struct instead of individual `force` and
`prune` parameters.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-05-26 17:43:09 +02:00
Paweł Gronowski
871675be9b c8d/delete: Extract untagReferences
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-05-26 17:43:08 +02:00
Jonathan A. Sternberg
61646c8bfc containerd: remove unleaseSnapshotsFromDeletedConfigs
Removes workaround for https://github.com/moby/buildkit/issues/3797 now
that the underlying issue is fixed.

Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
2025-05-14 09:20:22 -05:00
Sebastiaan van Stijn
088c180a9e daemon/containerd: remove named err-returns
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-04-28 15:06:34 +02:00
Laurent Goderre
844797348e Implement image mount for the snapshotter
Signed-off-by: Laurent Goderre <laurent.goderre@docker.com>
2025-01-31 10:34:27 -05:00
Derek McGowan
0aa8fe0bf9 Update to containerd v2.0.2, buildkit v0.19.0-rc2
Update buildkit version to commit which uses 2.0

Signed-off-by: Derek McGowan <derek@mcg.dev>
2025-01-15 14:09:30 +01:00
Sebastiaan van Stijn
ee1a15a970 daemon: ImageService.LogImageEvent: pass through context
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2025-01-08 15:43:17 +01:00
Paweł Gronowski
438f5801e1 daemon/images: Move ImageActions to metrics
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2025-01-07 14:13:07 +01:00
Paweł Gronowski
90fef061ec daemon/c8d: Force c8dimages alias for containerd/images
Change all github.com/containerd/containerd/images imports to be
imported as `c8dimages`.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-12-19 18:39:43 +01:00
Paweł Gronowski
8c30e11321 c8d/delete: Consistent method receiver
`imageDeleteConflict` is always returned via a reference, so adjust the
method receiver of `Conflict` to make it consistent with `Error`.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-12-19 18:39:42 +01:00
Paweł Gronowski
1ad78f00b1 daemon/c8d: Fix duplicate containerd/images import
Remove duplicate imports under different aliases

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-12-19 18:39:40 +01:00
Sebastiaan van Stijn
979227484f daemon/containerd: ImageService.imageDeleteHelper: fix shadowed variable (govet)
daemon/containerd/image_delete.go:378:4: shadow: declaration of "img" shadows declaration at line 355 (govet)
                img := images.Image{
                ^

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-11-06 12:54:51 +01:00
Sebastiaan van Stijn
5343c7b451 remove internal/compatcontext and use context instead
This internal package was added in f6e44bc0e8
to preserve compatibility with go1.20 and older. At the time, our vendor.mod
still had go1.18 as minimum version requirement (see [1]), which got updated to go1.20
in 16063c7456, and go1.21 in f90b03ee5d

The version of BuildKit we use already started using context.WithoutCancel,
without a fallback, so we no longer can provide compatibility with older
versions of Go, which makes our compatiblity package redundant.

This patch removes the package, and updates our code to use stdlib's context
instead.

[1]: f6e44bc0e8/vendor.mod (L7)

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-13 13:29:39 +02:00
Sebastiaan van Stijn
86f7762d48 vendor: github.com/containerd/containerd v1.7.18
Update to containerd 1.7.18, which now migrated to the errdefs module. The
existing errdefs package is now an alias for the module, and should no longer
be used directly.

This patch:

- updates the containerd dependency: https://github.com/containerd/containerd/compare/v1.7.17...v1.7.18
- replaces uses of the old package in favor of the new module
- adds a linter check to prevent accidental re-introduction of the old package
- adds a linter check to prevent using the "log" package, which was also
  migrated to a separate module.

There are still some uses of the old package in (indirect) dependencies,
which should go away over time.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2024-06-05 09:21:00 +02:00
Djordje Lukic
1cfd763214 c8d: Send image delete metrics to prometheus
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2024-03-13 15:03:42 +01:00
Paweł Gronowski
74e2f23e1a daemon/c8d: Use i.images and i.content
Use `image.Store` and `content.Store` stored in the ImageService struct
instead of fetching it every time from containerd client.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-03-07 16:25:27 +01:00
Djordje Lukic
71ebfc7c63 c8d: make the cache in classic builder work
In order for the cache in the classic builder to work we need to:
- use the came comparison function as the graph drivers implementation
- save the container config when commiting the image
- use all images to search a 'FROM "scratch"' image
- load all images if `cacheFrom` is empty

Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2024-01-17 14:57:50 +01:00
Derek McGowan
cf1ea9237c Add dangling image reference on delete when last image has children
Signed-off-by: Derek McGowan <derek@mcg.dev>
2023-12-19 05:56:43 -08:00
Derek McGowan
0c6e9121b2 Add support for removing repo and digest
When repo and digest is provided, remove all references within a
repository for the given digest.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2023-12-18 16:33:53 -08:00
Derek McGowan
87c87bccb5 Update cleanup logic to use resolve all images
Ensure that when removing an image, an image is checked consistently
against the images with the same target digest. Add unit testing around
delete.

Signed-off-by: Derek McGowan <derek@mcg.dev>
2023-12-18 14:04:48 -08:00
Sebastiaan van Stijn
48cacbca24 api/types: move image-types to api/types/image
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-10-12 11:29:20 +02:00
Sebastiaan van Stijn
cff4f20c44 migrate to github.com/containerd/log v0.1.0
The github.com/containerd/containerd/log package was moved to a separate
module, which will also be used by upcoming (patch) releases of containerd.

This patch moves our own uses of the package to use the new module.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-10-11 17:52:23 +02:00
Sebastiaan van Stijn
f0698dae14 Merge pull request #46590 from vvoland/c8d-tag-ctx-withoutcancel
daemon/c8d: Use WithoutCancel instead of context.Background
2023-10-11 16:55:16 +02:00
Paweł Gronowski
b8ba263099 c8d/rmi: Handle explicit dangling name
This isn't something that user should do, but technically the dangling
images exist in the image store and user can pass its name (`moby-dangling@digest`).
Change it so rmi now recognizes that it's actually a dangling image and
doesn't handle it like a regular tagged image.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2023-10-06 10:20:37 +02:00
Paweł Gronowski
25a813e924 c8d/rmi: Don't emit Untagged for dangling images
A dangling image isn't really a tag.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2023-10-06 10:20:35 +02:00
Paweł Gronowski
e0e6ae741e daemon/c8d: Use WithoutCancel instead of context.Background
Instead of passing a completely fresh context without any values, just
discard the cancellation.

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2023-10-04 13:17:51 +02:00
Sebastiaan van Stijn
1148a24e64 migrate to new github.com/distribution/reference module
The "reference" package was moved to a separate module, which was extracted
from b9b19409cf

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-09-05 12:09:26 +02:00
Sebastiaan van Stijn
0f871f8cb7 api/types/events: define "Action" type and consts
Define consts for the Actions we use for events, instead of "ad-hoc" strings.
Having these consts makes it easier to find where specific events are triggered,
makes the events less error-prone, and allows documenting each Action (if needed).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-08-29 00:38:08 +02:00
Brian Goff
74da6a6363 Switch all logging to use containerd log pkg
This unifies our logging and allows us to propagate logging and trace
contexts together.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
2023-06-24 00:23:44 +00:00
Paweł Gronowski
4295806736 c8d/handlers: Handle error in walkPresentChildren
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2023-06-02 10:23:03 +02:00
Laura Brehm
cad97135b3 c8d: implement missing image delete logic
Ports over all the previous image delete logic, such as:
- Introduce `prune` and `force` flags
- Introduce the concept of hard and soft image delete conflics, which represent:
  - image referenced in multiple tags (soft conflict)
  - image being used by a stopped container (soft conflict)
  - image being used by a running container (hard conflict)
- Implement delete logic such as:
  - if deleting by reference, and there are other references to the same image, just
    delete the passed reference
  - if deleting by reference, and there is only 1 reference and the image is being used
    by a running container, throw an error if !force, or delete the reference and create
    a dangling reference otherwise
  - if deleting by imageID, and force is true, remove all tags (otherwise soft conflict)
  - if imageID, check if stopped container is using the image (soft conflict), and
    delete anyway if force
  - if imageID was passed in, check if running container is using the image (hard conflict)
  - if `prune` is true, and the image being deleted has dangling parents, remove them

This commit also implements logic to get image parents in c8d by comparing shared layers.

Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2023-05-08 02:32:03 +01:00
Paweł Gronowski
52af6d957e c8d/prune: Remove gc.ref labels from configs of deleted images
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2023-04-26 16:40:34 +02:00
Laura Brehm
8df3db4b97 c8d: add support for removing images by shortID
Signed-off-by: Laura Brehm <laurabrehm@hey.com>
2023-04-21 10:30:53 +01:00
Djordje Lukic
1b178dffa3 Send an event when an image is deleted
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
2023-04-04 15:54:11 +02:00
Djordje Lukic
26c65447df Implement ImageDelete for containerd
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-07-28 22:56:34 +02:00
Sebastiaan van Stijn
9c8b0b6050 daemon/containerd: split methods to separate files
This splits the ImageService methods to separate files, to closer
match the existing implementation, and to reduce the amount of code
per file, making it easier to read, and to reduce merge conflicts if
new functionality is added.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2022-07-18 14:46:31 +02:00