diff --git a/daemon/containerd/image_exporter.go b/daemon/containerd/image_exporter.go index 6423e3fb03..4b34d0bc7b 100644 --- a/daemon/containerd/image_exporter.go +++ b/daemon/containerd/image_exporter.go @@ -53,7 +53,7 @@ func (i *ImageService) LoadImage(ctx context.Context, inTar io.ReadCloser, outSt for _, img := range imgs { platformImg := containerd.NewImageWithPlatform(i.client, img, platform) - unpacked, err := platformImg.IsUnpacked(ctx, containerd.DefaultSnapshotter) + unpacked, err := platformImg.IsUnpacked(ctx, i.snapshotter) if err != nil { // TODO(thaJeztah): remove this log or change to debug once we can; see https://github.com/moby/moby/pull/43822#discussion_r937502405 logrus.WithError(err).WithField("image", img.Name).Debug("failed to check if image is unpacked") @@ -61,7 +61,7 @@ func (i *ImageService) LoadImage(ctx context.Context, inTar io.ReadCloser, outSt } if !unpacked { - err := platformImg.Unpack(ctx, containerd.DefaultSnapshotter) + err := platformImg.Unpack(ctx, i.snapshotter) if err != nil { // TODO(thaJeztah): remove this log or change to debug once we can; see https://github.com/moby/moby/pull/43822#discussion_r937502405 logrus.WithError(err).WithField("image", img.Name).Warn("failed to unpack image") diff --git a/daemon/containerd/image_list.go b/daemon/containerd/image_list.go index 0c5ff0f49e..e6bb6d17f8 100644 --- a/daemon/containerd/image_list.go +++ b/daemon/containerd/image_list.go @@ -41,7 +41,7 @@ func (i *ImageService) Images(ctx context.Context, opts types.ImageListOptions) return nil, err } - snapshotter := i.client.SnapshotService(containerd.DefaultSnapshotter) + snapshotter := i.client.SnapshotService(i.snapshotter) sizeCache := make(map[digest.Digest]int64) snapshotSizeFn := func(d digest.Digest) (int64, error) { if s, ok := sizeCache[d]; ok { diff --git a/daemon/containerd/service.go b/daemon/containerd/service.go index 1cb55bae1f..aa2f58c38f 100644 --- a/daemon/containerd/service.go +++ b/daemon/containerd/service.go @@ -13,13 +13,15 @@ import ( // ImageService implements daemon.ImageService type ImageService struct { - client *containerd.Client + client *containerd.Client + snapshotter string } // NewService creates a new ImageService. -func NewService(c *containerd.Client) *ImageService { +func NewService(c *containerd.Client, snapshotter string) *ImageService { return &ImageService{ - client: c, + client: c, + snapshotter: snapshotter, } } @@ -81,7 +83,7 @@ func (i *ImageService) Cleanup() error { // StorageDriver returns the name of the default storage-driver (snapshotter) // used by the ImageService. func (i *ImageService) StorageDriver() string { - return "" + return i.snapshotter } // ReleaseLayer releases a layer allowing it to be removed diff --git a/daemon/daemon.go b/daemon/daemon.go index ea3320c798..dfacd217e5 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -833,22 +833,6 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S } } - var graphDriver string - if isWindows { - // On Windows we don't support the environment variable, or a user supplied graphdriver - graphDriver = "windowsfilter" - } else { - // Unix platforms however run a single graphdriver for all containers, and it can - // be set through an environment variable, a daemon start parameter, or chosen through - // initialization of the layerstore through driver priority order for example. - if drv := os.Getenv("DOCKER_DRIVER"); drv != "" { - graphDriver = drv - logrus.Infof("Setting the storage driver from the $DOCKER_DRIVER environment variable (%s)", drv) - } else { - graphDriver = config.GraphDriver // May still be empty. Layerstore init determines instead. - } - } - d.registryService = registryService logger.RegisterPluginGetter(d.PluginStore) @@ -938,27 +922,6 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S return nil, err } - layerStore, err := layer.NewStoreFromOptions(layer.StoreOptions{ - Root: config.Root, - MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"), - GraphDriver: graphDriver, - GraphDriverOptions: config.GraphOptions, - IDMapping: idMapping, - PluginGetter: d.PluginStore, - ExperimentalEnabled: config.Experimental, - }) - if err != nil { - return nil, err - } - - // Configure and validate the kernels security support. Note this is a Linux/FreeBSD - // operation only, so it is safe to pass *just* the runtime OS graphdriver. - if err := configureKernelSecuritySupport(config, layerStore.DriverName()); err != nil { - return nil, err - } - - imageRoot := filepath.Join(config.Root, "image", layerStore.DriverName()) - d.volumes, err = volumesservice.NewVolumeService(config.Root, d.PluginStore, rootIDs, d) if err != nil { return nil, err @@ -972,23 +935,6 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S logrus.WithError(err).Warnf("unable to migrate engine ID; a new engine ID will be generated") } - // We have a single tag/reference store for the daemon globally. However, it's - // stored under the graphdriver. On host platforms which only support a single - // container OS, but multiple selectable graphdrivers, this means depending on which - // graphdriver is chosen, the global reference store is under there. For - // platforms which support multiple container operating systems, this is slightly - // more problematic as where does the global ref store get located? Fortunately, - // for Windows, which is currently the only daemon supporting multiple container - // operating systems, the list of graphdrivers available isn't user configurable. - // For backwards compatibility, we just put it under the windowsfilter - // directory regardless. - refStoreLocation := filepath.Join(imageRoot, `repositories.json`) - rs, err := refstore.NewReferenceStore(refStoreLocation) - if err != nil { - return nil, fmt.Errorf("Couldn't create reference store repository: %s", err) - } - d.ReferenceStore = rs - // Check if Devices cgroup is mounted, it is hard requirement for container security, // on Linux. // @@ -1019,14 +965,69 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S d.linkIndex = newLinkIndex() - if d.UsesSnapshotter() { - d.imageService = ctrd.NewService(d.containerdCli) + // On Windows we don't support the environment variable, or a user supplied graphdriver + // Unix platforms however run a single graphdriver for all containers, and it can + // be set through an environment variable, a daemon start parameter, or chosen through + // initialization of the layerstore through driver priority order for example. + driverName := os.Getenv("DOCKER_DRIVER") + if isWindows { + driverName = "windowsfilter" + } else if driverName != "" { + logrus.Infof("Setting the storage driver from the $DOCKER_DRIVER environment variable (%s)", driverName) } else { + driverName = config.GraphDriver + } + + if d.UsesSnapshotter() { + // Configure and validate the kernels security support. Note this is a Linux/FreeBSD + // operation only, so it is safe to pass *just* the runtime OS graphdriver. + if err := configureKernelSecuritySupport(config, driverName); err != nil { + return nil, err + } + d.imageService = ctrd.NewService(d.containerdCli, driverName) + } else { + layerStore, err := layer.NewStoreFromOptions(layer.StoreOptions{ + Root: config.Root, + MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"), + GraphDriver: driverName, + GraphDriverOptions: config.GraphOptions, + IDMapping: idMapping, + PluginGetter: d.PluginStore, + ExperimentalEnabled: config.Experimental, + }) + if err != nil { + return nil, err + } + + // Configure and validate the kernels security support. Note this is a Linux/FreeBSD + // operation only, so it is safe to pass *just* the runtime OS graphdriver. + if err := configureKernelSecuritySupport(config, layerStore.DriverName()); err != nil { + return nil, err + } + + imageRoot := filepath.Join(config.Root, "image", layerStore.DriverName()) ifs, err := image.NewFSStoreBackend(filepath.Join(imageRoot, "imagedb")) if err != nil { return nil, err } + // We have a single tag/reference store for the daemon globally. However, it's + // stored under the graphdriver. On host platforms which only support a single + // container OS, but multiple selectable graphdrivers, this means depending on which + // graphdriver is chosen, the global reference store is under there. For + // platforms which support multiple container operating systems, this is slightly + // more problematic as where does the global ref store get located? Fortunately, + // for Windows, which is currently the only daemon supporting multiple container + // operating systems, the list of graphdrivers available isn't user configurable. + // For backwards compatibility, we just put it under the windowsfilter + // directory regardless. + refStoreLocation := filepath.Join(imageRoot, `repositories.json`) + rs, err := refstore.NewReferenceStore(refStoreLocation) + if err != nil { + return nil, fmt.Errorf("Couldn't create reference store repository: %s", err) + } + d.ReferenceStore = rs + imageStore, err := image.NewImageStore(ifs, layerStore) if err != nil { return nil, err diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go index 6686b15f87..d0b71d1c65 100644 --- a/daemon/daemon_unix.go +++ b/daemon/daemon_unix.go @@ -822,7 +822,7 @@ func configureKernelSecuritySupport(config *config.Config, driverName string) er return nil } - if driverName == "overlay" || driverName == "overlay2" { + if driverName == "overlay" || driverName == "overlay2" || driverName == "overlayfs" { // If driver is overlay or overlay2, make sure kernel // supports selinux with overlay. supported, err := overlaySupportsSelinux() diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go index 66ccdc5c6a..f8fba2bda8 100644 --- a/daemon/oci_linux.go +++ b/daemon/oci_linux.go @@ -1045,8 +1045,17 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e if daemon.configStore.Rootless { opts = append(opts, WithRootless(daemon)) } + + var snapshotter, snapshotKey string + if daemon.UsesSnapshotter() { + snapshotter = daemon.imageService.StorageDriver() + snapshotKey = c.ID + } + return &s, coci.ApplyOpts(context.Background(), nil, &containers.Container{ - ID: c.ID, + ID: c.ID, + Snapshotter: snapshotter, + SnapshotKey: snapshotKey, }, &s, opts...) }