Ver código fonte

Merge 9d4bf2cba4a804702f8be4b06d01145b8a1f4c26 into 801fd16e3e48b7638e6fee83facbb62de9a03cef

Brian Goff 1 ano atrás
pai
commit
656f711f6a

+ 29 - 0
api/swagger.yaml

@@ -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

+ 16 - 0
api/types/system/info.go

@@ -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.
 }

+ 5 - 0
daemon/containerd/image.go

@@ -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 {

+ 11 - 0
daemon/info.go

@@ -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) {

+ 19 - 1
daemon/start.go

@@ -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)
 	}

+ 38 - 0
integration/container/create_test.go

@@ -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, "")
+	}
+}