Browse code

imageservice: Add context to various methods

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

Nicolas De Loof authored on 2022/10/27 01:13:17
Showing 40 changed files
... ...
@@ -32,14 +32,14 @@ type copyBackend interface {
32 32
 
33 33
 // stateBackend includes functions to implement to provide container state lifecycle functionality.
34 34
 type stateBackend interface {
35
-	ContainerCreate(config types.ContainerCreateConfig) (container.CreateResponse, error)
35
+	ContainerCreate(ctx context.Context, config types.ContainerCreateConfig) (container.CreateResponse, error)
36 36
 	ContainerKill(name string, signal string) error
37 37
 	ContainerPause(name string) error
38 38
 	ContainerRename(oldName, newName string) error
39 39
 	ContainerResize(name string, height, width int) error
40 40
 	ContainerRestart(ctx context.Context, name string, options container.StopOptions) error
41 41
 	ContainerRm(name string, config *types.ContainerRmConfig) error
42
-	ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
42
+	ContainerStart(ctx context.Context, name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
43 43
 	ContainerStop(ctx context.Context, name string, options container.StopOptions) error
44 44
 	ContainerUnpause(name string) error
45 45
 	ContainerUpdate(name string, hostConfig *container.HostConfig) (container.ContainerUpdateOKBody, error)
... ...
@@ -54,7 +54,7 @@ type monitorBackend interface {
54 54
 	ContainerStats(ctx context.Context, name string, config *backend.ContainerStatsConfig) error
55 55
 	ContainerTop(name string, psArgs string) (*container.ContainerTopOKBody, error)
56 56
 
57
-	Containers(config *types.ContainerListOptions) ([]*types.Container, error)
57
+	Containers(ctx context.Context, config *types.ContainerListOptions) ([]*types.Container, error)
58 58
 }
59 59
 
60 60
 // attachBackend includes function to implement to provide container attaching functionality.
... ...
@@ -68,7 +68,7 @@ type systemBackend interface {
68 68
 }
69 69
 
70 70
 type commitBackend interface {
71
-	CreateImageFromContainer(name string, config *backend.CreateImageConfig) (imageID string, err error)
71
+	CreateImageFromContainer(ctx context.Context, name string, config *backend.CreateImageConfig) (imageID string, err error)
72 72
 }
73 73
 
74 74
 // Backend is all the methods that need to be implemented to provide container specific functionality.
... ...
@@ -58,7 +58,7 @@ func (s *containerRouter) postCommit(ctx context.Context, w http.ResponseWriter,
58 58
 		Changes: r.Form["changes"],
59 59
 	}
60 60
 
61
-	imgID, err := s.backend.CreateImageFromContainer(r.Form.Get("container"), commitCfg)
61
+	imgID, err := s.backend.CreateImageFromContainer(ctx, r.Form.Get("container"), commitCfg)
62 62
 	if err != nil {
63 63
 		return err
64 64
 	}
... ...
@@ -91,7 +91,7 @@ func (s *containerRouter) getContainersJSON(ctx context.Context, w http.Response
91 91
 		config.Limit = limit
92 92
 	}
93 93
 
94
-	containers, err := s.backend.Containers(config)
94
+	containers, err := s.backend.Containers(ctx, config)
95 95
 	if err != nil {
96 96
 		return err
97 97
 	}
... ...
@@ -214,7 +214,7 @@ func (s *containerRouter) postContainersStart(ctx context.Context, w http.Respon
214 214
 
215 215
 	checkpoint := r.Form.Get("checkpoint")
216 216
 	checkpointDir := r.Form.Get("checkpoint-dir")
217
-	if err := s.backend.ContainerStart(vars["name"], hostConfig, checkpoint, checkpointDir); err != nil {
217
+	if err := s.backend.ContainerStart(ctx, vars["name"], hostConfig, checkpoint, checkpointDir); err != nil {
218 218
 		return err
219 219
 	}
220 220
 
... ...
@@ -578,7 +578,7 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo
578 578
 		hostConfig.PidsLimit = nil
579 579
 	}
580 580
 
581
-	ccr, err := s.backend.ContainerCreate(types.ContainerCreateConfig{
581
+	ccr, err := s.backend.ContainerCreate(ctx, types.ContainerCreateConfig{
582 582
 		Name:             name,
583 583
 		Config:           config,
584 584
 		HostConfig:       hostConfig,
... ...
@@ -31,7 +31,7 @@ type imageBackend interface {
31 31
 
32 32
 type importExportBackend interface {
33 33
 	LoadImage(ctx context.Context, inTar io.ReadCloser, outStream io.Writer, quiet bool) error
34
-	ImportImage(src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
34
+	ImportImage(ctx context.Context, src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
35 35
 	ExportImage(ctx context.Context, names []string, outStream io.Writer) error
36 36
 }
37 37
 
... ...
@@ -68,7 +68,7 @@ func (ir *imageRouter) postImagesCreate(ctx context.Context, w http.ResponseWrit
68 68
 		progressErr = ir.backend.PullImage(ctx, img, tag, platform, metaHeaders, authConfig, output)
69 69
 	} else { // import
70 70
 		src := r.Form.Get("fromSrc")
71
-		progressErr = ir.backend.ImportImage(src, repo, platform, tag, message, r.Body, output, r.Form["changes"])
71
+		progressErr = ir.backend.ImportImage(ctx, src, repo, platform, tag, message, r.Body, output, r.Form["changes"])
72 72
 	}
73 73
 	if progressErr != nil {
74 74
 		if !output.Flushed() {
... ...
@@ -12,7 +12,7 @@ import (
12 12
 type Backend interface {
13 13
 	Init(req types.InitRequest) (string, error)
14 14
 	Join(req types.JoinRequest) error
15
-	Leave(force bool) error
15
+	Leave(ctx context.Context, force bool) error
16 16
 	Inspect() (types.Swarm, error)
17 17
 	Update(uint64, types.Spec, types.UpdateFlags) error
18 18
 	GetUnlockKey() (string, error)
... ...
@@ -56,7 +56,7 @@ func (sr *swarmRouter) leaveCluster(ctx context.Context, w http.ResponseWriter,
56 56
 	}
57 57
 
58 58
 	force := httputils.BoolValue(r, "force")
59
-	return sr.backend.Leave(force)
59
+	return sr.backend.Leave(ctx, force)
60 60
 }
61 61
 
62 62
 func (sr *swarmRouter) inspectCluster(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
... ...
@@ -60,13 +60,13 @@ type ExecBackend interface {
60 60
 	// ContainerAttachRaw attaches to container.
61 61
 	ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout, stderr io.Writer, stream bool, attached chan struct{}) error
62 62
 	// ContainerCreateIgnoreImagesArgsEscaped creates a new Docker container and returns potential warnings
63
-	ContainerCreateIgnoreImagesArgsEscaped(config types.ContainerCreateConfig) (container.CreateResponse, error)
63
+	ContainerCreateIgnoreImagesArgsEscaped(ctx context.Context, config types.ContainerCreateConfig) (container.CreateResponse, error)
64 64
 	// ContainerRm removes a container specified by `id`.
65 65
 	ContainerRm(name string, config *types.ContainerRmConfig) error
66 66
 	// ContainerKill stops the container execution abruptly.
67 67
 	ContainerKill(containerID string, sig string) error
68 68
 	// ContainerStart starts a new container
69
-	ContainerStart(containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
69
+	ContainerStart(ctx context.Context, containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
70 70
 	// ContainerWait stops processing until the given container is stopped.
71 71
 	ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
72 72
 }
... ...
@@ -80,7 +80,7 @@ type Result struct {
80 80
 // ImageCacheBuilder represents a generator for stateful image cache.
81 81
 type ImageCacheBuilder interface {
82 82
 	// MakeImageCache creates a stateful image cache.
83
-	MakeImageCache(cacheFrom []string) ImageCache
83
+	MakeImageCache(ctx context.Context, cacheFrom []string) (ImageCache, error)
84 84
 }
85 85
 
86 86
 // ImageCache abstracts an image cache.
... ...
@@ -95,7 +95,7 @@ func (bm *BuildManager) Build(ctx context.Context, config backend.BuildConfig) (
95 95
 	if err != nil {
96 96
 		return nil, err
97 97
 	}
98
-	return b.build(source, dockerfile)
98
+	return b.build(ctx, source, dockerfile)
99 99
 }
100 100
 
101 101
 // builderOptions are the dependencies required by the builder
... ...
@@ -136,6 +136,11 @@ func newBuilder(clientCtx context.Context, options builderOptions) (*Builder, er
136 136
 		config = new(types.ImageBuildOptions)
137 137
 	}
138 138
 
139
+	imageProber, err := newImageProber(clientCtx, options.Backend, config.CacheFrom, config.NoCache)
140
+	if err != nil {
141
+		return nil, err
142
+	}
143
+
139 144
 	b := &Builder{
140 145
 		clientCtx:        clientCtx,
141 146
 		options:          config,
... ...
@@ -147,7 +152,7 @@ func newBuilder(clientCtx context.Context, options builderOptions) (*Builder, er
147 147
 		idMapping:        options.IDMapping,
148 148
 		imageSources:     newImageSources(clientCtx, options),
149 149
 		pathCache:        options.PathCache,
150
-		imageProber:      newImageProber(options.Backend, config.CacheFrom, config.NoCache),
150
+		imageProber:      imageProber,
151 151
 		containerManager: newContainerManager(options.Backend),
152 152
 	}
153 153
 
... ...
@@ -181,7 +186,7 @@ func buildLabelOptions(labels map[string]string, stages []instructions.Stage) {
181 181
 
182 182
 // Build runs the Dockerfile builder by parsing the Dockerfile and executing
183 183
 // the instructions from the file.
184
-func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*builder.Result, error) {
184
+func (b *Builder) build(ctx context.Context, source builder.Source, dockerfile *parser.Result) (*builder.Result, error) {
185 185
 	defer b.imageSources.Unmount()
186 186
 
187 187
 	stages, metaArgs, err := instructions.Parse(dockerfile.AST)
... ...
@@ -205,7 +210,7 @@ func (b *Builder) build(source builder.Source, dockerfile *parser.Result) (*buil
205 205
 	buildLabelOptions(b.options.Labels, stages)
206 206
 
207 207
 	dockerfile.PrintWarnings(b.Stderr)
208
-	dispatchState, err := b.dispatchDockerfileWithCancellation(stages, metaArgs, dockerfile.EscapeToken, source)
208
+	dispatchState, err := b.dispatchDockerfileWithCancellation(ctx, stages, metaArgs, dockerfile.EscapeToken, source)
209 209
 	if err != nil {
210 210
 		return nil, err
211 211
 	}
... ...
@@ -244,7 +249,7 @@ func printCommand(out io.Writer, currentCommandIndex int, totalCommands int, cmd
244 244
 	return currentCommandIndex + 1
245 245
 }
246 246
 
247
-func (b *Builder) dispatchDockerfileWithCancellation(parseResult []instructions.Stage, metaArgs []instructions.ArgCommand, escapeToken rune, source builder.Source) (*dispatchState, error) {
247
+func (b *Builder) dispatchDockerfileWithCancellation(ctx context.Context, parseResult []instructions.Stage, metaArgs []instructions.ArgCommand, escapeToken rune, source builder.Source) (*dispatchState, error) {
248 248
 	dispatchRequest := dispatchRequest{}
249 249
 	buildArgs := NewBuildArgs(b.options.BuildArgs)
250 250
 	totalCommands := len(metaArgs) + len(parseResult)
... ...
@@ -272,7 +277,7 @@ func (b *Builder) dispatchDockerfileWithCancellation(parseResult []instructions.
272 272
 		dispatchRequest = newDispatchRequest(b, escapeToken, source, buildArgs, stagesResults)
273 273
 
274 274
 		currentCommandIndex = printCommand(b.Stdout, currentCommandIndex, totalCommands, stage.SourceCode)
275
-		if err := initializeStage(dispatchRequest, &stage); err != nil {
275
+		if err := initializeStage(ctx, dispatchRequest, &stage); err != nil {
276 276
 			return nil, err
277 277
 		}
278 278
 		dispatchRequest.state.updateRunConfig()
... ...
@@ -290,7 +295,7 @@ func (b *Builder) dispatchDockerfileWithCancellation(parseResult []instructions.
290 290
 
291 291
 			currentCommandIndex = printCommand(b.Stdout, currentCommandIndex, totalCommands, cmd)
292 292
 
293
-			if err := dispatch(dispatchRequest, cmd); err != nil {
293
+			if err := dispatch(ctx, dispatchRequest, cmd); err != nil {
294 294
 				return nil, err
295 295
 			}
296 296
 			dispatchRequest.state.updateRunConfig()
... ...
@@ -317,7 +322,7 @@ func (b *Builder) dispatchDockerfileWithCancellation(parseResult []instructions.
317 317
 // coming from the query parameter of the same name.
318 318
 //
319 319
 // TODO: Remove?
320
-func BuildFromConfig(config *container.Config, changes []string, os string) (*container.Config, error) {
320
+func BuildFromConfig(ctx context.Context, config *container.Config, changes []string, os string) (*container.Config, error) {
321 321
 	if len(changes) == 0 {
322 322
 		return config, nil
323 323
 	}
... ...
@@ -327,7 +332,7 @@ func BuildFromConfig(config *container.Config, changes []string, os string) (*co
327 327
 		return nil, errdefs.InvalidParameter(err)
328 328
 	}
329 329
 
330
-	b, err := newBuilder(context.Background(), builderOptions{
330
+	b, err := newBuilder(ctx, builderOptions{
331 331
 		Options: &types.ImageBuildOptions{NoCache: true},
332 332
 	})
333 333
 	if err != nil {
... ...
@@ -360,7 +365,7 @@ func BuildFromConfig(config *container.Config, changes []string, os string) (*co
360 360
 	dispatchRequest.state.imageID = config.Image
361 361
 	dispatchRequest.state.operatingSystem = os
362 362
 	for _, cmd := range commands {
363
-		err := dispatch(dispatchRequest, cmd)
363
+		err := dispatch(ctx, dispatchRequest, cmd)
364 364
 		if err != nil {
365 365
 			return nil, errdefs.InvalidParameter(err)
366 366
 		}
... ...
@@ -28,8 +28,8 @@ func newContainerManager(docker builder.ExecBackend) *containerManager {
28 28
 }
29 29
 
30 30
 // Create a container
31
-func (c *containerManager) Create(runConfig *container.Config, hostConfig *container.HostConfig) (container.CreateResponse, error) {
32
-	container, err := c.backend.ContainerCreateIgnoreImagesArgsEscaped(types.ContainerCreateConfig{
31
+func (c *containerManager) Create(ctx context.Context, runConfig *container.Config, hostConfig *container.HostConfig) (container.CreateResponse, error) {
32
+	container, err := c.backend.ContainerCreateIgnoreImagesArgsEscaped(ctx, types.ContainerCreateConfig{
33 33
 		Config:     runConfig,
34 34
 		HostConfig: hostConfig,
35 35
 	})
... ...
@@ -69,7 +69,7 @@ func (c *containerManager) Run(ctx context.Context, cID string, stdout, stderr i
69 69
 		}
70 70
 	}()
71 71
 
72
-	if err := c.backend.ContainerStart(cID, nil, "", ""); err != nil {
72
+	if err := c.backend.ContainerStart(ctx, cID, nil, "", ""); err != nil {
73 73
 		close(finished)
74 74
 		logCancellationError(cancelErrCh, "error from ContainerStart: "+err.Error())
75 75
 		return err
... ...
@@ -9,6 +9,7 @@ package dockerfile // import "github.com/docker/docker/builder/dockerfile"
9 9
 
10 10
 import (
11 11
 	"bytes"
12
+	"context"
12 13
 	"fmt"
13 14
 	"runtime"
14 15
 	"sort"
... ...
@@ -35,7 +36,7 @@ import (
35 35
 //
36 36
 // Sets the environment variable foo to bar, also makes interpolation
37 37
 // in the dockerfile available from the next statement on via ${foo}.
38
-func dispatchEnv(d dispatchRequest, c *instructions.EnvCommand) error {
38
+func dispatchEnv(ctx context.Context, d dispatchRequest, c *instructions.EnvCommand) error {
39 39
 	runConfig := d.state.runConfig
40 40
 	commitMessage := bytes.NewBufferString("ENV")
41 41
 	for _, e := range c.Env {
... ...
@@ -57,21 +58,21 @@ func dispatchEnv(d dispatchRequest, c *instructions.EnvCommand) error {
57 57
 			runConfig.Env = append(runConfig.Env, newVar)
58 58
 		}
59 59
 	}
60
-	return d.builder.commit(d.state, commitMessage.String())
60
+	return d.builder.commit(ctx, d.state, commitMessage.String())
61 61
 }
62 62
 
63 63
 // MAINTAINER some text <maybe@an.email.address>
64 64
 //
65 65
 // Sets the maintainer metadata.
66
-func dispatchMaintainer(d dispatchRequest, c *instructions.MaintainerCommand) error {
66
+func dispatchMaintainer(ctx context.Context, d dispatchRequest, c *instructions.MaintainerCommand) error {
67 67
 	d.state.maintainer = c.Maintainer
68
-	return d.builder.commit(d.state, "MAINTAINER "+c.Maintainer)
68
+	return d.builder.commit(ctx, d.state, "MAINTAINER "+c.Maintainer)
69 69
 }
70 70
 
71 71
 // LABEL some json data describing the image
72 72
 //
73 73
 // Sets the Label variable foo to bar,
74
-func dispatchLabel(d dispatchRequest, c *instructions.LabelCommand) error {
74
+func dispatchLabel(ctx context.Context, d dispatchRequest, c *instructions.LabelCommand) error {
75 75
 	if d.state.runConfig.Labels == nil {
76 76
 		d.state.runConfig.Labels = make(map[string]string)
77 77
 	}
... ...
@@ -80,14 +81,14 @@ func dispatchLabel(d dispatchRequest, c *instructions.LabelCommand) error {
80 80
 		d.state.runConfig.Labels[v.Key] = v.Value
81 81
 		commitStr += " " + v.String()
82 82
 	}
83
-	return d.builder.commit(d.state, commitStr)
83
+	return d.builder.commit(ctx, d.state, commitStr)
84 84
 }
85 85
 
86 86
 // ADD foo /path
87 87
 //
88 88
 // Add the file 'foo' to '/path'. Tarball and Remote URL (http, https) handling
89 89
 // exist here. If you do not wish to have this automatic handling, use COPY.
90
-func dispatchAdd(d dispatchRequest, c *instructions.AddCommand) error {
90
+func dispatchAdd(ctx context.Context, d dispatchRequest, c *instructions.AddCommand) error {
91 91
 	if c.Chmod != "" {
92 92
 		return errors.New("the --chmod option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled")
93 93
 	}
... ...
@@ -102,13 +103,13 @@ func dispatchAdd(d dispatchRequest, c *instructions.AddCommand) error {
102 102
 	copyInstruction.chownStr = c.Chown
103 103
 	copyInstruction.allowLocalDecompression = true
104 104
 
105
-	return d.builder.performCopy(d, copyInstruction)
105
+	return d.builder.performCopy(ctx, d, copyInstruction)
106 106
 }
107 107
 
108 108
 // COPY foo /path
109 109
 //
110 110
 // Same as 'ADD' but without the tar and remote url handling.
111
-func dispatchCopy(d dispatchRequest, c *instructions.CopyCommand) error {
111
+func dispatchCopy(ctx context.Context, d dispatchRequest, c *instructions.CopyCommand) error {
112 112
 	if c.Chmod != "" {
113 113
 		return errors.New("the --chmod option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled")
114 114
 	}
... ...
@@ -130,7 +131,7 @@ func dispatchCopy(d dispatchRequest, c *instructions.CopyCommand) error {
130 130
 	if c.From != "" && copyInstruction.chownStr == "" {
131 131
 		copyInstruction.preserveOwnership = true
132 132
 	}
133
-	return d.builder.performCopy(d, copyInstruction)
133
+	return d.builder.performCopy(ctx, d, copyInstruction)
134 134
 }
135 135
 
136 136
 func (d *dispatchRequest) getImageMount(imageRefOrID string) (*imageMount, error) {
... ...
@@ -152,8 +153,11 @@ func (d *dispatchRequest) getImageMount(imageRefOrID string) (*imageMount, error
152 152
 }
153 153
 
154 154
 // FROM [--platform=platform] imagename[:tag | @digest] [AS build-stage-name]
155
-func initializeStage(d dispatchRequest, cmd *instructions.Stage) error {
156
-	d.builder.imageProber.Reset()
155
+func initializeStage(ctx context.Context, d dispatchRequest, cmd *instructions.Stage) error {
156
+	err := d.builder.imageProber.Reset(ctx)
157
+	if err != nil {
158
+		return err
159
+	}
157 160
 
158 161
 	var platform *specs.Platform
159 162
 	if v := cmd.Platform; v != "" {
... ...
@@ -180,12 +184,12 @@ func initializeStage(d dispatchRequest, cmd *instructions.Stage) error {
180 180
 	if len(state.runConfig.OnBuild) > 0 {
181 181
 		triggers := state.runConfig.OnBuild
182 182
 		state.runConfig.OnBuild = nil
183
-		return dispatchTriggeredOnBuild(d, triggers)
183
+		return dispatchTriggeredOnBuild(ctx, d, triggers)
184 184
 	}
185 185
 	return nil
186 186
 }
187 187
 
188
-func dispatchTriggeredOnBuild(d dispatchRequest, triggers []string) error {
188
+func dispatchTriggeredOnBuild(ctx context.Context, d dispatchRequest, triggers []string) error {
189 189
 	fmt.Fprintf(d.builder.Stdout, "# Executing %d build trigger", len(triggers))
190 190
 	if len(triggers) > 1 {
191 191
 		fmt.Fprint(d.builder.Stdout, "s")
... ...
@@ -208,7 +212,7 @@ func dispatchTriggeredOnBuild(d dispatchRequest, triggers []string) error {
208 208
 			}
209 209
 			return err
210 210
 		}
211
-		err = dispatch(d, cmd)
211
+		err = dispatch(ctx, d, cmd)
212 212
 		if err != nil {
213 213
 			return err
214 214
 		}
... ...
@@ -276,15 +280,15 @@ func (d *dispatchRequest) getFromImage(shlex *shell.Lex, basename string, platfo
276 276
 	return d.getImageOrStage(name, platform)
277 277
 }
278 278
 
279
-func dispatchOnbuild(d dispatchRequest, c *instructions.OnbuildCommand) error {
279
+func dispatchOnbuild(ctx context.Context, d dispatchRequest, c *instructions.OnbuildCommand) error {
280 280
 	d.state.runConfig.OnBuild = append(d.state.runConfig.OnBuild, c.Expression)
281
-	return d.builder.commit(d.state, "ONBUILD "+c.Expression)
281
+	return d.builder.commit(ctx, d.state, "ONBUILD "+c.Expression)
282 282
 }
283 283
 
284 284
 // WORKDIR /tmp
285 285
 //
286 286
 // Set the working directory for future RUN/CMD/etc statements.
287
-func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
287
+func dispatchWorkdir(ctx context.Context, d dispatchRequest, c *instructions.WorkdirCommand) error {
288 288
 	runConfig := d.state.runConfig
289 289
 	var err error
290 290
 	runConfig.WorkingDir, err = normalizeWorkdir(d.state.operatingSystem, runConfig.WorkingDir, c.Path)
... ...
@@ -305,7 +309,7 @@ func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
305 305
 	comment := "WORKDIR " + runConfig.WorkingDir
306 306
 	runConfigWithCommentCmd := copyRunConfig(runConfig, withCmdCommentString(comment, d.state.operatingSystem))
307 307
 
308
-	containerID, err := d.builder.probeAndCreate(d.state, runConfigWithCommentCmd)
308
+	containerID, err := d.builder.probeAndCreate(ctx, d.state, runConfigWithCommentCmd)
309 309
 	if err != nil || containerID == "" {
310 310
 		return err
311 311
 	}
... ...
@@ -326,7 +330,7 @@ func dispatchWorkdir(d dispatchRequest, c *instructions.WorkdirCommand) error {
326 326
 // RUN echo hi          # sh -c echo hi       (Linux and LCOW)
327 327
 // RUN echo hi          # cmd /S /C echo hi   (Windows)
328 328
 // RUN [ "echo", "hi" ] # echo hi
329
-func dispatchRun(d dispatchRequest, c *instructions.RunCommand) error {
329
+func dispatchRun(ctx context.Context, d dispatchRequest, c *instructions.RunCommand) error {
330 330
 	if !system.IsOSSupported(d.state.operatingSystem) {
331 331
 		return system.ErrNotSupportedOperatingSystem
332 332
 	}
... ...
@@ -360,7 +364,7 @@ func dispatchRun(d dispatchRequest, c *instructions.RunCommand) error {
360 360
 		withEntrypointOverride(saveCmd, strslice.StrSlice{""}),
361 361
 		withoutHealthcheck())
362 362
 
363
-	cID, err := d.builder.create(runConfig)
363
+	cID, err := d.builder.create(ctx, runConfig)
364 364
 	if err != nil {
365 365
 		return err
366 366
 	}
... ...
@@ -420,7 +424,7 @@ func prependEnvOnCmd(buildArgs *BuildArgs, buildArgVars []string, cmd strslice.S
420 420
 //
421 421
 // Set the default command to run in the container (which may be empty).
422 422
 // Argument handling is the same as RUN.
423
-func dispatchCmd(d dispatchRequest, c *instructions.CmdCommand) error {
423
+func dispatchCmd(ctx context.Context, d dispatchRequest, c *instructions.CmdCommand) error {
424 424
 	runConfig := d.state.runConfig
425 425
 	cmd, argsEscaped := resolveCmdLine(c.ShellDependantCmdLine, runConfig, d.state.operatingSystem, c.Name(), c.String())
426 426
 
... ...
@@ -436,7 +440,7 @@ func dispatchCmd(d dispatchRequest, c *instructions.CmdCommand) error {
436 436
 	runConfig.Cmd = cmd
437 437
 	runConfig.ArgsEscaped = argsEscaped
438 438
 
439
-	if err := d.builder.commit(d.state, fmt.Sprintf("CMD %q", cmd)); err != nil {
439
+	if err := d.builder.commit(ctx, d.state, fmt.Sprintf("CMD %q", cmd)); err != nil {
440 440
 		return err
441 441
 	}
442 442
 	if len(c.ShellDependantCmdLine.CmdLine) != 0 {
... ...
@@ -450,7 +454,7 @@ func dispatchCmd(d dispatchRequest, c *instructions.CmdCommand) error {
450 450
 //
451 451
 // Set the default healthcheck command to run in the container (which may be empty).
452 452
 // Argument handling is the same as RUN.
453
-func dispatchHealthcheck(d dispatchRequest, c *instructions.HealthCheckCommand) error {
453
+func dispatchHealthcheck(ctx context.Context, d dispatchRequest, c *instructions.HealthCheckCommand) error {
454 454
 	runConfig := d.state.runConfig
455 455
 	if runConfig.Healthcheck != nil {
456 456
 		oldCmd := runConfig.Healthcheck.Test
... ...
@@ -459,7 +463,7 @@ func dispatchHealthcheck(d dispatchRequest, c *instructions.HealthCheckCommand)
459 459
 		}
460 460
 	}
461 461
 	runConfig.Healthcheck = c.Health
462
-	return d.builder.commit(d.state, fmt.Sprintf("HEALTHCHECK %q", runConfig.Healthcheck))
462
+	return d.builder.commit(ctx, d.state, fmt.Sprintf("HEALTHCHECK %q", runConfig.Healthcheck))
463 463
 }
464 464
 
465 465
 // ENTRYPOINT /usr/sbin/nginx
... ...
@@ -469,7 +473,7 @@ func dispatchHealthcheck(d dispatchRequest, c *instructions.HealthCheckCommand)
469 469
 //
470 470
 // Handles command processing similar to CMD and RUN, only req.runConfig.Entrypoint
471 471
 // is initialized at newBuilder time instead of through argument parsing.
472
-func dispatchEntrypoint(d dispatchRequest, c *instructions.EntrypointCommand) error {
472
+func dispatchEntrypoint(ctx context.Context, d dispatchRequest, c *instructions.EntrypointCommand) error {
473 473
 	runConfig := d.state.runConfig
474 474
 	cmd, argsEscaped := resolveCmdLine(c.ShellDependantCmdLine, runConfig, d.state.operatingSystem, c.Name(), c.String())
475 475
 
... ...
@@ -491,14 +495,14 @@ func dispatchEntrypoint(d dispatchRequest, c *instructions.EntrypointCommand) er
491 491
 		runConfig.Cmd = nil
492 492
 	}
493 493
 
494
-	return d.builder.commit(d.state, fmt.Sprintf("ENTRYPOINT %q", runConfig.Entrypoint))
494
+	return d.builder.commit(ctx, d.state, fmt.Sprintf("ENTRYPOINT %q", runConfig.Entrypoint))
495 495
 }
496 496
 
497 497
 // EXPOSE 6667/tcp 7000/tcp
498 498
 //
499 499
 // Expose ports for links and port mappings. This all ends up in
500 500
 // req.runConfig.ExposedPorts for runconfig.
501
-func dispatchExpose(d dispatchRequest, c *instructions.ExposeCommand, envs []string) error {
501
+func dispatchExpose(ctx context.Context, d dispatchRequest, c *instructions.ExposeCommand, envs []string) error {
502 502
 	// custom multi word expansion
503 503
 	// expose $FOO with FOO="80 443" is expanded as EXPOSE [80,443]. This is the only command supporting word to words expansion
504 504
 	// so the word processing has been de-generalized
... ...
@@ -524,22 +528,22 @@ func dispatchExpose(d dispatchRequest, c *instructions.ExposeCommand, envs []str
524 524
 		d.state.runConfig.ExposedPorts[p] = struct{}{}
525 525
 	}
526 526
 
527
-	return d.builder.commit(d.state, "EXPOSE "+strings.Join(c.Ports, " "))
527
+	return d.builder.commit(ctx, d.state, "EXPOSE "+strings.Join(c.Ports, " "))
528 528
 }
529 529
 
530 530
 // USER foo
531 531
 //
532 532
 // Set the user to 'foo' for future commands and when running the
533 533
 // ENTRYPOINT/CMD at container run time.
534
-func dispatchUser(d dispatchRequest, c *instructions.UserCommand) error {
534
+func dispatchUser(ctx context.Context, d dispatchRequest, c *instructions.UserCommand) error {
535 535
 	d.state.runConfig.User = c.User
536
-	return d.builder.commit(d.state, fmt.Sprintf("USER %v", c.User))
536
+	return d.builder.commit(ctx, d.state, fmt.Sprintf("USER %v", c.User))
537 537
 }
538 538
 
539 539
 // VOLUME /foo
540 540
 //
541 541
 // Expose the volume /foo for use. Will also accept the JSON array form.
542
-func dispatchVolume(d dispatchRequest, c *instructions.VolumeCommand) error {
542
+func dispatchVolume(ctx context.Context, d dispatchRequest, c *instructions.VolumeCommand) error {
543 543
 	if d.state.runConfig.Volumes == nil {
544 544
 		d.state.runConfig.Volumes = map[string]struct{}{}
545 545
 	}
... ...
@@ -549,19 +553,19 @@ func dispatchVolume(d dispatchRequest, c *instructions.VolumeCommand) error {
549 549
 		}
550 550
 		d.state.runConfig.Volumes[v] = struct{}{}
551 551
 	}
552
-	return d.builder.commit(d.state, fmt.Sprintf("VOLUME %v", c.Volumes))
552
+	return d.builder.commit(ctx, d.state, fmt.Sprintf("VOLUME %v", c.Volumes))
553 553
 }
554 554
 
555 555
 // STOPSIGNAL signal
556 556
 //
557 557
 // Set the signal that will be used to kill the container.
558
-func dispatchStopSignal(d dispatchRequest, c *instructions.StopSignalCommand) error {
558
+func dispatchStopSignal(ctx context.Context, d dispatchRequest, c *instructions.StopSignalCommand) error {
559 559
 	_, err := signal.ParseSignal(c.Signal)
560 560
 	if err != nil {
561 561
 		return errdefs.InvalidParameter(err)
562 562
 	}
563 563
 	d.state.runConfig.StopSignal = c.Signal
564
-	return d.builder.commit(d.state, fmt.Sprintf("STOPSIGNAL %v", c.Signal))
564
+	return d.builder.commit(ctx, d.state, fmt.Sprintf("STOPSIGNAL %v", c.Signal))
565 565
 }
566 566
 
567 567
 // ARG name[=value]
... ...
@@ -569,7 +573,7 @@ func dispatchStopSignal(d dispatchRequest, c *instructions.StopSignalCommand) er
569 569
 // Adds the variable foo to the trusted list of variables that can be passed
570 570
 // to builder using the --build-arg flag for expansion/substitution or passing to 'run'.
571 571
 // Dockerfile author may optionally set a default value of this variable.
572
-func dispatchArg(d dispatchRequest, c *instructions.ArgCommand) error {
572
+func dispatchArg(ctx context.Context, d dispatchRequest, c *instructions.ArgCommand) error {
573 573
 	var commitStr strings.Builder
574 574
 	commitStr.WriteString("ARG ")
575 575
 	for i, arg := range c.Args {
... ...
@@ -584,13 +588,13 @@ func dispatchArg(d dispatchRequest, c *instructions.ArgCommand) error {
584 584
 		d.state.buildArgs.AddArg(arg.Key, arg.Value)
585 585
 	}
586 586
 
587
-	return d.builder.commit(d.state, commitStr.String())
587
+	return d.builder.commit(ctx, d.state, commitStr.String())
588 588
 }
589 589
 
590 590
 // SHELL powershell -command
591 591
 //
592 592
 // Set the non-default shell to use.
593
-func dispatchShell(d dispatchRequest, c *instructions.ShellCommand) error {
593
+func dispatchShell(ctx context.Context, d dispatchRequest, c *instructions.ShellCommand) error {
594 594
 	d.state.runConfig.Shell = c.Shell
595
-	return d.builder.commit(d.state, fmt.Sprintf("SHELL %v", d.state.runConfig.Shell))
595
+	return d.builder.commit(ctx, d.state, fmt.Sprintf("SHELL %v", d.state.runConfig.Shell))
596 596
 }
... ...
@@ -23,10 +23,15 @@ import (
23 23
 	is "gotest.tools/v3/assert/cmp"
24 24
 )
25 25
 
26
-func newBuilderWithMockBackend() *Builder {
26
+func newBuilderWithMockBackend(t *testing.T) *Builder {
27
+	t.Helper()
27 28
 	mockBackend := &MockBackend{}
28 29
 	opts := &types.ImageBuildOptions{}
29 30
 	ctx := context.Background()
31
+
32
+	imageProber, err := newImageProber(ctx, mockBackend, nil, false)
33
+	assert.NilError(t, err, "Could not create image prober")
34
+
30 35
 	b := &Builder{
31 36
 		options:       opts,
32 37
 		docker:        mockBackend,
... ...
@@ -37,14 +42,14 @@ func newBuilderWithMockBackend() *Builder {
37 37
 			Options: opts,
38 38
 			Backend: mockBackend,
39 39
 		}),
40
-		imageProber:      newImageProber(mockBackend, nil, false),
40
+		imageProber:      imageProber,
41 41
 		containerManager: newContainerManager(mockBackend),
42 42
 	}
43 43
 	return b
44 44
 }
45 45
 
46 46
 func TestEnv2Variables(t *testing.T) {
47
-	b := newBuilderWithMockBackend()
47
+	b := newBuilderWithMockBackend(t)
48 48
 	sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
49 49
 	envCommand := &instructions.EnvCommand{
50 50
 		Env: instructions.KeyValuePairs{
... ...
@@ -52,7 +57,7 @@ func TestEnv2Variables(t *testing.T) {
52 52
 			instructions.KeyValuePair{Key: "var2", Value: "val2"},
53 53
 		},
54 54
 	}
55
-	err := dispatch(sb, envCommand)
55
+	err := dispatch(context.TODO(), sb, envCommand)
56 56
 	assert.NilError(t, err)
57 57
 
58 58
 	expected := []string{
... ...
@@ -63,7 +68,7 @@ func TestEnv2Variables(t *testing.T) {
63 63
 }
64 64
 
65 65
 func TestEnvValueWithExistingRunConfigEnv(t *testing.T) {
66
-	b := newBuilderWithMockBackend()
66
+	b := newBuilderWithMockBackend(t)
67 67
 	sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
68 68
 	sb.state.runConfig.Env = []string{"var1=old", "var2=fromenv"}
69 69
 	envCommand := &instructions.EnvCommand{
... ...
@@ -71,7 +76,7 @@ func TestEnvValueWithExistingRunConfigEnv(t *testing.T) {
71 71
 			instructions.KeyValuePair{Key: "var1", Value: "val1"},
72 72
 		},
73 73
 	}
74
-	err := dispatch(sb, envCommand)
74
+	err := dispatch(context.TODO(), sb, envCommand)
75 75
 	assert.NilError(t, err)
76 76
 	expected := []string{
77 77
 		"var1=val1",
... ...
@@ -82,10 +87,10 @@ func TestEnvValueWithExistingRunConfigEnv(t *testing.T) {
82 82
 
83 83
 func TestMaintainer(t *testing.T) {
84 84
 	maintainerEntry := "Some Maintainer <maintainer@example.com>"
85
-	b := newBuilderWithMockBackend()
85
+	b := newBuilderWithMockBackend(t)
86 86
 	sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
87 87
 	cmd := &instructions.MaintainerCommand{Maintainer: maintainerEntry}
88
-	err := dispatch(sb, cmd)
88
+	err := dispatch(context.TODO(), sb, cmd)
89 89
 	assert.NilError(t, err)
90 90
 	assert.Check(t, is.Equal(maintainerEntry, sb.state.maintainer))
91 91
 }
... ...
@@ -94,14 +99,14 @@ func TestLabel(t *testing.T) {
94 94
 	labelName := "label"
95 95
 	labelValue := "value"
96 96
 
97
-	b := newBuilderWithMockBackend()
97
+	b := newBuilderWithMockBackend(t)
98 98
 	sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
99 99
 	cmd := &instructions.LabelCommand{
100 100
 		Labels: instructions.KeyValuePairs{
101 101
 			instructions.KeyValuePair{Key: labelName, Value: labelValue},
102 102
 		},
103 103
 	}
104
-	err := dispatch(sb, cmd)
104
+	err := dispatch(context.TODO(), sb, cmd)
105 105
 	assert.NilError(t, err)
106 106
 
107 107
 	assert.Assert(t, is.Contains(sb.state.runConfig.Labels, labelName))
... ...
@@ -109,12 +114,12 @@ func TestLabel(t *testing.T) {
109 109
 }
110 110
 
111 111
 func TestFromScratch(t *testing.T) {
112
-	b := newBuilderWithMockBackend()
112
+	b := newBuilderWithMockBackend(t)
113 113
 	sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
114 114
 	cmd := &instructions.Stage{
115 115
 		BaseName: "scratch",
116 116
 	}
117
-	err := initializeStage(sb, cmd)
117
+	err := initializeStage(context.TODO(), sb, cmd)
118 118
 
119 119
 	if runtime.GOOS == "windows" {
120 120
 		assert.Check(t, is.Error(err, "Windows does not support FROM scratch"))
... ...
@@ -135,7 +140,7 @@ func TestFromWithArg(t *testing.T) {
135 135
 		assert.Check(t, is.Equal("alpine"+tag, name))
136 136
 		return &mockImage{id: "expectedthisid"}, nil, nil
137 137
 	}
138
-	b := newBuilderWithMockBackend()
138
+	b := newBuilderWithMockBackend(t)
139 139
 	b.docker.(*MockBackend).getImageFunc = getImage
140 140
 	args := NewBuildArgs(make(map[string]*string))
141 141
 
... ...
@@ -151,7 +156,7 @@ func TestFromWithArg(t *testing.T) {
151 151
 
152 152
 	sb := newDispatchRequest(b, '\\', nil, args, newStagesBuildResults())
153 153
 	assert.NilError(t, err)
154
-	err = initializeStage(sb, cmd)
154
+	err = initializeStage(context.TODO(), sb, cmd)
155 155
 	assert.NilError(t, err)
156 156
 
157 157
 	assert.Check(t, is.Equal(expected, sb.state.imageID))
... ...
@@ -161,7 +166,7 @@ func TestFromWithArg(t *testing.T) {
161 161
 }
162 162
 
163 163
 func TestFromWithArgButBuildArgsNotGiven(t *testing.T) {
164
-	b := newBuilderWithMockBackend()
164
+	b := newBuilderWithMockBackend(t)
165 165
 	args := NewBuildArgs(make(map[string]*string))
166 166
 
167 167
 	metaArg := instructions.ArgCommand{}
... ...
@@ -172,7 +177,7 @@ func TestFromWithArgButBuildArgsNotGiven(t *testing.T) {
172 172
 
173 173
 	sb := newDispatchRequest(b, '\\', nil, args, newStagesBuildResults())
174 174
 	assert.NilError(t, err)
175
-	err = initializeStage(sb, cmd)
175
+	err = initializeStage(context.TODO(), sb, cmd)
176 176
 	assert.Error(t, err, "base name (${THETAG}) should not be blank")
177 177
 }
178 178
 
... ...
@@ -183,7 +188,7 @@ func TestFromWithUndefinedArg(t *testing.T) {
183 183
 		assert.Check(t, is.Equal("alpine", name))
184 184
 		return &mockImage{id: "expectedthisid"}, nil, nil
185 185
 	}
186
-	b := newBuilderWithMockBackend()
186
+	b := newBuilderWithMockBackend(t)
187 187
 	b.docker.(*MockBackend).getImageFunc = getImage
188 188
 	sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
189 189
 
... ...
@@ -192,41 +197,41 @@ func TestFromWithUndefinedArg(t *testing.T) {
192 192
 	cmd := &instructions.Stage{
193 193
 		BaseName: "alpine${THETAG}",
194 194
 	}
195
-	err := initializeStage(sb, cmd)
195
+	err := initializeStage(context.TODO(), sb, cmd)
196 196
 	assert.NilError(t, err)
197 197
 	assert.Check(t, is.Equal(expected, sb.state.imageID))
198 198
 }
199 199
 
200 200
 func TestFromMultiStageWithNamedStage(t *testing.T) {
201
-	b := newBuilderWithMockBackend()
201
+	b := newBuilderWithMockBackend(t)
202 202
 	firstFrom := &instructions.Stage{BaseName: "someimg", Name: "base"}
203 203
 	secondFrom := &instructions.Stage{BaseName: "base"}
204 204
 	previousResults := newStagesBuildResults()
205 205
 	firstSB := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), previousResults)
206 206
 	secondSB := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), previousResults)
207
-	err := initializeStage(firstSB, firstFrom)
207
+	err := initializeStage(context.TODO(), firstSB, firstFrom)
208 208
 	assert.NilError(t, err)
209 209
 	assert.Check(t, firstSB.state.hasFromImage())
210 210
 	previousResults.indexed["base"] = firstSB.state.runConfig
211 211
 	previousResults.flat = append(previousResults.flat, firstSB.state.runConfig)
212
-	err = initializeStage(secondSB, secondFrom)
212
+	err = initializeStage(context.TODO(), secondSB, secondFrom)
213 213
 	assert.NilError(t, err)
214 214
 	assert.Check(t, secondSB.state.hasFromImage())
215 215
 }
216 216
 
217 217
 func TestOnbuild(t *testing.T) {
218
-	b := newBuilderWithMockBackend()
218
+	b := newBuilderWithMockBackend(t)
219 219
 	sb := newDispatchRequest(b, '\\', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
220 220
 	cmd := &instructions.OnbuildCommand{
221 221
 		Expression: "ADD . /app/src",
222 222
 	}
223
-	err := dispatch(sb, cmd)
223
+	err := dispatch(context.TODO(), sb, cmd)
224 224
 	assert.NilError(t, err)
225 225
 	assert.Check(t, is.Equal("ADD . /app/src", sb.state.runConfig.OnBuild[0]))
226 226
 }
227 227
 
228 228
 func TestWorkdir(t *testing.T) {
229
-	b := newBuilderWithMockBackend()
229
+	b := newBuilderWithMockBackend(t)
230 230
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
231 231
 	sb.state.baseImage = &mockImage{}
232 232
 	workingDir := "/app"
... ...
@@ -237,13 +242,13 @@ func TestWorkdir(t *testing.T) {
237 237
 		Path: workingDir,
238 238
 	}
239 239
 
240
-	err := dispatch(sb, cmd)
240
+	err := dispatch(context.TODO(), sb, cmd)
241 241
 	assert.NilError(t, err)
242 242
 	assert.Check(t, is.Equal(workingDir, sb.state.runConfig.WorkingDir))
243 243
 }
244 244
 
245 245
 func TestCmd(t *testing.T) {
246
-	b := newBuilderWithMockBackend()
246
+	b := newBuilderWithMockBackend(t)
247 247
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
248 248
 	sb.state.baseImage = &mockImage{}
249 249
 	command := "./executable"
... ...
@@ -254,7 +259,7 @@ func TestCmd(t *testing.T) {
254 254
 			PrependShell: true,
255 255
 		},
256 256
 	}
257
-	err := dispatch(sb, cmd)
257
+	err := dispatch(context.TODO(), sb, cmd)
258 258
 	assert.NilError(t, err)
259 259
 
260 260
 	var expectedCommand strslice.StrSlice
... ...
@@ -269,14 +274,14 @@ func TestCmd(t *testing.T) {
269 269
 }
270 270
 
271 271
 func TestHealthcheckNone(t *testing.T) {
272
-	b := newBuilderWithMockBackend()
272
+	b := newBuilderWithMockBackend(t)
273 273
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
274 274
 	cmd := &instructions.HealthCheckCommand{
275 275
 		Health: &container.HealthConfig{
276 276
 			Test: []string{"NONE"},
277 277
 		},
278 278
 	}
279
-	err := dispatch(sb, cmd)
279
+	err := dispatch(context.TODO(), sb, cmd)
280 280
 	assert.NilError(t, err)
281 281
 
282 282
 	assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
... ...
@@ -284,7 +289,7 @@ func TestHealthcheckNone(t *testing.T) {
284 284
 }
285 285
 
286 286
 func TestHealthcheckCmd(t *testing.T) {
287
-	b := newBuilderWithMockBackend()
287
+	b := newBuilderWithMockBackend(t)
288 288
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
289 289
 	expectedTest := []string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"}
290 290
 	cmd := &instructions.HealthCheckCommand{
... ...
@@ -292,7 +297,7 @@ func TestHealthcheckCmd(t *testing.T) {
292 292
 			Test: expectedTest,
293 293
 		},
294 294
 	}
295
-	err := dispatch(sb, cmd)
295
+	err := dispatch(context.TODO(), sb, cmd)
296 296
 	assert.NilError(t, err)
297 297
 
298 298
 	assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
... ...
@@ -300,7 +305,7 @@ func TestHealthcheckCmd(t *testing.T) {
300 300
 }
301 301
 
302 302
 func TestEntrypoint(t *testing.T) {
303
-	b := newBuilderWithMockBackend()
303
+	b := newBuilderWithMockBackend(t)
304 304
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
305 305
 	sb.state.baseImage = &mockImage{}
306 306
 	entrypointCmd := "/usr/sbin/nginx"
... ...
@@ -311,7 +316,7 @@ func TestEntrypoint(t *testing.T) {
311 311
 			PrependShell: true,
312 312
 		},
313 313
 	}
314
-	err := dispatch(sb, cmd)
314
+	err := dispatch(context.TODO(), sb, cmd)
315 315
 	assert.NilError(t, err)
316 316
 	assert.Assert(t, sb.state.runConfig.Entrypoint != nil)
317 317
 
... ...
@@ -325,14 +330,14 @@ func TestEntrypoint(t *testing.T) {
325 325
 }
326 326
 
327 327
 func TestExpose(t *testing.T) {
328
-	b := newBuilderWithMockBackend()
328
+	b := newBuilderWithMockBackend(t)
329 329
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
330 330
 
331 331
 	exposedPort := "80"
332 332
 	cmd := &instructions.ExposeCommand{
333 333
 		Ports: []string{exposedPort},
334 334
 	}
335
-	err := dispatch(sb, cmd)
335
+	err := dispatch(context.TODO(), sb, cmd)
336 336
 	assert.NilError(t, err)
337 337
 
338 338
 	assert.Assert(t, sb.state.runConfig.ExposedPorts != nil)
... ...
@@ -344,19 +349,19 @@ func TestExpose(t *testing.T) {
344 344
 }
345 345
 
346 346
 func TestUser(t *testing.T) {
347
-	b := newBuilderWithMockBackend()
347
+	b := newBuilderWithMockBackend(t)
348 348
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
349 349
 
350 350
 	cmd := &instructions.UserCommand{
351 351
 		User: "test",
352 352
 	}
353
-	err := dispatch(sb, cmd)
353
+	err := dispatch(context.TODO(), sb, cmd)
354 354
 	assert.NilError(t, err)
355 355
 	assert.Check(t, is.Equal("test", sb.state.runConfig.User))
356 356
 }
357 357
 
358 358
 func TestVolume(t *testing.T) {
359
-	b := newBuilderWithMockBackend()
359
+	b := newBuilderWithMockBackend(t)
360 360
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
361 361
 
362 362
 	exposedVolume := "/foo"
... ...
@@ -364,7 +369,7 @@ func TestVolume(t *testing.T) {
364 364
 	cmd := &instructions.VolumeCommand{
365 365
 		Volumes: []string{exposedVolume},
366 366
 	}
367
-	err := dispatch(sb, cmd)
367
+	err := dispatch(context.TODO(), sb, cmd)
368 368
 	assert.NilError(t, err)
369 369
 	assert.Assert(t, sb.state.runConfig.Volumes != nil)
370 370
 	assert.Check(t, is.Len(sb.state.runConfig.Volumes, 1))
... ...
@@ -376,7 +381,7 @@ func TestStopSignal(t *testing.T) {
376 376
 		t.Skip("Windows does not support stopsignal")
377 377
 		return
378 378
 	}
379
-	b := newBuilderWithMockBackend()
379
+	b := newBuilderWithMockBackend(t)
380 380
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
381 381
 	sb.state.baseImage = &mockImage{}
382 382
 	signal := "SIGKILL"
... ...
@@ -384,19 +389,19 @@ func TestStopSignal(t *testing.T) {
384 384
 	cmd := &instructions.StopSignalCommand{
385 385
 		Signal: signal,
386 386
 	}
387
-	err := dispatch(sb, cmd)
387
+	err := dispatch(context.TODO(), sb, cmd)
388 388
 	assert.NilError(t, err)
389 389
 	assert.Check(t, is.Equal(signal, sb.state.runConfig.StopSignal))
390 390
 }
391 391
 
392 392
 func TestArg(t *testing.T) {
393
-	b := newBuilderWithMockBackend()
393
+	b := newBuilderWithMockBackend(t)
394 394
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
395 395
 
396 396
 	argName := "foo"
397 397
 	argVal := "bar"
398 398
 	cmd := &instructions.ArgCommand{Args: []instructions.KeyValuePairOptional{{Key: argName, Value: &argVal}}}
399
-	err := dispatch(sb, cmd)
399
+	err := dispatch(context.TODO(), sb, cmd)
400 400
 	assert.NilError(t, err)
401 401
 
402 402
 	expected := map[string]string{argName: argVal}
... ...
@@ -404,13 +409,13 @@ func TestArg(t *testing.T) {
404 404
 }
405 405
 
406 406
 func TestShell(t *testing.T) {
407
-	b := newBuilderWithMockBackend()
407
+	b := newBuilderWithMockBackend(t)
408 408
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
409 409
 
410 410
 	shellCmd := "powershell"
411 411
 	cmd := &instructions.ShellCommand{Shell: strslice.StrSlice{shellCmd}}
412 412
 
413
-	err := dispatch(sb, cmd)
413
+	err := dispatch(context.TODO(), sb, cmd)
414 414
 	assert.NilError(t, err)
415 415
 
416 416
 	expectedShell := strslice.StrSlice([]string{shellCmd})
... ...
@@ -430,7 +435,7 @@ func TestPrependEnvOnCmd(t *testing.T) {
430 430
 }
431 431
 
432 432
 func TestRunWithBuildArgs(t *testing.T) {
433
-	b := newBuilderWithMockBackend()
433
+	b := newBuilderWithMockBackend(t)
434 434
 	args := NewBuildArgs(make(map[string]*string))
435 435
 	args.argsFromOptions["HTTP_PROXY"] = strPtr("FOO")
436 436
 	b.disableCommit = false
... ...
@@ -462,7 +467,11 @@ func TestRunWithBuildArgs(t *testing.T) {
462 462
 	mockBackend.makeImageCacheFunc = func(_ []string) builder.ImageCache {
463 463
 		return imageCache
464 464
 	}
465
-	b.imageProber = newImageProber(mockBackend, nil, false)
465
+
466
+	imageProber, err := newImageProber(context.TODO(), mockBackend, nil, false)
467
+	assert.NilError(t, err, "Could not create image prober")
468
+	b.imageProber = imageProber
469
+
466 470
 	mockBackend.getImageFunc = func(_ string) (builder.Image, builder.ROLayer, error) {
467 471
 		return &mockImage{
468 472
 			id:     "abcdef",
... ...
@@ -484,7 +493,7 @@ func TestRunWithBuildArgs(t *testing.T) {
484 484
 		return "", nil
485 485
 	}
486 486
 	from := &instructions.Stage{BaseName: "abcdef"}
487
-	err := initializeStage(sb, from)
487
+	err = initializeStage(context.TODO(), sb, from)
488 488
 	assert.NilError(t, err)
489 489
 	sb.state.buildArgs.AddArg("one", strPtr("two"))
490 490
 
... ...
@@ -504,14 +513,14 @@ func TestRunWithBuildArgs(t *testing.T) {
504 504
 	runinst.CmdLine = strslice.StrSlice{"echo foo"}
505 505
 	runinst.PrependShell = true
506 506
 
507
-	assert.NilError(t, dispatch(sb, runinst))
507
+	assert.NilError(t, dispatch(context.TODO(), sb, runinst))
508 508
 
509 509
 	// Check that runConfig.Cmd has not been modified by run
510 510
 	assert.Check(t, is.DeepEqual(origCmd, sb.state.runConfig.Cmd))
511 511
 }
512 512
 
513 513
 func TestRunIgnoresHealthcheck(t *testing.T) {
514
-	b := newBuilderWithMockBackend()
514
+	b := newBuilderWithMockBackend(t)
515 515
 	args := NewBuildArgs(make(map[string]*string))
516 516
 	sb := newDispatchRequest(b, '`', nil, args, newStagesBuildResults())
517 517
 	b.disableCommit = false
... ...
@@ -528,7 +537,10 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
528 528
 	mockBackend.makeImageCacheFunc = func(_ []string) builder.ImageCache {
529 529
 		return imageCache
530 530
 	}
531
-	b.imageProber = newImageProber(mockBackend, nil, false)
531
+	imageProber, err := newImageProber(context.TODO(), mockBackend, nil, false)
532
+	assert.NilError(t, err, "Could not create image prober")
533
+
534
+	b.imageProber = imageProber
532 535
 	mockBackend.getImageFunc = func(_ string) (builder.Image, builder.ROLayer, error) {
533 536
 		return &mockImage{
534 537
 			id:     "abcdef",
... ...
@@ -542,7 +554,7 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
542 542
 		return "", nil
543 543
 	}
544 544
 	from := &instructions.Stage{BaseName: "abcdef"}
545
-	err := initializeStage(sb, from)
545
+	err = initializeStage(context.TODO(), sb, from)
546 546
 	assert.NilError(t, err)
547 547
 
548 548
 	expectedTest := []string{"CMD-SHELL", "curl -f http://localhost/ || exit 1"}
... ...
@@ -559,7 +571,7 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
559 559
 	assert.NilError(t, err)
560 560
 	cmd := healthint.(*instructions.HealthCheckCommand)
561 561
 
562
-	assert.NilError(t, dispatch(sb, cmd))
562
+	assert.NilError(t, dispatch(context.TODO(), sb, cmd))
563 563
 	assert.Assert(t, sb.state.runConfig.Healthcheck != nil)
564 564
 
565 565
 	mockBackend.containerCreateFunc = func(config types.ContainerCreateConfig) (container.CreateResponse, error) {
... ...
@@ -574,12 +586,12 @@ func TestRunIgnoresHealthcheck(t *testing.T) {
574 574
 	run := runint.(*instructions.RunCommand)
575 575
 	run.PrependShell = true
576 576
 
577
-	assert.NilError(t, dispatch(sb, run))
577
+	assert.NilError(t, dispatch(context.TODO(), sb, run))
578 578
 	assert.Check(t, is.DeepEqual(expectedTest, sb.state.runConfig.Healthcheck.Test))
579 579
 }
580 580
 
581 581
 func TestDispatchUnsupportedOptions(t *testing.T) {
582
-	b := newBuilderWithMockBackend()
582
+	b := newBuilderWithMockBackend(t)
583 583
 	sb := newDispatchRequest(b, '`', nil, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
584 584
 	sb.state.baseImage = &mockImage{}
585 585
 	sb.state.operatingSystem = runtime.GOOS
... ...
@@ -592,7 +604,7 @@ func TestDispatchUnsupportedOptions(t *testing.T) {
592 592
 			},
593 593
 			Chmod: "0655",
594 594
 		}
595
-		err := dispatch(sb, cmd)
595
+		err := dispatch(context.TODO(), sb, cmd)
596 596
 		assert.Error(t, err, "the --chmod option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled")
597 597
 	})
598 598
 
... ...
@@ -604,7 +616,7 @@ func TestDispatchUnsupportedOptions(t *testing.T) {
604 604
 			},
605 605
 			Chmod: "0655",
606 606
 		}
607
-		err := dispatch(sb, cmd)
607
+		err := dispatch(context.TODO(), sb, cmd)
608 608
 		assert.Error(t, err, "the --chmod option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled")
609 609
 	})
610 610
 
... ...
@@ -618,7 +630,7 @@ func TestDispatchUnsupportedOptions(t *testing.T) {
618 618
 		// one or more of these flags will be supported in future
619 619
 		for _, f := range []string{"mount", "network", "security", "any-flag"} {
620 620
 			cmd.FlagsUsed = []string{f}
621
-			err := dispatch(sb, cmd)
621
+			err := dispatch(context.TODO(), sb, cmd)
622 622
 			assert.Error(t, err, fmt.Sprintf("the --%s option requires BuildKit. Refer to https://docs.docker.com/go/buildkit/ to learn how to build images with BuildKit enabled", f))
623 623
 		}
624 624
 	})
... ...
@@ -20,6 +20,7 @@
20 20
 package dockerfile // import "github.com/docker/docker/builder/dockerfile"
21 21
 
22 22
 import (
23
+	"context"
23 24
 	"reflect"
24 25
 	"strconv"
25 26
 	"strings"
... ...
@@ -34,7 +35,7 @@ import (
34 34
 	"github.com/pkg/errors"
35 35
 )
36 36
 
37
-func dispatch(d dispatchRequest, cmd instructions.Command) (err error) {
37
+func dispatch(ctx context.Context, d dispatchRequest, cmd instructions.Command) (err error) {
38 38
 	if c, ok := cmd.(instructions.PlatformSpecific); ok {
39 39
 		err := c.CheckPlatform(d.state.operatingSystem)
40 40
 		if err != nil {
... ...
@@ -65,39 +66,39 @@ func dispatch(d dispatchRequest, cmd instructions.Command) (err error) {
65 65
 	}()
66 66
 	switch c := cmd.(type) {
67 67
 	case *instructions.EnvCommand:
68
-		return dispatchEnv(d, c)
68
+		return dispatchEnv(ctx, d, c)
69 69
 	case *instructions.MaintainerCommand:
70
-		return dispatchMaintainer(d, c)
70
+		return dispatchMaintainer(ctx, d, c)
71 71
 	case *instructions.LabelCommand:
72
-		return dispatchLabel(d, c)
72
+		return dispatchLabel(ctx, d, c)
73 73
 	case *instructions.AddCommand:
74
-		return dispatchAdd(d, c)
74
+		return dispatchAdd(ctx, d, c)
75 75
 	case *instructions.CopyCommand:
76
-		return dispatchCopy(d, c)
76
+		return dispatchCopy(ctx, d, c)
77 77
 	case *instructions.OnbuildCommand:
78
-		return dispatchOnbuild(d, c)
78
+		return dispatchOnbuild(ctx, d, c)
79 79
 	case *instructions.WorkdirCommand:
80
-		return dispatchWorkdir(d, c)
80
+		return dispatchWorkdir(ctx, d, c)
81 81
 	case *instructions.RunCommand:
82
-		return dispatchRun(d, c)
82
+		return dispatchRun(ctx, d, c)
83 83
 	case *instructions.CmdCommand:
84
-		return dispatchCmd(d, c)
84
+		return dispatchCmd(ctx, d, c)
85 85
 	case *instructions.HealthCheckCommand:
86
-		return dispatchHealthcheck(d, c)
86
+		return dispatchHealthcheck(ctx, d, c)
87 87
 	case *instructions.EntrypointCommand:
88
-		return dispatchEntrypoint(d, c)
88
+		return dispatchEntrypoint(ctx, d, c)
89 89
 	case *instructions.ExposeCommand:
90
-		return dispatchExpose(d, c, envs)
90
+		return dispatchExpose(ctx, d, c, envs)
91 91
 	case *instructions.UserCommand:
92
-		return dispatchUser(d, c)
92
+		return dispatchUser(ctx, d, c)
93 93
 	case *instructions.VolumeCommand:
94
-		return dispatchVolume(d, c)
94
+		return dispatchVolume(ctx, d, c)
95 95
 	case *instructions.StopSignalCommand:
96
-		return dispatchStopSignal(d, c)
96
+		return dispatchStopSignal(ctx, d, c)
97 97
 	case *instructions.ArgCommand:
98
-		return dispatchArg(d, c)
98
+		return dispatchArg(ctx, d, c)
99 99
 	case *instructions.ShellCommand:
100
-		return dispatchShell(d, c)
100
+		return dispatchShell(ctx, d, c)
101 101
 	}
102 102
 	return errors.Errorf("unsupported command type: %v", reflect.TypeOf(cmd))
103 103
 }
... ...
@@ -1,6 +1,7 @@
1 1
 package dockerfile // import "github.com/docker/docker/builder/dockerfile"
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"os"
5 6
 	"runtime"
6 7
 	"testing"
... ...
@@ -127,9 +128,9 @@ func TestDispatch(t *testing.T) {
127 127
 				}
128 128
 			}()
129 129
 
130
-			b := newBuilderWithMockBackend()
130
+			b := newBuilderWithMockBackend(t)
131 131
 			sb := newDispatchRequest(b, '`', buildContext, NewBuildArgs(make(map[string]*string)), newStagesBuildResults())
132
-			err = dispatch(sb, tc.cmd)
132
+			err = dispatch(context.TODO(), sb, tc.cmd)
133 133
 			assert.Check(t, is.ErrorContains(err, tc.expectedError))
134 134
 		})
135 135
 	}
... ...
@@ -1,6 +1,8 @@
1 1
 package dockerfile // import "github.com/docker/docker/builder/dockerfile"
2 2
 
3 3
 import (
4
+	"context"
5
+
4 6
 	"github.com/docker/docker/api/types/container"
5 7
 	"github.com/docker/docker/builder"
6 8
 	"github.com/sirupsen/logrus"
... ...
@@ -9,30 +11,42 @@ import (
9 9
 // ImageProber exposes an Image cache to the Builder. It supports resetting a
10 10
 // cache.
11 11
 type ImageProber interface {
12
-	Reset()
12
+	Reset(ctx context.Context) error
13 13
 	Probe(parentID string, runConfig *container.Config) (string, error)
14 14
 }
15 15
 
16
+type resetFunc func(context.Context) (builder.ImageCache, error)
17
+
16 18
 type imageProber struct {
17 19
 	cache       builder.ImageCache
18
-	reset       func() builder.ImageCache
20
+	reset       resetFunc
19 21
 	cacheBusted bool
20 22
 }
21 23
 
22
-func newImageProber(cacheBuilder builder.ImageCacheBuilder, cacheFrom []string, noCache bool) ImageProber {
24
+func newImageProber(ctx context.Context, cacheBuilder builder.ImageCacheBuilder, cacheFrom []string, noCache bool) (ImageProber, error) {
23 25
 	if noCache {
24
-		return &nopProber{}
26
+		return &nopProber{}, nil
27
+	}
28
+
29
+	reset := func(ctx context.Context) (builder.ImageCache, error) {
30
+		return cacheBuilder.MakeImageCache(ctx, cacheFrom)
25 31
 	}
26 32
 
27
-	reset := func() builder.ImageCache {
28
-		return cacheBuilder.MakeImageCache(cacheFrom)
33
+	cache, err := reset(ctx)
34
+	if err != nil {
35
+		return nil, err
29 36
 	}
30
-	return &imageProber{cache: reset(), reset: reset}
37
+	return &imageProber{cache: cache, reset: reset}, nil
31 38
 }
32 39
 
33
-func (c *imageProber) Reset() {
34
-	c.cache = c.reset()
40
+func (c *imageProber) Reset(ctx context.Context) error {
41
+	newCache, err := c.reset(ctx)
42
+	if err != nil {
43
+		return err
44
+	}
45
+	c.cache = newCache
35 46
 	c.cacheBusted = false
47
+	return nil
36 48
 }
37 49
 
38 50
 // Probe checks if cache match can be found for current build instruction.
... ...
@@ -56,7 +70,9 @@ func (c *imageProber) Probe(parentID string, runConfig *container.Config) (strin
56 56
 
57 57
 type nopProber struct{}
58 58
 
59
-func (c *nopProber) Reset() {}
59
+func (c *nopProber) Reset(ctx context.Context) error {
60
+	return nil
61
+}
60 62
 
61 63
 func (c *nopProber) Probe(_ string, _ *container.Config) (string, error) {
62 64
 	return "", nil
... ...
@@ -4,6 +4,7 @@ package dockerfile // import "github.com/docker/docker/builder/dockerfile"
4 4
 // non-contiguous functionality. Please read the comments.
5 5
 
6 6
 import (
7
+	"context"
7 8
 	"crypto/sha256"
8 9
 	"encoding/hex"
9 10
 	"fmt"
... ...
@@ -27,7 +28,7 @@ func (b *Builder) getArchiver() *archive.Archiver {
27 27
 	return chrootarchive.NewArchiver(b.idMapping)
28 28
 }
29 29
 
30
-func (b *Builder) commit(dispatchState *dispatchState, comment string) error {
30
+func (b *Builder) commit(ctx context.Context, dispatchState *dispatchState, comment string) error {
31 31
 	if b.disableCommit {
32 32
 		return nil
33 33
 	}
... ...
@@ -36,7 +37,7 @@ func (b *Builder) commit(dispatchState *dispatchState, comment string) error {
36 36
 	}
37 37
 
38 38
 	runConfigWithCommentCmd := copyRunConfig(dispatchState.runConfig, withCmdComment(comment, dispatchState.operatingSystem))
39
-	id, err := b.probeAndCreate(dispatchState, runConfigWithCommentCmd)
39
+	id, err := b.probeAndCreate(ctx, dispatchState, runConfigWithCommentCmd)
40 40
 	if err != nil || id == "" {
41 41
 		return err
42 42
 	}
... ...
@@ -107,7 +108,7 @@ func (b *Builder) exportImage(state *dispatchState, layer builder.RWLayer, paren
107 107
 	return nil
108 108
 }
109 109
 
110
-func (b *Builder) performCopy(req dispatchRequest, inst copyInstruction) error {
110
+func (b *Builder) performCopy(ctx context.Context, req dispatchRequest, inst copyInstruction) error {
111 111
 	state := req.state
112 112
 	srcHash := getSourceHashFromInfos(inst.infos)
113 113
 
... ...
@@ -147,7 +148,7 @@ func (b *Builder) performCopy(req dispatchRequest, inst copyInstruction) error {
147 147
 	// translated (if necessary because of user namespaces), and replace
148 148
 	// the root pair with the chown pair for copy operations
149 149
 	if inst.chownStr != "" {
150
-		identity, err = parseChownFlag(b, state, inst.chownStr, destInfo.root, b.idMapping)
150
+		identity, err = parseChownFlag(ctx, b, state, inst.chownStr, destInfo.root, b.idMapping)
151 151
 		if err != nil {
152 152
 			if b.options.Platform != "windows" {
153 153
 				return errors.Wrapf(err, "unable to convert uid/gid chown string to host mapping")
... ...
@@ -331,18 +332,18 @@ func (b *Builder) probeCache(dispatchState *dispatchState, runConfig *container.
331 331
 
332 332
 var defaultLogConfig = container.LogConfig{Type: "none"}
333 333
 
334
-func (b *Builder) probeAndCreate(dispatchState *dispatchState, runConfig *container.Config) (string, error) {
334
+func (b *Builder) probeAndCreate(ctx context.Context, dispatchState *dispatchState, runConfig *container.Config) (string, error) {
335 335
 	if hit, err := b.probeCache(dispatchState, runConfig); err != nil || hit {
336 336
 		return "", err
337 337
 	}
338
-	return b.create(runConfig)
338
+	return b.create(ctx, runConfig)
339 339
 }
340 340
 
341
-func (b *Builder) create(runConfig *container.Config) (string, error) {
341
+func (b *Builder) create(ctx context.Context, runConfig *container.Config) (string, error) {
342 342
 	logrus.Debugf("[BUILDER] Command to be executed: %v", runConfig.Cmd)
343 343
 
344 344
 	hostConfig := hostConfigFromOptions(b.options)
345
-	container, err := b.containerManager.Create(runConfig, hostConfig)
345
+	container, err := b.containerManager.Create(ctx, runConfig, hostConfig)
346 346
 	if err != nil {
347 347
 		return "", err
348 348
 	}
... ...
@@ -1,6 +1,7 @@
1 1
 package dockerfile // import "github.com/docker/docker/builder/dockerfile"
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"path/filepath"
5 6
 	"strconv"
6 7
 	"strings"
... ...
@@ -11,7 +12,7 @@ import (
11 11
 	"github.com/pkg/errors"
12 12
 )
13 13
 
14
-func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
14
+func parseChownFlag(ctx context.Context, builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
15 15
 	var userStr, grpStr string
16 16
 	parts := strings.Split(chown, ":")
17 17
 	if len(parts) > 2 {
... ...
@@ -1,6 +1,7 @@
1 1
 package dockerfile // import "github.com/docker/docker/builder/dockerfile"
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"os"
5 6
 	"path/filepath"
6 7
 	"testing"
... ...
@@ -115,7 +116,7 @@ othergrp:x:6666:
115 115
 		},
116 116
 	} {
117 117
 		t.Run(testcase.name, func(t *testing.T) {
118
-			idPair, err := parseChownFlag(testcase.builder, testcase.state, testcase.chownStr, contextDir, testcase.idMapping)
118
+			idPair, err := parseChownFlag(context.TODO(), testcase.builder, testcase.state, testcase.chownStr, contextDir, testcase.idMapping)
119 119
 			assert.NilError(t, err, "Failed to parse chown flag: %q", testcase.chownStr)
120 120
 			assert.Check(t, is.DeepEqual(testcase.expected, idPair), "chown flag mapping failure")
121 121
 		})
... ...
@@ -156,7 +157,7 @@ othergrp:x:6666:
156 156
 		},
157 157
 	} {
158 158
 		t.Run(testcase.name, func(t *testing.T) {
159
-			_, err := parseChownFlag(testcase.builder, testcase.state, testcase.chownStr, contextDir, testcase.idMapping)
159
+			_, err := parseChownFlag(context.TODO(), testcase.builder, testcase.state, testcase.chownStr, contextDir, testcase.idMapping)
160 160
 			assert.Check(t, is.Error(err, testcase.descr), "Expected error string doesn't match")
161 161
 		})
162 162
 	}
... ...
@@ -2,6 +2,7 @@ package dockerfile // import "github.com/docker/docker/builder/dockerfile"
2 2
 
3 3
 import (
4 4
 	"bytes"
5
+	"context"
5 6
 	"os"
6 7
 	"path/filepath"
7 8
 	"strings"
... ...
@@ -14,15 +15,15 @@ import (
14 14
 	"golang.org/x/sys/windows"
15 15
 )
16 16
 
17
-func parseChownFlag(builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
17
+func parseChownFlag(ctx context.Context, builder *Builder, state *dispatchState, chown, ctrRootPath string, identityMapping idtools.IdentityMapping) (idtools.Identity, error) {
18 18
 	if builder.options.Platform == "windows" {
19
-		return getAccountIdentity(builder, chown, ctrRootPath, state)
19
+		return getAccountIdentity(ctx, builder, chown, ctrRootPath, state)
20 20
 	}
21 21
 
22 22
 	return identityMapping.RootPair(), nil
23 23
 }
24 24
 
25
-func getAccountIdentity(builder *Builder, accountName string, ctrRootPath string, state *dispatchState) (idtools.Identity, error) {
25
+func getAccountIdentity(ctx context.Context, builder *Builder, accountName string, ctrRootPath string, state *dispatchState) (idtools.Identity, error) {
26 26
 	// If this is potentially a string SID then attempt to convert it to verify
27 27
 	// this, otherwise continue looking for the account.
28 28
 	if strings.HasPrefix(accountName, "S-") || strings.HasPrefix(accountName, "s-") {
... ...
@@ -51,10 +52,10 @@ func getAccountIdentity(builder *Builder, accountName string, ctrRootPath string
51 51
 
52 52
 	// All other lookups failed, so therefore determine if the account in
53 53
 	// question exists in the container and if so, obtain its SID.
54
-	return lookupNTAccount(builder, accountName, state)
54
+	return lookupNTAccount(ctx, builder, accountName, state)
55 55
 }
56 56
 
57
-func lookupNTAccount(builder *Builder, accountName string, state *dispatchState) (idtools.Identity, error) {
57
+func lookupNTAccount(ctx context.Context, builder *Builder, accountName string, state *dispatchState) (idtools.Identity, error) {
58 58
 
59 59
 	source, _ := filepath.Split(os.Args[0])
60 60
 
... ...
@@ -81,7 +82,7 @@ func lookupNTAccount(builder *Builder, accountName string, state *dispatchState)
81 81
 	},
82 82
 	}
83 83
 
84
-	container, err := builder.containerManager.Create(runConfig, hostConfig)
84
+	container, err := builder.containerManager.Create(ctx, runConfig, hostConfig)
85 85
 	if err != nil {
86 86
 		return idtools.Identity{}, err
87 87
 	}
... ...
@@ -27,7 +27,7 @@ func (m *MockBackend) ContainerAttachRaw(cID string, stdin io.ReadCloser, stdout
27 27
 	return nil
28 28
 }
29 29
 
30
-func (m *MockBackend) ContainerCreateIgnoreImagesArgsEscaped(config types.ContainerCreateConfig) (container.CreateResponse, error) {
30
+func (m *MockBackend) ContainerCreateIgnoreImagesArgsEscaped(ctx context.Context, config types.ContainerCreateConfig) (container.CreateResponse, error) {
31 31
 	if m.containerCreateFunc != nil {
32 32
 		return m.containerCreateFunc(config)
33 33
 	}
... ...
@@ -49,7 +49,7 @@ func (m *MockBackend) ContainerKill(containerID string, sig string) error {
49 49
 	return nil
50 50
 }
51 51
 
52
-func (m *MockBackend) ContainerStart(containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error {
52
+func (m *MockBackend) ContainerStart(ctx context.Context, containerID string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error {
53 53
 	return nil
54 54
 }
55 55
 
... ...
@@ -73,11 +73,11 @@ func (m *MockBackend) GetImageAndReleasableLayer(ctx context.Context, refOrID st
73 73
 	return &mockImage{id: "theid"}, &mockLayer{}, nil
74 74
 }
75 75
 
76
-func (m *MockBackend) MakeImageCache(cacheFrom []string) builder.ImageCache {
76
+func (m *MockBackend) MakeImageCache(ctx context.Context, cacheFrom []string) (builder.ImageCache, error) {
77 77
 	if m.makeImageCacheFunc != nil {
78
-		return m.makeImageCacheFunc(cacheFrom)
78
+		return m.makeImageCacheFunc(cacheFrom), nil
79 79
 	}
80
-	return nil
80
+	return nil, nil
81 81
 }
82 82
 
83 83
 func (m *MockBackend) CreateImage(config []byte, parent string) (builder.Image, error) {
... ...
@@ -252,7 +252,7 @@ func (cli *DaemonCli) start(opts *daemonOptions) (err error) {
252 252
 
253 253
 	// notify systemd that we're shutting down
254 254
 	notifyStopping()
255
-	shutdownDaemon(d)
255
+	shutdownDaemon(ctx, d)
256 256
 
257 257
 	// Stop notification processing and any background processes
258 258
 	cancel()
... ...
@@ -359,11 +359,11 @@ func (cli *DaemonCli) stop() {
359 359
 // shutdownDaemon just wraps daemon.Shutdown() to handle a timeout in case
360 360
 // d.Shutdown() is waiting too long to kill container or worst it's
361 361
 // blocked there
362
-func shutdownDaemon(d *daemon.Daemon) {
362
+func shutdownDaemon(ctx context.Context, d *daemon.Daemon) {
363 363
 	shutdownTimeout := d.ShutdownTimeout()
364 364
 	ch := make(chan struct{})
365 365
 	go func() {
366
-		d.Shutdown()
366
+		d.Shutdown(ctx)
367 367
 		close(ch)
368 368
 	}()
369 369
 	if shutdownTimeout < 0 {
... ...
@@ -37,8 +37,8 @@ type Backend interface {
37 37
 	FindNetwork(idName string) (libnetwork.Network, error)
38 38
 	SetupIngress(clustertypes.NetworkCreateRequest, string) (<-chan struct{}, error)
39 39
 	ReleaseIngress() (<-chan struct{}, error)
40
-	CreateManagedContainer(config types.ContainerCreateConfig) (container.CreateResponse, error)
41
-	ContainerStart(name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
40
+	CreateManagedContainer(ctx context.Context, config types.ContainerCreateConfig) (container.CreateResponse, error)
41
+	ContainerStart(ctx context.Context, name string, hostConfig *container.HostConfig, checkpoint string, checkpointDir string) error
42 42
 	ContainerStop(ctx context.Context, name string, config container.StopOptions) error
43 43
 	ContainerLogs(ctx context.Context, name string, config *types.ContainerLogsOptions) (msgs <-chan *backend.LogMessage, tty bool, err error)
44 44
 	ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
... ...
@@ -53,7 +53,7 @@ type Backend interface {
53 53
 	SetContainerSecretReferences(name string, refs []*swarm.SecretReference) error
54 54
 	SetContainerConfigReferences(name string, refs []*swarm.ConfigReference) error
55 55
 	SystemInfo() *types.Info
56
-	Containers(config *types.ContainerListOptions) ([]*types.Container, error)
56
+	Containers(ctx context.Context, config *types.ContainerListOptions) ([]*types.Container, error)
57 57
 	SetNetworkBootstrapKeys([]*networktypes.EncryptionKey) error
58 58
 	DaemonJoinsCluster(provider cluster.Provider)
59 59
 	DaemonLeavesCluster()
... ...
@@ -290,7 +290,7 @@ func (c *containerAdapter) waitForDetach(ctx context.Context) error {
290 290
 func (c *containerAdapter) create(ctx context.Context) error {
291 291
 	var cr containertypes.CreateResponse
292 292
 	var err error
293
-	if cr, err = c.backend.CreateManagedContainer(types.ContainerCreateConfig{
293
+	if cr, err = c.backend.CreateManagedContainer(ctx, types.ContainerCreateConfig{
294 294
 		Name:       c.container.name(),
295 295
 		Config:     c.container.config(),
296 296
 		HostConfig: c.container.hostConfig(c.dependencies.Volumes()),
... ...
@@ -357,7 +357,7 @@ func (c *containerAdapter) start(ctx context.Context) error {
357 357
 		return err
358 358
 	}
359 359
 
360
-	return c.backend.ContainerStart(c.container.name(), nil, "", "")
360
+	return c.backend.ContainerStart(ctx, c.container.name(), nil, "", "")
361 361
 }
362 362
 
363 363
 func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, error) {
... ...
@@ -356,7 +356,7 @@ func (c *Cluster) UnlockSwarm(req types.UnlockRequest) error {
356 356
 }
357 357
 
358 358
 // Leave shuts down Cluster and removes current state.
359
-func (c *Cluster) Leave(force bool) error {
359
+func (c *Cluster) Leave(ctx context.Context, force bool) error {
360 360
 	c.controlMutex.Lock()
361 361
 	defer c.controlMutex.Unlock()
362 362
 
... ...
@@ -408,7 +408,7 @@ func (c *Cluster) Leave(force bool) error {
408 408
 	c.mu.Unlock()
409 409
 
410 410
 	if nodeID := state.NodeID(); nodeID != "" {
411
-		nodeContainers, err := c.listContainerForNode(nodeID)
411
+		nodeContainers, err := c.listContainerForNode(ctx, nodeID)
412 412
 		if err != nil {
413 413
 			return err
414 414
 		}
... ...
@@ -604,11 +604,11 @@ func initClusterSpec(node *swarmnode.Node, spec types.Spec) error {
604 604
 	return ctx.Err()
605 605
 }
606 606
 
607
-func (c *Cluster) listContainerForNode(nodeID string) ([]string, error) {
607
+func (c *Cluster) listContainerForNode(ctx context.Context, nodeID string) ([]string, error) {
608 608
 	var ids []string
609 609
 	filters := filters.NewArgs()
610 610
 	filters.Add("label", fmt.Sprintf("com.docker.swarm.node.id=%s", nodeID))
611
-	containers, err := c.config.Backend.Containers(&apitypes.ContainerListOptions{
611
+	containers, err := c.config.Backend.Containers(ctx, &apitypes.ContainerListOptions{
612 612
 		Filters: filters,
613 613
 	})
614 614
 	if err != nil {
... ...
@@ -1,6 +1,7 @@
1 1
 package daemon // import "github.com/docker/docker/daemon"
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"fmt"
5 6
 	"runtime"
6 7
 	"strings"
... ...
@@ -116,7 +117,7 @@ func merge(userConf, imageConf *containertypes.Config) error {
116 116
 // CreateImageFromContainer creates a new image from a container. The container
117 117
 // config will be updated by applying the change set to the custom config, then
118 118
 // applying that config over the existing container config.
119
-func (daemon *Daemon) CreateImageFromContainer(name string, c *backend.CreateImageConfig) (string, error) {
119
+func (daemon *Daemon) CreateImageFromContainer(ctx context.Context, name string, c *backend.CreateImageConfig) (string, error) {
120 120
 	start := time.Now()
121 121
 	container, err := daemon.GetContainer(name)
122 122
 	if err != nil {
... ...
@@ -146,7 +147,7 @@ func (daemon *Daemon) CreateImageFromContainer(name string, c *backend.CreateIma
146 146
 	if c.Config == nil {
147 147
 		c.Config = container.Config
148 148
 	}
149
-	newConfig, err := dockerfile.BuildFromConfig(c.Config, c.Changes, container.OS)
149
+	newConfig, err := dockerfile.BuildFromConfig(ctx, c.Config, c.Changes, container.OS)
150 150
 	if err != nil {
151 151
 		return "", err
152 152
 	}
... ...
@@ -1,10 +1,12 @@
1 1
 package containerd
2 2
 
3 3
 import (
4
+	"context"
5
+
4 6
 	"github.com/docker/docker/builder"
5 7
 )
6 8
 
7 9
 // MakeImageCache creates a stateful image cache.
8
-func (i *ImageService) MakeImageCache(cacheFrom []string) builder.ImageCache {
10
+func (i *ImageService) MakeImageCache(ctx context.Context, cacheFrom []string) (builder.ImageCache, error) {
9 11
 	panic("not implemented")
10 12
 }
... ...
@@ -1,6 +1,7 @@
1 1
 package containerd
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"errors"
5 6
 	"io"
6 7
 
... ...
@@ -12,6 +13,6 @@ import (
12 12
 // inConfig (if src is "-"), or from a URI specified in src. Progress output is
13 13
 // written to outStream. Repository and tag names can optionally be given in
14 14
 // the repo and tag arguments, respectively.
15
-func (i *ImageService) ImportImage(src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
15
+func (i *ImageService) ImportImage(ctx context.Context, src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
16 16
 	return errdefs.NotImplemented(errors.New("not implemented"))
17 17
 }
... ...
@@ -33,31 +33,30 @@ type createOpts struct {
33 33
 }
34 34
 
35 35
 // CreateManagedContainer creates a container that is managed by a Service
36
-func (daemon *Daemon) CreateManagedContainer(params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
37
-	return daemon.containerCreate(createOpts{
36
+func (daemon *Daemon) CreateManagedContainer(ctx context.Context, params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
37
+	return daemon.containerCreate(ctx, createOpts{
38 38
 		params:  params,
39 39
 		managed: true,
40 40
 	})
41 41
 }
42 42
 
43 43
 // ContainerCreate creates a regular container
44
-func (daemon *Daemon) ContainerCreate(params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
45
-	return daemon.containerCreate(createOpts{
44
+func (daemon *Daemon) ContainerCreate(ctx context.Context, params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
45
+	return daemon.containerCreate(ctx, createOpts{
46 46
 		params: params,
47 47
 	})
48 48
 }
49 49
 
50 50
 // ContainerCreateIgnoreImagesArgsEscaped creates a regular container. This is called from the builder RUN case
51 51
 // and ensures that we do not take the images ArgsEscaped
52
-func (daemon *Daemon) ContainerCreateIgnoreImagesArgsEscaped(params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
53
-	return daemon.containerCreate(createOpts{
52
+func (daemon *Daemon) ContainerCreateIgnoreImagesArgsEscaped(ctx context.Context, params types.ContainerCreateConfig) (containertypes.CreateResponse, error) {
53
+	return daemon.containerCreate(ctx, createOpts{
54 54
 		params:                  params,
55 55
 		ignoreImagesArgsEscaped: true,
56 56
 	})
57 57
 }
58 58
 
59
-func (daemon *Daemon) containerCreate(opts createOpts) (containertypes.CreateResponse, error) {
60
-	ctx := context.TODO()
59
+func (daemon *Daemon) containerCreate(ctx context.Context, opts createOpts) (containertypes.CreateResponse, error) {
61 60
 	start := time.Now()
62 61
 	if opts.params.Config == nil {
63 62
 		return containertypes.CreateResponse{}, errdefs.InvalidParameter(errors.New("Config cannot be empty in order to create a container"))
... ...
@@ -100,7 +99,7 @@ func (daemon *Daemon) containerCreate(opts createOpts) (containertypes.CreateRes
100 100
 		return containertypes.CreateResponse{Warnings: warnings}, errdefs.InvalidParameter(err)
101 101
 	}
102 102
 
103
-	ctr, err := daemon.create(opts)
103
+	ctr, err := daemon.create(ctx, opts)
104 104
 	if err != nil {
105 105
 		return containertypes.CreateResponse{Warnings: warnings}, err
106 106
 	}
... ...
@@ -114,8 +113,7 @@ func (daemon *Daemon) containerCreate(opts createOpts) (containertypes.CreateRes
114 114
 }
115 115
 
116 116
 // Create creates a new container from the given configuration with a given name.
117
-func (daemon *Daemon) create(opts createOpts) (retC *container.Container, retErr error) {
118
-	ctx := context.TODO()
117
+func (daemon *Daemon) create(ctx context.Context, opts createOpts) (retC *container.Container, retErr error) {
119 118
 	var (
120 119
 		ctr   *container.Container
121 120
 		img   *image.Image
... ...
@@ -526,7 +526,7 @@ func (daemon *Daemon) restore() error {
526 526
 			if err := daemon.prepareMountPoints(c); err != nil {
527 527
 				log.WithError(err).Error("failed to prepare mount points for container")
528 528
 			}
529
-			if err := daemon.containerStart(c, "", "", true); err != nil {
529
+			if err := daemon.containerStart(context.Background(), c, "", "", true); err != nil {
530 530
 				log.WithError(err).Error("failed to start container")
531 531
 			}
532 532
 			close(chNotify)
... ...
@@ -617,7 +617,7 @@ func (daemon *Daemon) RestartSwarmContainers() {
617 617
 						return
618 618
 					}
619 619
 
620
-					if err := daemon.containerStart(c, "", "", true); err != nil {
620
+					if err := daemon.containerStart(ctx, c, "", "", true); err != nil {
621 621
 						logrus.WithField("container", c.ID).WithError(err).Error("failed to start swarm container")
622 622
 					}
623 623
 
... ...
@@ -775,7 +775,8 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
775 775
 	// initialization
776 776
 	defer func() {
777 777
 		if err != nil {
778
-			if err := d.Shutdown(); err != nil {
778
+			// Use a fresh context here. Passed context could be cancelled.
779
+			if err := d.Shutdown(context.Background()); err != nil {
779 780
 				logrus.Error(err)
780 781
 			}
781 782
 		}
... ...
@@ -1193,17 +1194,17 @@ func (daemon *Daemon) ShutdownTimeout() int {
1193 1193
 }
1194 1194
 
1195 1195
 // Shutdown stops the daemon.
1196
-func (daemon *Daemon) Shutdown() error {
1196
+func (daemon *Daemon) Shutdown(ctx context.Context) error {
1197 1197
 	daemon.shutdown = true
1198 1198
 	// Keep mounts and networking running on daemon shutdown if
1199 1199
 	// we are to keep containers running and restore them.
1200 1200
 
1201 1201
 	if daemon.configStore.LiveRestoreEnabled && daemon.containers != nil {
1202 1202
 		// check if there are any running containers, if none we should do some cleanup
1203
-		if ls, err := daemon.Containers(&types.ContainerListOptions{}); len(ls) != 0 || err != nil {
1203
+		if ls, err := daemon.Containers(ctx, &types.ContainerListOptions{}); len(ls) != 0 || err != nil {
1204 1204
 			// metrics plugins still need some cleanup
1205 1205
 			daemon.cleanupMetricsPlugins()
1206
-			return nil
1206
+			return err
1207 1207
 		}
1208 1208
 	}
1209 1209
 
... ...
@@ -14,7 +14,7 @@ import (
14 14
 func (daemon *Daemon) ContainerDiskUsage(ctx context.Context) ([]*types.Container, error) {
15 15
 	ch := daemon.usage.DoChan("ContainerDiskUsage", func() (interface{}, error) {
16 16
 		// Retrieve container list
17
-		containers, err := daemon.Containers(&types.ContainerListOptions{
17
+		containers, err := daemon.Containers(context.TODO(), &types.ContainerListOptions{
18 18
 			Size: true,
19 19
 			All:  true,
20 20
 		})
... ...
@@ -37,7 +37,7 @@ type ImageService interface {
37 37
 	CountImages() int
38 38
 	ImageDiskUsage(ctx context.Context) ([]*types.ImageSummary, error)
39 39
 	ImagesPrune(ctx context.Context, pruneFilters filters.Args) (*types.ImagesPruneReport, error)
40
-	ImportImage(src string, repository string, platform *v1.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
40
+	ImportImage(ctx context.Context, src string, repository string, platform *v1.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error
41 41
 	TagImage(imageName, repository, tag string) (string, error)
42 42
 	TagImageWithReference(imageID image.ID, newTag reference.Named) error
43 43
 	GetImage(ctx context.Context, refOrID string, options imagetype.GetImageOpts) (*image.Image, error)
... ...
@@ -62,7 +62,7 @@ type ImageService interface {
62 62
 
63 63
 	// Build
64 64
 
65
-	MakeImageCache(sourceRefs []string) builder.ImageCache
65
+	MakeImageCache(ctx context.Context, cacheFrom []string) (builder.ImageCache, error)
66 66
 	CommitBuildStep(c backend.CommitConfig) (image.ID, error)
67 67
 
68 68
 	// Other
... ...
@@ -6,14 +6,14 @@ import (
6 6
 	imagetypes "github.com/docker/docker/api/types/image"
7 7
 	"github.com/docker/docker/builder"
8 8
 	"github.com/docker/docker/image/cache"
9
+	"github.com/pkg/errors"
9 10
 	"github.com/sirupsen/logrus"
10 11
 )
11 12
 
12 13
 // MakeImageCache creates a stateful image cache.
13
-func (i *ImageService) MakeImageCache(sourceRefs []string) builder.ImageCache {
14
-	ctx := context.TODO()
14
+func (i *ImageService) MakeImageCache(ctx context.Context, sourceRefs []string) (builder.ImageCache, error) {
15 15
 	if len(sourceRefs) == 0 {
16
-		return cache.NewLocal(i.imageStore)
16
+		return cache.NewLocal(i.imageStore), nil
17 17
 	}
18 18
 
19 19
 	cache := cache.New(i.imageStore)
... ...
@@ -21,11 +21,14 @@ func (i *ImageService) MakeImageCache(sourceRefs []string) builder.ImageCache {
21 21
 	for _, ref := range sourceRefs {
22 22
 		img, err := i.GetImage(ctx, ref, imagetypes.GetImageOpts{})
23 23
 		if err != nil {
24
+			if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
25
+				return nil, err
26
+			}
24 27
 			logrus.Warnf("Could not look up %s for cache resolution, skipping: %+v", ref, err)
25 28
 			continue
26 29
 		}
27 30
 		cache.Populate(img)
28 31
 	}
29 32
 
30
-	return cache
33
+	return cache, nil
31 34
 }
... ...
@@ -1,6 +1,7 @@
1 1
 package images // import "github.com/docker/docker/daemon/images"
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"encoding/json"
5 6
 	"io"
6 7
 	"net/http"
... ...
@@ -29,7 +30,7 @@ import (
29 29
 // inConfig (if src is "-"), or from a URI specified in src. Progress output is
30 30
 // written to outStream. Repository and tag names can optionally be given in
31 31
 // the repo and tag arguments, respectively.
32
-func (i *ImageService) ImportImage(src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
32
+func (i *ImageService) ImportImage(ctx context.Context, src string, repository string, platform *specs.Platform, tag string, msg string, inConfig io.ReadCloser, outStream io.Writer, changes []string) error {
33 33
 	var (
34 34
 		rc     io.ReadCloser
35 35
 		resp   *http.Response
... ...
@@ -62,7 +63,7 @@ func (i *ImageService) ImportImage(src string, repository string, platform *spec
62 62
 	if !system.IsOSSupported(platform.OS) {
63 63
 		return errdefs.InvalidParameter(system.ErrNotSupportedOperatingSystem)
64 64
 	}
65
-	config, err := dockerfile.BuildFromConfig(&container.Config{}, changes, platform.OS)
65
+	config, err := dockerfile.BuildFromConfig(ctx, &container.Config{}, changes, platform.OS)
66 66
 	if err != nil {
67 67
 		return err
68 68
 	}
... ...
@@ -42,7 +42,7 @@ type iterationAction int
42 42
 
43 43
 // containerReducer represents a reducer for a container.
44 44
 // Returns the object to serialize by the api.
45
-type containerReducer func(*container.Snapshot, *listContext) (*types.Container, error)
45
+type containerReducer func(context.Context, *container.Snapshot, *listContext) (*types.Container, error)
46 46
 
47 47
 const (
48 48
 	// includeContainer is the action to include a container in the reducer.
... ...
@@ -106,8 +106,8 @@ func (r byCreatedDescending) Less(i, j int) bool {
106 106
 }
107 107
 
108 108
 // Containers returns the list of containers to show given the user's filtering.
109
-func (daemon *Daemon) Containers(config *types.ContainerListOptions) ([]*types.Container, error) {
110
-	return daemon.reduceContainers(config, daemon.refreshImage)
109
+func (daemon *Daemon) Containers(ctx context.Context, config *types.ContainerListOptions) ([]*types.Container, error) {
110
+	return daemon.reduceContainers(ctx, config, daemon.refreshImage)
111 111
 }
112 112
 
113 113
 func (daemon *Daemon) filterByNameIDMatches(view *container.View, filter *listContext) ([]container.Snapshot, error) {
... ...
@@ -177,7 +177,7 @@ func (daemon *Daemon) filterByNameIDMatches(view *container.View, filter *listCo
177 177
 }
178 178
 
179 179
 // reduceContainers parses the user's filtering options and generates the list of containers to return based on a reducer.
180
-func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reducer containerReducer) ([]*types.Container, error) {
180
+func (daemon *Daemon) reduceContainers(ctx context.Context, config *types.ContainerListOptions, reducer containerReducer) ([]*types.Container, error) {
181 181
 	if err := config.Filters.Validate(acceptedPsFilterTags); err != nil {
182 182
 		return nil, err
183 183
 	}
... ...
@@ -187,7 +187,7 @@ func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reduc
187 187
 		containers = []*types.Container{}
188 188
 	)
189 189
 
190
-	filter, err := daemon.foldFilter(view, config)
190
+	filter, err := daemon.foldFilter(ctx, view, config)
191 191
 	if err != nil {
192 192
 		return nil, err
193 193
 	}
... ...
@@ -201,7 +201,7 @@ func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reduc
201 201
 	}
202 202
 
203 203
 	for i := range containerList {
204
-		t, err := daemon.reducePsContainer(&containerList[i], filter, reducer)
204
+		t, err := daemon.reducePsContainer(ctx, &containerList[i], filter, reducer)
205 205
 		if err != nil {
206 206
 			if err != errStopIteration {
207 207
 				return nil, err
... ...
@@ -218,7 +218,7 @@ func (daemon *Daemon) reduceContainers(config *types.ContainerListOptions, reduc
218 218
 }
219 219
 
220 220
 // reducePsContainer is the basic representation for a container as expected by the ps command.
221
-func (daemon *Daemon) reducePsContainer(container *container.Snapshot, filter *listContext, reducer containerReducer) (*types.Container, error) {
221
+func (daemon *Daemon) reducePsContainer(ctx context.Context, container *container.Snapshot, filter *listContext, reducer containerReducer) (*types.Container, error) {
222 222
 	// filter containers to return
223 223
 	switch includeContainerInList(container, filter) {
224 224
 	case excludeContainer:
... ...
@@ -228,7 +228,7 @@ func (daemon *Daemon) reducePsContainer(container *container.Snapshot, filter *l
228 228
 	}
229 229
 
230 230
 	// transform internal container struct into api structs
231
-	newC, err := reducer(container, filter)
231
+	newC, err := reducer(ctx, container, filter)
232 232
 	if err != nil {
233 233
 		return nil, err
234 234
 	}
... ...
@@ -243,8 +243,7 @@ func (daemon *Daemon) reducePsContainer(container *container.Snapshot, filter *l
243 243
 }
244 244
 
245 245
 // foldFilter generates the container filter based on the user's filtering options.
246
-func (daemon *Daemon) foldFilter(view *container.View, config *types.ContainerListOptions) (*listContext, error) {
247
-	ctx := context.TODO()
246
+func (daemon *Daemon) foldFilter(ctx context.Context, view *container.View, config *types.ContainerListOptions) (*listContext, error) {
248 247
 	psFilters := config.Filters
249 248
 
250 249
 	var filtExited []int
... ...
@@ -580,8 +579,7 @@ func includeContainerInList(container *container.Snapshot, filter *listContext)
580 580
 }
581 581
 
582 582
 // refreshImage checks if the Image ref still points to the correct ID, and updates the ref to the actual ID when it doesn't
583
-func (daemon *Daemon) refreshImage(s *container.Snapshot, filter *listContext) (*types.Container, error) {
584
-	ctx := context.TODO()
583
+func (daemon *Daemon) refreshImage(ctx context.Context, s *container.Snapshot, filter *listContext) (*types.Container, error) {
585 584
 	c := s.Container
586 585
 	tmpImage := s.Image // keep the original ref if still valid (hasn't changed)
587 586
 	if tmpImage != s.ImageID {
... ...
@@ -1,6 +1,7 @@
1 1
 package daemon
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"os"
5 6
 	"path/filepath"
6 7
 	"testing"
... ...
@@ -88,7 +89,7 @@ func TestListInvalidFilter(t *testing.T) {
88 88
 
89 89
 	f := filters.NewArgs(filters.Arg("invalid", "foo"))
90 90
 
91
-	_, err = d.Containers(&types.ContainerListOptions{
91
+	_, err = d.Containers(context.Background(), &types.ContainerListOptions{
92 92
 		Filters: f,
93 93
 	})
94 94
 	assert.Assert(t, is.Error(err, "invalid filter 'invalid'"))
... ...
@@ -109,7 +110,7 @@ func TestNameFilter(t *testing.T) {
109 109
 
110 110
 	// moby/moby #37453 - ^ regex not working due to prefix slash
111 111
 	// not being stripped
112
-	containerList, err := d.Containers(&types.ContainerListOptions{
112
+	containerList, err := d.Containers(context.Background(), &types.ContainerListOptions{
113 113
 		Filters: filters.NewArgs(filters.Arg("name", "^a")),
114 114
 	})
115 115
 	assert.NilError(t, err)
... ...
@@ -118,7 +119,7 @@ func TestNameFilter(t *testing.T) {
118 118
 	assert.Assert(t, containerListContainsName(containerList, two.Name))
119 119
 
120 120
 	// Same as above but with slash prefix should produce the same result
121
-	containerListWithPrefix, err := d.Containers(&types.ContainerListOptions{
121
+	containerListWithPrefix, err := d.Containers(context.Background(), &types.ContainerListOptions{
122 122
 		Filters: filters.NewArgs(filters.Arg("name", "^/a")),
123 123
 	})
124 124
 	assert.NilError(t, err)
... ...
@@ -127,7 +128,7 @@ func TestNameFilter(t *testing.T) {
127 127
 	assert.Assert(t, containerListContainsName(containerListWithPrefix, two.Name))
128 128
 
129 129
 	// Same as above but make sure it works for exact names
130
-	containerList, err = d.Containers(&types.ContainerListOptions{
130
+	containerList, err = d.Containers(context.Background(), &types.ContainerListOptions{
131 131
 		Filters: filters.NewArgs(filters.Arg("name", "b1")),
132 132
 	})
133 133
 	assert.NilError(t, err)
... ...
@@ -135,7 +136,7 @@ func TestNameFilter(t *testing.T) {
135 135
 	assert.Assert(t, containerListContainsName(containerList, three.Name))
136 136
 
137 137
 	// Same as above but with slash prefix should produce the same result
138
-	containerListWithPrefix, err = d.Containers(&types.ContainerListOptions{
138
+	containerListWithPrefix, err = d.Containers(context.Background(), &types.ContainerListOptions{
139 139
 		Filters: filters.NewArgs(filters.Arg("name", "/b1")),
140 140
 	})
141 141
 	assert.NilError(t, err)
... ...
@@ -111,7 +111,7 @@ func (daemon *Daemon) handleContainerExit(c *container.Container, e *libcontaine
111 111
 				// But containerStart will use daemon.netController segment.
112 112
 				// So to avoid panic at startup process, here must wait util daemon restore done.
113 113
 				daemon.waitForStartupDone()
114
-				if err = daemon.containerStart(c, "", "", false); err != nil {
114
+				if err = daemon.containerStart(context.Background(), c, "", "", false); err != nil {
115 115
 					logrus.Debugf("failed to restart container: %+v", err)
116 116
 				}
117 117
 			}
... ...
@@ -1007,7 +1007,7 @@ func WithUser(c *container.Container) coci.SpecOpts {
1007 1007
 	}
1008 1008
 }
1009 1009
 
1010
-func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, err error) {
1010
+func (daemon *Daemon) createSpec(ctx context.Context, c *container.Container) (retSpec *specs.Spec, err error) {
1011 1011
 	var (
1012 1012
 		opts []coci.SpecOpts
1013 1013
 		s    = oci.DefaultSpec()
... ...
@@ -1052,7 +1052,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
1052 1052
 		snapshotKey = c.ID
1053 1053
 	}
1054 1054
 
1055
-	return &s, coci.ApplyOpts(context.Background(), nil, &containers.Container{
1055
+	return &s, coci.ApplyOpts(ctx, nil, &containers.Container{
1056 1056
 		ID:          c.ID,
1057 1057
 		Snapshotter: snapshotter,
1058 1058
 		SnapshotKey: snapshotKey,
... ...
@@ -1,6 +1,7 @@
1 1
 package daemon // import "github.com/docker/docker/daemon"
2 2
 
3 3
 import (
4
+	"context"
4 5
 	"os"
5 6
 	"path/filepath"
6 7
 	"testing"
... ...
@@ -73,7 +74,7 @@ func TestTmpfsDevShmNoDupMount(t *testing.T) {
73 73
 	d := setupFakeDaemon(t, c)
74 74
 	defer cleanupFakeContainer(c)
75 75
 
76
-	_, err := d.createSpec(c)
76
+	_, err := d.createSpec(context.TODO(), c)
77 77
 	assert.Check(t, err)
78 78
 }
79 79
 
... ...
@@ -92,7 +93,7 @@ func TestIpcPrivateVsReadonly(t *testing.T) {
92 92
 	d := setupFakeDaemon(t, c)
93 93
 	defer cleanupFakeContainer(c)
94 94
 
95
-	s, err := d.createSpec(c)
95
+	s, err := d.createSpec(context.TODO(), c)
96 96
 	assert.Check(t, err)
97 97
 
98 98
 	// Find the /dev/shm mount in ms, check it does not have ro
... ...
@@ -122,7 +123,7 @@ func TestSysctlOverride(t *testing.T) {
122 122
 	defer cleanupFakeContainer(c)
123 123
 
124 124
 	// Ensure that the implicit sysctl is set correctly.
125
-	s, err := d.createSpec(c)
125
+	s, err := d.createSpec(context.TODO(), c)
126 126
 	assert.NilError(t, err)
127 127
 	assert.Equal(t, s.Hostname, "foobar")
128 128
 	assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.Config.Domainname)
... ...
@@ -138,7 +139,7 @@ func TestSysctlOverride(t *testing.T) {
138 138
 	assert.Assert(t, c.HostConfig.Sysctls["kernel.domainname"] != c.Config.Domainname)
139 139
 	c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"] = "1024"
140 140
 
141
-	s, err = d.createSpec(c)
141
+	s, err = d.createSpec(context.TODO(), c)
142 142
 	assert.NilError(t, err)
143 143
 	assert.Equal(t, s.Hostname, "foobar")
144 144
 	assert.Equal(t, s.Linux.Sysctl["kernel.domainname"], c.HostConfig.Sysctls["kernel.domainname"])
... ...
@@ -146,7 +147,7 @@ func TestSysctlOverride(t *testing.T) {
146 146
 
147 147
 	// Ensure the ping_group_range is not set on a daemon with user-namespaces enabled
148 148
 	d.configStore.RemappedRoot = "dummy:dummy"
149
-	s, err = d.createSpec(c)
149
+	s, err = d.createSpec(context.TODO(), c)
150 150
 	assert.NilError(t, err)
151 151
 	_, ok := s.Linux.Sysctl["net.ipv4.ping_group_range"]
152 152
 	assert.Assert(t, !ok)
... ...
@@ -154,7 +155,7 @@ func TestSysctlOverride(t *testing.T) {
154 154
 	// Ensure the ping_group_range is set on a container in "host" userns mode
155 155
 	// on a daemon with user-namespaces enabled
156 156
 	c.HostConfig.UsernsMode = "host"
157
-	s, err = d.createSpec(c)
157
+	s, err = d.createSpec(context.TODO(), c)
158 158
 	assert.NilError(t, err)
159 159
 	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ping_group_range"], "0 2147483647")
160 160
 }
... ...
@@ -174,7 +175,7 @@ func TestSysctlOverrideHost(t *testing.T) {
174 174
 	defer cleanupFakeContainer(c)
175 175
 
176 176
 	// Ensure that the implicit sysctl is not set
177
-	s, err := d.createSpec(c)
177
+	s, err := d.createSpec(context.TODO(), c)
178 178
 	assert.NilError(t, err)
179 179
 	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], "")
180 180
 	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ping_group_range"], "")
... ...
@@ -182,7 +183,7 @@ func TestSysctlOverrideHost(t *testing.T) {
182 182
 	// Set an explicit sysctl.
183 183
 	c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"] = "1024"
184 184
 
185
-	s, err = d.createSpec(c)
185
+	s, err = d.createSpec(context.TODO(), c)
186 186
 	assert.NilError(t, err)
187 187
 	assert.Equal(t, s.Linux.Sysctl["net.ipv4.ip_unprivileged_port_start"], c.HostConfig.Sysctls["net.ipv4.ip_unprivileged_port_start"])
188 188
 }
... ...
@@ -26,8 +26,7 @@ const (
26 26
 	credentialSpecFileLocation     = "CredentialSpecs"
27 27
 )
28 28
 
29
-func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) {
30
-	ctx := context.TODO()
29
+func (daemon *Daemon) createSpec(ctx context.Context, c *container.Container) (*specs.Spec, error) {
31 30
 	img, err := daemon.imageService.GetImage(ctx, string(c.ImageID), imagetypes.GetImageOpts{})
32 31
 	if err != nil {
33 32
 		return nil, err
... ...
@@ -61,7 +61,7 @@ func (daemon *Daemon) containerRestart(ctx context.Context, container *container
61 61
 		}
62 62
 	}
63 63
 
64
-	if err := daemon.containerStart(container, "", "", true); err != nil {
64
+	if err := daemon.containerStart(ctx, container, "", "", true); err != nil {
65 65
 		return err
66 66
 	}
67 67
 
... ...
@@ -15,7 +15,7 @@ import (
15 15
 )
16 16
 
17 17
 // ContainerStart starts a container.
18
-func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.HostConfig, checkpoint string, checkpointDir string) error {
18
+func (daemon *Daemon) ContainerStart(ctx context.Context, name string, hostConfig *containertypes.HostConfig, checkpoint string, checkpointDir string) error {
19 19
 	if checkpoint != "" && !daemon.HasExperimental() {
20 20
 		return errdefs.InvalidParameter(errors.New("checkpoint is only supported in experimental mode"))
21 21
 	}
... ...
@@ -92,14 +92,14 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *containertypes.Hos
92 92
 			return errdefs.InvalidParameter(err)
93 93
 		}
94 94
 	}
95
-	return daemon.containerStart(ctr, checkpoint, checkpointDir, true)
95
+	return daemon.containerStart(ctx, ctr, checkpoint, checkpointDir, true)
96 96
 }
97 97
 
98 98
 // containerStart prepares the container to run by setting up everything the
99 99
 // container needs, such as storage and networking, as well as links
100 100
 // between containers. The container is left waiting for a signal to
101 101
 // begin running.
102
-func (daemon *Daemon) containerStart(container *container.Container, checkpoint string, checkpointDir string, resetRestartManager bool) (err error) {
102
+func (daemon *Daemon) containerStart(ctx context.Context, container *container.Container, checkpoint string, checkpointDir string, resetRestartManager bool) (err error) {
103 103
 	start := time.Now()
104 104
 	container.Lock()
105 105
 	defer container.Unlock()
... ...
@@ -151,7 +151,7 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
151 151
 		return err
152 152
 	}
153 153
 
154
-	spec, err := daemon.createSpec(container)
154
+	spec, err := daemon.createSpec(ctx, container)
155 155
 	if err != nil {
156 156
 		return errdefs.System(err)
157 157
 	}
... ...
@@ -177,8 +177,6 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
177 177
 		return err
178 178
 	}
179 179
 
180
-	ctx := context.TODO()
181
-
182 180
 	ctr, err := libcontainerd.ReplaceContainer(ctx, daemon.containerd, container.ID, spec, shim, createOptions)
183 181
 	if err != nil {
184 182
 		return translateContainerdStartErr(container.Path, container.SetExitCode, err)