Browse code

daemon: Do not default to c8d image store on Windows

Before this commit migration to c8d would apply when
`TEST_INTEGRATION_USE_GRAPHDRIVER` is empty/unset (which is the default
scenario).

This caused fresh Windows installations to default to containerd image
store and panic:

```
PS C:\Users\Administrator\Desktop> .\dockerd.exe --debug
time="2025-09-01T12:45:42.182741200Z" level=info msg="Starting up"
time="2025-09-01T12:45:42.225128900Z" level=debug msg="Listener created for HTTP on npipe (//./pipe/docker_engine)"
time="2025-09-01T12:45:42.231740900Z" level=info msg="OTEL tracing is not configured, using no-op tracer provider"
time="2025-09-01T12:45:42.263475300Z" level=info msg="Windows default isolation mode: process"
time="2025-09-01T12:45:42.263475300Z" level=debug msg="Stackdump - waiting signal at Global\\stackdump-7780"
time="2025-09-01T12:45:42.273230800Z" level=debug msg="Using default logging driver json-file"
time="2025-09-01T12:45:42.273230800Z" level=debug msg="No quota support for local volumes in C:\\ProgramData\\docker\\volumes: Filesystem does not support, or has not enabled quotas"
time="2025-09-01T12:45:42.301881100Z" level=info msg="Loading containers: start."
time="2025-09-01T12:45:42.302302800Z" level=info msg="[graphdriver] trying configured driver: windowsfilter"
time="2025-09-01T12:45:42.302302800Z" level=debug msg="WindowsGraphDriver InitFilter at C:\\ProgramData\\docker\\windowsfilter"
time="2025-09-01T12:45:42.303028000Z" level=debug msg="Initialized graph driver windowsfilter"
time="2025-09-01T12:45:42.323007600Z" level=info msg="Enabling containerd snapshotter because migration set with no containers and 0 images in graph driver" total=0
time="2025-09-01T12:45:42.323007600Z" level=info msg="Starting daemon with containerd snapshotter integration enabled"
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x88 pc=0x16522c4]

goroutine 1 [running]:
github.com/containerd/containerd/v2/client.(*Client).IntrospectionService(0x3153e60?)
/go/src/github.com/docker/docker/vendor/github.com/containerd/containerd/v2/client/client.go:731 +0x24
github.com/moby/moby/v2/daemon.NewDaemon({0x3153e60, 0xc0001360f0}, 0xc0000fa008, 0xc00025c5a0, 0xc0002deee0)
/go/src/github.com/docker/docker/daemon/daemon.go:1276 +0x35ad
github.com/moby/moby/v2/daemon/command.(*daemonCLI).start(0xc0000da320, {0x3153df0, 0x4704c60})
/go/src/github.com/docker/docker/daemon/command/daemon.go:262 +0xa09
github.com/moby/moby/v2/daemon/command.runDaemon({0x3153df0, 0x4704c60}, 0xc0000da320)
/go/src/github.com/docker/docker/daemon/command/docker_windows.go:28 +0x8a
github.com/moby/moby/v2/daemon/command.newDaemonCommand.func1(0xc000147508, {0xc000500f60?, 0x7?, 0x2cf8c90?})
/go/src/github.com/docker/docker/daemon/command/docker.go:45 +0xd1
github.com/spf13/cobra.(*Command).execute(0xc000147508, {0xc00006a0f0, 0x1, 0x1})
/go/src/github.com/docker/docker/vendor/github.com/spf13/cobra/command.go:1015 +0xaaa
github.com/spf13/cobra.(*Command).ExecuteC(0xc000147508)
/go/src/github.com/docker/docker/vendor/github.com/spf13/cobra/command.go:1148 +0x46f
github.com/spf13/cobra.(*Command).Execute(...)
/go/src/github.com/docker/docker/vendor/github.com/spf13/cobra/command.go:1071
github.com/spf13/cobra.(*Command).ExecuteContext(...)
/go/src/github.com/docker/docker/vendor/github.com/spf13/cobra/command.go:1064
github.com/moby/moby/v2/daemon/command.daemonRunner.Run({0x3127160?}, {0x3153df0, 0x4704c60})
/go/src/github.com/docker/docker/daemon/command/docker.go:111 +0x6e
main.main()
/go/src/github.com/docker/docker/cmd/dockerd/main.go:38 +0x122
```

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>

Paweł Gronowski authored on 2025/09/01 22:08:27
Showing 2 changed files
... ...
@@ -785,6 +785,10 @@ func (daemon *Daemon) IsSwarmCompatible() error {
785 785
 	return daemon.config().IsSwarmCompatible()
786 786
 }
787 787
 
788
+func useContainerdByDefault() bool {
789
+	return os.Getenv("TEST_INTEGRATION_USE_GRAPHDRIVER") == "" && runtime.GOOS != "windows"
790
+}
791
+
788 792
 // NewDaemon sets up everything for the daemon to be able to service
789 793
 // requests from the webserver.
790 794
 func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.Store, authzMiddleware *authorization.Middleware) (_ *Daemon, retErr error) {
... ...
@@ -894,7 +898,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
894 894
 			log.G(ctx).WithField("env", os.Environ()).Info("Migration to containerd is enabled, driver will be switched to snapshotter if there are no images or containers")
895 895
 		}
896 896
 	}
897
-	if config.Features["containerd-snapshotter"] {
897
+	if config.Features["containerd-snapshotter"] && useContainerdByDefault() {
898 898
 		log.G(ctx).Warn(`"containerd-snapshotter" is now the default and no longer needed to be set`)
899 899
 	}
900 900
 
... ...
@@ -1113,11 +1117,10 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
1113 1113
 		case "windowsfilter":
1114 1114
 			// Docker WCOW graphdriver
1115 1115
 		case "":
1116
-			// Use graph driver but enable migration
1116
+			// Use graph driver unless opted-in to containerd store
1117 1117
 			driverName = "windowsfilter"
1118
-			if os.Getenv("TEST_INTEGRATION_USE_GRAPHDRIVER") == "" {
1119
-				// Don't force migration if graph driver is explicit
1120
-				migrationThreshold = 0
1118
+			if useContainerdByDefault() || config.Features["containerd-snapshotter"] {
1119
+				driverName = "windows"
1121 1120
 			}
1122 1121
 		default:
1123 1122
 			log.G(ctx).Infof("Using non-default snapshotter %s", driverName)
... ...
@@ -5,6 +5,7 @@ import (
5 5
 	"fmt"
6 6
 	"os"
7 7
 	"path/filepath"
8
+	"runtime"
8 9
 	"strings"
9 10
 	"testing"
10 11
 
... ...
@@ -190,7 +191,7 @@ func (e *Execution) IsUserNamespaceInKernel() bool {
190 190
 // UsingSnapshotter returns whether containerd snapshotters are used for the
191 191
 // tests by checking if the "TEST_INTEGRATION_USE_GRAPHDRIVER" is empty
192 192
 func (e *Execution) UsingSnapshotter() bool {
193
-	return os.Getenv("TEST_INTEGRATION_USE_GRAPHDRIVER") == ""
193
+	return os.Getenv("TEST_INTEGRATION_USE_GRAPHDRIVER") == "" && runtime.GOOS != "windows"
194 194
 }
195 195
 
196 196
 // HasExistingImage checks whether there is an image with the given reference.