This commit is contained in:
Brian Goff 2024-04-19 22:19:32 -07:00 committed by GitHub
commit 656f711f6a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 118 additions and 1 deletions

View file

@ -5436,6 +5436,35 @@ 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.
Tampering with the containerd instance may cause unexpected behavior.
type: "object"
properties:
Address:
description: "The address of the containerd socket."
type: "string"
Namespaces:
description: "The namespaces that are used by containerd."
type: "object"
properties:
Containers:
description: "The namespace that is used for containers."
type: "string"
Plugins:
description: "The namespace that is used for plugins."
type: "string"
example:
Address: "/run/containerd/containerd.sock"
Namespaces:
Containers: "moby"
Plugins: "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,20 @@ 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.
type ContainerdNamespaces struct {
Containers string
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

@ -227,6 +227,17 @@ func (daemon *Daemon) fillDebugInfo(ctx context.Context, v *system.Info) {
v.NFd = fileutils.GetTotalUsedFds(ctx)
v.NGoroutines = runtime.NumGoroutine()
v.NEventsListener = daemon.EventsService.SubscribersCount()
config := daemon.Config()
if config.ContainerdAddr != "" {
v.Containerd = &system.ContainerdInfo{
Address: config.ContainerdAddr,
Namespaces: system.ContainerdNamespaces{
Containers: config.ContainerdNamespace,
Plugins: config.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/internal/compatcontext"
"github.com/docker/docker/libcontainerd"
@ -166,7 +169,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

@ -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.45"), "requires API v1.45")
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, "")
}
}