package daemon import ( "context" "fmt" "os" "runtime" "github.com/containerd/log" "github.com/moby/moby/v2/daemon/config" "github.com/moby/moby/v2/daemon/graphdriver" ) type imageStoreChoice string const ( // containerd by default imageStoreChoiceContainerd imageStoreChoice = "containerd-by-default" // containerd explicitly chosen by user imageStoreChoiceContainerdExplicit imageStoreChoice = "containerd-explicit" // graphdriver by default imageStoreChoiceGraphdriver imageStoreChoice = "graphdriver-by-default" // graphdrivers explicitly chosen by user imageStoreChoiceGraphdriverExplicit imageStoreChoice = "graphdriver-explicit" // would be containerd, but the system has already been running with a graphdriver imageStoreChoiceGraphdriverPrior imageStoreChoice = "graphdriver-prior" ) func (c imageStoreChoice) IsGraphDriver() bool { switch c { case imageStoreChoiceContainerd, imageStoreChoiceContainerdExplicit: return false default: return true } } func (c imageStoreChoice) IsExplicit() bool { switch c { case imageStoreChoiceGraphdriverExplicit, imageStoreChoiceContainerdExplicit: return true default: return false } } // getDriverOverride determines the storage driver name based on environment variables, // configuration, and platform-specific logic. // On Windows we don't support the environment variable, or a user supplied graphdriver, // but it is allowed when using snapshotters. // 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. func getDriverOverride(ctx context.Context, cfgGraphDriver string, imgStoreChoice imageStoreChoice) string { driverName := os.Getenv("DOCKER_DRIVER") if driverName == "" { driverName = cfgGraphDriver } else { log.G(ctx).Infof("Setting the storage driver from the $DOCKER_DRIVER environment variable (%s)", driverName) } if runtime.GOOS == "windows" { if driverName == "" { driverName = cfgGraphDriver } switch driverName { case "windows": // Docker WCOW snapshotters case "windowsfilter": // Docker WCOW graphdriver case "": if imgStoreChoice.IsGraphDriver() { driverName = "windowsfilter" } else { driverName = "windows" } default: log.G(ctx).Infof("Using non-default snapshotter %s", driverName) } } return driverName } type determineImageStoreChoiceOptions struct { hasPriorDriver func(root string) bool isRegisteredGraphdriver func(driverName string) bool runtimeOS string } func determineImageStoreChoice(cfgStore *config.Config, opts determineImageStoreChoiceOptions) (imageStoreChoice, error) { if opts.hasPriorDriver == nil { opts.hasPriorDriver = graphdriver.HasPriorDriver } if opts.isRegisteredGraphdriver == nil { opts.isRegisteredGraphdriver = graphdriver.IsRegistered } if opts.runtimeOS == "" { opts.runtimeOS = runtime.GOOS } out := imageStoreChoiceContainerd if opts.runtimeOS == "windows" { out = imageStoreChoiceGraphdriver } driverName := os.Getenv("DOCKER_DRIVER") if driverName == "" { driverName = cfgStore.GraphDriver } if enabled, ok := cfgStore.Features["containerd-snapshotter"]; ok { if enabled { if out == imageStoreChoiceContainerd { log.G(context.TODO()).Warn(`"containerd-snapshotter" is now the default and no longer needed to be set`) } out = imageStoreChoiceContainerdExplicit } else { out = imageStoreChoiceGraphdriverExplicit } } if os.Getenv("TEST_INTEGRATION_USE_GRAPHDRIVER") != "" { out = imageStoreChoiceGraphdriverExplicit } if out == imageStoreChoiceContainerd { if opts.hasPriorDriver(cfgStore.Root) { return imageStoreChoiceGraphdriverPrior, nil } } if driverName != "" { if !out.IsExplicit() && opts.isRegisteredGraphdriver(driverName) { return imageStoreChoiceGraphdriverExplicit, nil } if out.IsGraphDriver() { if opts.isRegisteredGraphdriver(driverName) { return imageStoreChoiceGraphdriverExplicit, nil } else if out.IsExplicit() { return imageStoreChoiceGraphdriverExplicit, fmt.Errorf("graphdriver is explicitly enabled but %q is not registered, %v %v", driverName, cfgStore.Features, os.Getenv("TEST_INTEGRATION_USE_GRAPHDRIVER")) } } // Assume snapshotter is chosen return imageStoreChoiceContainerdExplicit, nil } return out, nil }