Merge pull request #47239 from cpuguy83/containerd_image_info

Set containerd container image ref
This commit is contained in:
Paweł Gronowski
2024-06-17 17:02:24 +02:00
committed by GitHub
8 changed files with 178 additions and 1 deletions

View File

@@ -97,6 +97,10 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
info.Runtimes[k] = system.RuntimeWithStatus{Runtime: rt.Runtime}
}
}
if versions.LessThan(version, "1.46") {
// Containerd field introduced in API v1.46.
info.Containerd = nil
}
if versions.GreaterThanOrEqualTo(version, "1.42") {
info.KernelMemory = false
}

View File

@@ -5824,6 +5824,58 @@ definitions:
example:
- "/etc/cdi"
- "/var/run/cdi"
Containerd:
$ref: "#/definitions/ContainerdInfo"
x-nullable: true
ContainerdInfo:
description: |
Information for connecting to the containerd instance that is used by the daemon.
This is included for debugging purposes only.
type: "object"
properties:
Address:
description: "The address of the containerd socket."
type: "string"
example: "/run/containerd/containerd.sock"
Namespaces:
description: |
The namespaces that the daemon uses for running containers and
plugins in containerd. These namespaces can be configured in the
daemon configuration, and are considered to be used exclusively
by the daemon, Tampering with the containerd instance may cause
unexpected behavior.
As these namespaces are considered to be exclusively accessed
by the daemon, it is not recommended to change these values,
or to change them to a value that is used by other systems,
such as cri-containerd.
type: "object"
properties:
Containers:
description: |
The default containerd namespace used for containers managed
by the daemon.
The default namespace for containers is "moby", but will be
suffixed with the `<uid>.<gid>` of the remapped `root` if
user-namespaces are enabled and the containerd image-store
is used.
type: "string"
default: "moby"
example: "moby"
Plugins:
description: |
The default containerd namespace used for plugins managed by
the daemon.
The default namespace for plugins is "plugins.moby", but will be
suffixed with the `<uid>.<gid>` of the remapped `root` if
user-namespaces are enabled and the containerd image-store
is used.
type: "string"
default: "plugins.moby"
example: "plugins.moby"
# PluginsInfo is a temp struct holding Plugins name
# registered with docker daemon. It is used by Info struct

View File

