mirror of
https://github.com/moby/moby.git
synced 2026-01-11 18:51:37 +00:00
Merge pull request #47239 from cpuguy83/containerd_image_info
Set containerd container image ref
This commit is contained in:
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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, "")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user