@@ -75,6 +75,8 @@ type Info struct {
DefaultAddressPools []NetworkAddressPool `json:",omitempty"`
CDISpecDirs []string
Containerd *ContainerdInfo `json:",omitempty"`
// Legacy API fields for older API versions.
legacyFields
@@ -85,6 +87,43 @@ type Info struct {
Warnings []string
}
// ContainerdInfo holds information about the containerd instance used by the daemon.
type ContainerdInfo struct {
// Address is the path to the containerd socket.
Address string `json:",omitempty"`
// Namespaces is the containerd namespaces used by the daemon.
Namespaces ContainerdNamespaces
}
// ContainerdNamespaces reflects the containerd namespaces used by the daemon.
//
// These namespaces can be configured in the daemon configuration, and are
// considered to be used exclusively by the daemon,
//
// As these namespaces are considered to be exclusively accessed
// by the daemon, it is not recommended to change these values,
// or to change them to a value that is used by other systems,
// such as cri-containerd.
type ContainerdNamespaces struct {
// Containers holds the default containerd namespace used for
// containers managed by the daemon.
//
// The default namespace for containers is "moby", but will be
// suffixed with the `<uid>.<gid>` of the remapped `root` if
// user-namespaces are enabled and the containerd image-store
// is used.
Containers string
// Plugins holds the default containerd namespace used for
// plugins managed by the daemon.
//
// The default namespace for plugins is "moby", but will be
// suffixed with the `<uid>.<gid>` of the remapped `root` if
// user-namespaces are enabled and the containerd image-store
// is used.
Plugins string
}
type legacyFields struct {
ExecutionDriver string `json:",omitempty"` // Deprecated: deprecated since API v1.25, but returned for older versions.
}

View File

@@ -273,6 +273,11 @@ func (i *ImageService) resolveDescriptor(ctx context.Context, refOrID string) (o
return img.Target, nil
}
// ResolveImage looks up an image by reference or identifier in the image store.
func (i *ImageService) ResolveImage(ctx context.Context, refOrID string) (containerdimages.Image, error) {
return i.resolveImage(ctx, refOrID)
}
func (i *ImageService) resolveImage(ctx context.Context, refOrID string) (containerdimages.Image, error) {
parsed, err := reference.ParseAnyReference(refOrID)
if err != nil {

View File

@@ -82,7 +82,9 @@ func (daemon *Daemon) SystemInfo(ctx context.Context) (*system.Info, error) {
daemon.fillContainerStates(v)
daemon.fillDebugInfo(ctx, v)
daemon.fillContainerdInfo(v, &cfg.Config)
daemon.fillAPIInfo(v, &cfg.Config)
// Retrieve platform specific info
if err := daemon.fillPlatformInfo(ctx, v, sysInfo, cfg); err != nil {
return nil, err
@@ -227,6 +229,22 @@ func (daemon *Daemon) fillDebugInfo(ctx context.Context, v *system.Info) {
v.NFd = fileutils.GetTotalUsedFds(ctx)
v.NGoroutines = runtime.NumGoroutine()
v.NEventsListener = daemon.EventsService.SubscribersCount()
}
// fillContainerdInfo provides information about the containerd configuration
// for debugging purposes.
func (daemon *Daemon) fillContainerdInfo(v *system.Info, cfg *config.Config) {
if cfg.ContainerdAddr == "" {
return
}
v.Containerd = &system.ContainerdInfo{
Address: cfg.ContainerdAddr,
Namespaces: system.ContainerdNamespaces{
Containers: cfg.ContainerdNamespace,
Plugins: cfg.ContainerdPluginNamespace,
},
}
}
func (daemon *Daemon) fillAPIInfo(v *system.Info, cfg *config.Config) {

View File

@@ -4,10 +4,13 @@ import (
"context"
"time"
"github.com/containerd/containerd"
"github.com/containerd/containerd/containers"
"github.com/containerd/log"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/events"
"github.com/docker/docker/container"
mobyc8dstore "github.com/docker/docker/daemon/containerd"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/libcontainerd"
"github.com/pkg/errors"
@@ -173,7 +176,22 @@ func (daemon *Daemon) containerStart(ctx context.Context, daemonCfg *configStore
return err
}
ctr, err := libcontainerd.ReplaceContainer(ctx, daemon.containerd, container.ID, spec, shim, createOptions)
ctr, err := libcontainerd.ReplaceContainer(ctx, daemon.containerd, container.ID, spec, shim, createOptions, func(ctx context.Context, client *containerd.Client, c *containers.Container) error {
// Only set the image if we are using containerd for image storage.
// This is for metadata purposes only.
// Other lower-level components may make use of this information.
is, ok := daemon.imageService.(*mobyc8dstore.ImageService)
if !ok {
return nil
}
img, err := is.ResolveImage(ctx, container.Config.Image)
if err != nil {
log.G(ctx).WithError(err).WithField("container", container.ID).Warn("Failed to resolve containerd image reference")
return nil
}
c.Image = img.Name
return nil
})
if err != nil {
return setExitCodeFromError(container.SetExitCode, err)
}

View File

@@ -17,6 +17,9 @@ keywords: "API, Docker, rcli, REST, documentation"
[Docker Engine API v1.46](https://docs.docker.com/engine/api/v1.46/) documentation
* `GET /info` now includes a `Containerd` field containing information about
the location of the containerd API socket and containerd namespaces used
by the daemon to run containers and plugins.
* `POST /containers/create` field `NetworkingConfig.EndpointsConfig.DriverOpts`,
and `POST /networks/{id}/connect` field `EndpointsConfig.DriverOpts`, now
support label `com.docker.network.endpoint.sysctls` for setting per-interface

View File

@@ -10,6 +10,7 @@ import (
"testing"
"time"
"github.com/containerd/containerd"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/api/types/versions"
@@ -668,3 +669,40 @@ func TestCreateWithCustomMACs(t *testing.T) {
assert.Equal(t, mac, "02:32:1c:23:00:04")
}
}
// Tests that when using containerd backed storage the containerd container has the image referenced stored.
func TestContainerdContainerImageInfo(t *testing.T) {
skip.If(t, versions.LessThan(testEnv.DaemonAPIVersion(), "1.46"), "requires API v1.46")
ctx := setupTest(t)
apiClient := testEnv.APIClient()
defer apiClient.Close()
info, err := apiClient.Info(ctx)
assert.NilError(t, err)
skip.If(t, info.Containerd == nil, "requires containerd")
// Currently a containerd container is only created when the container is started.
// So start the container and then inspect the containerd container to verify the image info.
id := ctr.Run(ctx, t, apiClient, func(cfg *ctr.TestContainerConfig) {
// busybox is the default (as of this writing) used by the test client, but lets be explicit here.
cfg.Config.Image = "busybox"
})
defer apiClient.ContainerRemove(ctx, id, container.RemoveOptions{Force: true})
client, err := containerd.New(info.Containerd.Address, containerd.WithDefaultNamespace(info.Containerd.Namespaces.Containers))
assert.NilError(t, err)
defer client.Close()
ctr, err := client.ContainerService().Get(ctx, id)
assert.NilError(t, err)
if testEnv.UsingSnapshotter() {
assert.Equal(t, ctr.Image, "docker.io/library/busybox:latest")
} else {
// This field is not set when not using contianerd backed storage.
assert.Equal(t, ctr.Image, "")
}
}