Browse code

Rework usage of context.Context in api/client

Make better default usage on context.Context on the `api/client` package
to share the context (it is useless if not shared, which was the case
for a lot of commands).

Signed-off-by: Vincent Demeester <vincent@sbr.pm>

Vincent Demeester authored on 2016/05/21 22:57:57
Showing 28 changed files
... ...
@@ -27,7 +27,9 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
27 27
 
28 28
 	cmd.ParseFlags(args, true)
29 29
 
30
-	c, err := cli.client.ContainerInspect(context.Background(), cmd.Arg(0))
30
+	ctx := context.Background()
31
+
32
+	c, err := cli.client.ContainerInspect(ctx, cmd.Arg(0))
31 33
 	if err != nil {
32 34
 		return err
33 35
 	}
... ...
@@ -64,11 +66,11 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
64 64
 	}
65 65
 
66 66
 	if *proxy && !c.Config.Tty {
67
-		sigc := cli.forwardAllSignals(container)
67
+		sigc := cli.forwardAllSignals(ctx, container)
68 68
 		defer signal.StopCatch(sigc)
69 69
 	}
70 70
 
71
-	resp, errAttach := cli.client.ContainerAttach(context.Background(), container, options)
71
+	resp, errAttach := cli.client.ContainerAttach(ctx, container, options)
72 72
 	if errAttach != nil && errAttach != httputil.ErrPersistEOF {
73 73
 		// ContainerAttach returns an ErrPersistEOF (connection closed)
74 74
 		// means server met an error and put it in Hijacked connection
... ...
@@ -83,15 +85,15 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
83 83
 		// terminal, the only way to get the shell prompt to display for attaches 2+ is to artificially
84 84
 		// resize it, then go back to normal. Without this, every attach after the first will
85 85
 		// require the user to manually resize or hit enter.
86
-		cli.resizeTtyTo(cmd.Arg(0), height+1, width+1, false)
86
+		cli.resizeTtyTo(ctx, cmd.Arg(0), height+1, width+1, false)
87 87
 
88 88
 		// After the above resizing occurs, the call to monitorTtySize below will handle resetting back
89 89
 		// to the actual size.
90
-		if err := cli.monitorTtySize(cmd.Arg(0), false); err != nil {
90
+		if err := cli.monitorTtySize(ctx, cmd.Arg(0), false); err != nil {
91 91
 			logrus.Debugf("Error monitoring TTY size: %s", err)
92 92
 		}
93 93
 	}
94
-	if err := cli.holdHijackedConnection(context.Background(), c.Config.Tty, in, cli.out, cli.err, resp); err != nil {
94
+	if err := cli.holdHijackedConnection(ctx, c.Config.Tty, in, cli.out, cli.err, resp); err != nil {
95 95
 		return err
96 96
 	}
97 97
 
... ...
@@ -99,7 +101,7 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
99 99
 		return errAttach
100 100
 	}
101 101
 
102
-	_, status, err := getExitCode(cli, container)
102
+	_, status, err := cli.getExitCode(ctx, container)
103 103
 	if err != nil {
104 104
 		return err
105 105
 	}
... ...
@@ -32,7 +32,7 @@ import (
32 32
 	"github.com/docker/go-units"
33 33
 )
34 34
 
35
-type translatorFunc func(reference.NamedTagged) (reference.Canonical, error)
35
+type translatorFunc func(context.Context, reference.NamedTagged) (reference.Canonical, error)
36 36
 
37 37
 // CmdBuild builds a new image from the source code at a given path.
38 38
 //
... ...
@@ -77,8 +77,8 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
77 77
 	cmd.ParseFlags(args, true)
78 78
 
79 79
 	var (
80
-		ctx io.ReadCloser
81
-		err error
80
+		buildCtx io.ReadCloser
81
+		err      error
82 82
 	)
83 83
 
84 84
 	specifiedContext := cmd.Arg(0)
... ...
@@ -100,11 +100,11 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
100 100
 
101 101
 	switch {
102 102
 	case specifiedContext == "-":
103
-		ctx, relDockerfile, err = builder.GetContextFromReader(cli.in, *dockerfileName)
103
+		buildCtx, relDockerfile, err = builder.GetContextFromReader(cli.in, *dockerfileName)
104 104
 	case urlutil.IsGitURL(specifiedContext):
105 105
 		tempDir, relDockerfile, err = builder.GetContextFromGitURL(specifiedContext, *dockerfileName)
106 106
 	case urlutil.IsURL(specifiedContext):
107
-		ctx, relDockerfile, err = builder.GetContextFromURL(progBuff, specifiedContext, *dockerfileName)
107
+		buildCtx, relDockerfile, err = builder.GetContextFromURL(progBuff, specifiedContext, *dockerfileName)
108 108
 	default:
109 109
 		contextDir, relDockerfile, err = builder.GetContextFromLocalDir(specifiedContext, *dockerfileName)
110 110
 	}
... ...
@@ -121,7 +121,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
121 121
 		contextDir = tempDir
122 122
 	}
123 123
 
124
-	if ctx == nil {
124
+	if buildCtx == nil {
125 125
 		// And canonicalize dockerfile name to a platform-independent one
126 126
 		relDockerfile, err = archive.CanonicalTarNameForPath(relDockerfile)
127 127
 		if err != nil {
... ...
@@ -159,7 +159,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
159 159
 			includes = append(includes, ".dockerignore", relDockerfile)
160 160
 		}
161 161
 
162
-		ctx, err = archive.TarWithOptions(contextDir, &archive.TarOptions{
162
+		buildCtx, err = archive.TarWithOptions(contextDir, &archive.TarOptions{
163 163
 			Compression:     archive.Uncompressed,
164 164
 			ExcludePatterns: excludes,
165 165
 			IncludeFiles:    includes,
... ...
@@ -169,17 +169,19 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
169 169
 		}
170 170
 	}
171 171
 
172
+	ctx := context.Background()
173
+
172 174
 	var resolvedTags []*resolvedTag
173 175
 	if isTrusted() {
174 176
 		// Wrap the tar archive to replace the Dockerfile entry with the rewritten
175 177
 		// Dockerfile which uses trusted pulls.
176
-		ctx = replaceDockerfileTarWrapper(ctx, relDockerfile, cli.trustedReference, &resolvedTags)
178
+		buildCtx = replaceDockerfileTarWrapper(ctx, buildCtx, relDockerfile, cli.trustedReference, &resolvedTags)
177 179
 	}
178 180
 
179 181
 	// Setup an upload progress bar
180 182
 	progressOutput := streamformatter.NewStreamFormatter().NewProgressOutput(progBuff, true)
181 183
 
182
-	var body io.Reader = progress.NewProgressReader(ctx, progressOutput, 0, "", "Sending build context to Docker daemon")
184
+	var body io.Reader = progress.NewProgressReader(buildCtx, progressOutput, 0, "", "Sending build context to Docker daemon")
183 185
 
184 186
 	var memory int64
185 187
 	if *flMemoryString != "" {
... ...
@@ -235,7 +237,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
235 235
 		Labels:         runconfigopts.ConvertKVStringsToMap(flLabels.GetAll()),
236 236
 	}
237 237
 
238
-	response, err := cli.client.ImageBuild(context.Background(), body, options)
238
+	response, err := cli.client.ImageBuild(ctx, body, options)
239 239
 	if err != nil {
240 240
 		return err
241 241
 	}
... ...
@@ -271,7 +273,7 @@ func (cli *DockerCli) CmdBuild(args ...string) error {
271 271
 		// Since the build was successful, now we must tag any of the resolved
272 272
 		// images from the above Dockerfile rewrite.
273 273
 		for _, resolved := range resolvedTags {
274
-			if err := cli.tagTrusted(resolved.digestRef, resolved.tagRef); err != nil {
274
+			if err := cli.tagTrusted(ctx, resolved.digestRef, resolved.tagRef); err != nil {
275 275
 				return err
276 276
 			}
277 277
 		}
... ...
@@ -303,7 +305,7 @@ type resolvedTag struct {
303 303
 // "FROM <image>" instructions to a digest reference. `translator` is a
304 304
 // function that takes a repository name and tag reference and returns a
305 305
 // trusted digest reference.
306
-func rewriteDockerfileFrom(dockerfile io.Reader, translator translatorFunc) (newDockerfile []byte, resolvedTags []*resolvedTag, err error) {
306
+func rewriteDockerfileFrom(ctx context.Context, dockerfile io.Reader, translator translatorFunc) (newDockerfile []byte, resolvedTags []*resolvedTag, err error) {
307 307
 	scanner := bufio.NewScanner(dockerfile)
308 308
 	buf := bytes.NewBuffer(nil)
309 309
 
... ...
@@ -320,7 +322,7 @@ func rewriteDockerfileFrom(dockerfile io.Reader, translator translatorFunc) (new
320 320
 			}
321 321
 			ref = reference.WithDefaultTag(ref)
322 322
 			if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() {
323
-				trustedRef, err := translator(ref)
323
+				trustedRef, err := translator(ctx, ref)
324 324
 				if err != nil {
325 325
 					return nil, nil, err
326 326
 				}
... ...
@@ -346,7 +348,7 @@ func rewriteDockerfileFrom(dockerfile io.Reader, translator translatorFunc) (new
346 346
 // replaces the entry with the given Dockerfile name with the contents of the
347 347
 // new Dockerfile. Returns a new tar archive stream with the replaced
348 348
 // Dockerfile.
349
-func replaceDockerfileTarWrapper(inputTarStream io.ReadCloser, dockerfileName string, translator translatorFunc, resolvedTags *[]*resolvedTag) io.ReadCloser {
349
+func replaceDockerfileTarWrapper(ctx context.Context, inputTarStream io.ReadCloser, dockerfileName string, translator translatorFunc, resolvedTags *[]*resolvedTag) io.ReadCloser {
350 350
 	pipeReader, pipeWriter := io.Pipe()
351 351
 	go func() {
352 352
 		tarReader := tar.NewReader(inputTarStream)
... ...
@@ -373,7 +375,7 @@ func replaceDockerfileTarWrapper(inputTarStream io.ReadCloser, dockerfileName st
373 373
 				// generated from a directory on the local filesystem, the
374 374
 				// Dockerfile will only appear once in the archive.
375 375
 				var newDockerfile []byte
376
-				newDockerfile, *resolvedTags, err = rewriteDockerfileFrom(content, translator)
376
+				newDockerfile, *resolvedTags, err = rewriteDockerfileFrom(ctx, content, translator)
377 377
 				if err != nil {
378 378
 					pipeWriter.CloseWithError(err)
379 379
 					return
... ...
@@ -81,11 +81,13 @@ func (cli *DockerCli) CmdCp(args ...string) error {
81 81
 		followLink: *followLink,
82 82
 	}
83 83
 
84
+	ctx := context.Background()
85
+
84 86
 	switch direction {
85 87
 	case fromContainer:
86
-		return cli.copyFromContainer(srcContainer, srcPath, dstPath, cpParam)
88
+		return cli.copyFromContainer(ctx, srcContainer, srcPath, dstPath, cpParam)
87 89
 	case toContainer:
88
-		return cli.copyToContainer(srcPath, dstContainer, dstPath, cpParam)
90
+		return cli.copyToContainer(ctx, srcPath, dstContainer, dstPath, cpParam)
89 91
 	case acrossContainers:
90 92
 		// Copying between containers isn't supported.
91 93
 		return fmt.Errorf("copying between containers is not supported")
... ...
@@ -126,8 +128,8 @@ func splitCpArg(arg string) (container, path string) {
126 126
 	return parts[0], parts[1]
127 127
 }
128 128
 
129
-func (cli *DockerCli) statContainerPath(containerName, path string) (types.ContainerPathStat, error) {
130
-	return cli.client.ContainerStatPath(context.Background(), containerName, path)
129
+func (cli *DockerCli) statContainerPath(ctx context.Context, containerName, path string) (types.ContainerPathStat, error) {
130
+	return cli.client.ContainerStatPath(ctx, containerName, path)
131 131
 }
132 132
 
133 133
 func resolveLocalPath(localPath string) (absPath string, err error) {
... ...
@@ -138,7 +140,7 @@ func resolveLocalPath(localPath string) (absPath string, err error) {
138 138
 	return archive.PreserveTrailingDotOrSeparator(absPath, localPath), nil
139 139
 }
140 140
 
141
-func (cli *DockerCli) copyFromContainer(srcContainer, srcPath, dstPath string, cpParam *cpConfig) (err error) {
141
+func (cli *DockerCli) copyFromContainer(ctx context.Context, srcContainer, srcPath, dstPath string, cpParam *cpConfig) (err error) {
142 142
 	if dstPath != "-" {
143 143
 		// Get an absolute destination path.
144 144
 		dstPath, err = resolveLocalPath(dstPath)
... ...
@@ -150,7 +152,7 @@ func (cli *DockerCli) copyFromContainer(srcContainer, srcPath, dstPath string, c
150 150
 	// if client requests to follow symbol link, then must decide target file to be copied
151 151
 	var rebaseName string
152 152
 	if cpParam.followLink {
153
-		srcStat, err := cli.statContainerPath(srcContainer, srcPath)
153
+		srcStat, err := cli.statContainerPath(ctx, srcContainer, srcPath)
154 154
 
155 155
 		// If the destination is a symbolic link, we should follow it.
156 156
 		if err == nil && srcStat.Mode&os.ModeSymlink != 0 {
... ...
@@ -167,7 +169,7 @@ func (cli *DockerCli) copyFromContainer(srcContainer, srcPath, dstPath string, c
167 167
 
168 168
 	}
169 169
 
170
-	content, stat, err := cli.client.CopyFromContainer(context.Background(), srcContainer, srcPath)
170
+	content, stat, err := cli.client.CopyFromContainer(ctx, srcContainer, srcPath)
171 171
 	if err != nil {
172 172
 		return err
173 173
 	}
... ...
@@ -199,7 +201,7 @@ func (cli *DockerCli) copyFromContainer(srcContainer, srcPath, dstPath string, c
199 199
 	return archive.CopyTo(preArchive, srcInfo, dstPath)
200 200
 }
201 201
 
202
-func (cli *DockerCli) copyToContainer(srcPath, dstContainer, dstPath string, cpParam *cpConfig) (err error) {
202
+func (cli *DockerCli) copyToContainer(ctx context.Context, srcPath, dstContainer, dstPath string, cpParam *cpConfig) (err error) {
203 203
 	if srcPath != "-" {
204 204
 		// Get an absolute source path.
205 205
 		srcPath, err = resolveLocalPath(srcPath)
... ...
@@ -215,7 +217,7 @@ func (cli *DockerCli) copyToContainer(srcPath, dstContainer, dstPath string, cpP
215 215
 
216 216
 	// Prepare destination copy info by stat-ing the container path.
217 217
 	dstInfo := archive.CopyInfo{Path: dstPath}
218
-	dstStat, err := cli.statContainerPath(dstContainer, dstPath)
218
+	dstStat, err := cli.statContainerPath(ctx, dstContainer, dstPath)
219 219
 
220 220
 	// If the destination is a symbolic link, we should evaluate it.
221 221
 	if err == nil && dstStat.Mode&os.ModeSymlink != 0 {
... ...
@@ -227,7 +229,7 @@ func (cli *DockerCli) copyToContainer(srcPath, dstContainer, dstPath string, cpP
227 227
 		}
228 228
 
229 229
 		dstInfo.Path = linkTarget
230
-		dstStat, err = cli.statContainerPath(dstContainer, linkTarget)
230
+		dstStat, err = cli.statContainerPath(ctx, dstContainer, linkTarget)
231 231
 	}
232 232
 
233 233
 	// Ignore any error and assume that the parent directory of the destination
... ...
@@ -291,5 +293,5 @@ func (cli *DockerCli) copyToContainer(srcPath, dstContainer, dstPath string, cpP
291 291
 		AllowOverwriteDirWithFile: false,
292 292
 	}
293 293
 
294
-	return cli.client.CopyToContainer(context.Background(), dstContainer, resolvedDstPath, content, options)
294
+	return cli.client.CopyToContainer(ctx, dstContainer, resolvedDstPath, content, options)
295 295
 }
... ...
@@ -19,7 +19,7 @@ import (
19 19
 	networktypes "github.com/docker/engine-api/types/network"
20 20
 )
21 21
 
22
-func (cli *DockerCli) pullImage(image string, out io.Writer) error {
22
+func (cli *DockerCli) pullImage(ctx context.Context, image string, out io.Writer) error {
23 23
 	ref, err := reference.ParseNamed(image)
24 24
 	if err != nil {
25 25
 		return err
... ...
@@ -31,7 +31,7 @@ func (cli *DockerCli) pullImage(image string, out io.Writer) error {
31 31
 		return err
32 32
 	}
33 33
 
34
-	authConfig := cli.resolveAuthConfig(repoInfo.Index)
34
+	authConfig := cli.resolveAuthConfig(ctx, repoInfo.Index)
35 35
 	encodedAuth, err := encodeAuthToBase64(authConfig)
36 36
 	if err != nil {
37 37
 		return err
... ...
@@ -41,7 +41,7 @@ func (cli *DockerCli) pullImage(image string, out io.Writer) error {
41 41
 		RegistryAuth: encodedAuth,
42 42
 	}
43 43
 
44
-	responseBody, err := cli.client.ImageCreate(context.Background(), image, options)
44
+	responseBody, err := cli.client.ImageCreate(ctx, image, options)
45 45
 	if err != nil {
46 46
 		return err
47 47
 	}
... ...
@@ -69,7 +69,7 @@ func newCIDFile(path string) (*cidFile, error) {
69 69
 	return &cidFile{path: path, file: f}, nil
70 70
 }
71 71
 
72
-func (cli *DockerCli) createContainer(config *container.Config, hostConfig *container.HostConfig, networkingConfig *networktypes.NetworkingConfig, cidfile, name string) (*types.ContainerCreateResponse, error) {
72
+func (cli *DockerCli) createContainer(ctx context.Context, config *container.Config, hostConfig *container.HostConfig, networkingConfig *networktypes.NetworkingConfig, cidfile, name string) (*types.ContainerCreateResponse, error) {
73 73
 	var containerIDFile *cidFile
74 74
 	if cidfile != "" {
75 75
 		var err error
... ...
@@ -89,7 +89,7 @@ func (cli *DockerCli) createContainer(config *container.Config, hostConfig *cont
89 89
 
90 90
 		if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() {
91 91
 			var err error
92
-			trustedRef, err = cli.trustedReference(ref)
92
+			trustedRef, err = cli.trustedReference(ctx, ref)
93 93
 			if err != nil {
94 94
 				return nil, err
95 95
 			}
... ...
@@ -98,7 +98,7 @@ func (cli *DockerCli) createContainer(config *container.Config, hostConfig *cont
98 98
 	}
99 99
 
100 100
 	//create the container
101
-	response, err := cli.client.ContainerCreate(context.Background(), config, hostConfig, networkingConfig, name)
101
+	response, err := cli.client.ContainerCreate(ctx, config, hostConfig, networkingConfig, name)
102 102
 
103 103
 	//if image not found try to pull it
104 104
 	if err != nil {
... ...
@@ -106,17 +106,17 @@ func (cli *DockerCli) createContainer(config *container.Config, hostConfig *cont
106 106
 			fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", ref.String())
107 107
 
108 108
 			// we don't want to write to stdout anything apart from container.ID
109
-			if err = cli.pullImage(config.Image, cli.err); err != nil {
109
+			if err = cli.pullImage(ctx, config.Image, cli.err); err != nil {
110 110
 				return nil, err
111 111
 			}
112 112
 			if ref, ok := ref.(reference.NamedTagged); ok && trustedRef != nil {
113
-				if err := cli.tagTrusted(trustedRef, ref); err != nil {
113
+				if err := cli.tagTrusted(ctx, trustedRef, ref); err != nil {
114 114
 					return nil, err
115 115
 				}
116 116
 			}
117 117
 			// Retry
118 118
 			var retryErr error
119
-			response, retryErr = cli.client.ContainerCreate(context.Background(), config, hostConfig, networkingConfig, name)
119
+			response, retryErr = cli.client.ContainerCreate(ctx, config, hostConfig, networkingConfig, name)
120 120
 			if retryErr != nil {
121 121
 				return nil, retryErr
122 122
 			}
... ...
@@ -158,7 +158,7 @@ func (cli *DockerCli) CmdCreate(args ...string) error {
158 158
 		cmd.Usage()
159 159
 		return nil
160 160
 	}
161
-	response, err := cli.createContainer(config, hostConfig, networkingConfig, hostConfig.ContainerIDFile, *flName)
161
+	response, err := cli.createContainer(context.Background(), config, hostConfig, networkingConfig, hostConfig.ContainerIDFile, *flName)
162 162
 	if err != nil {
163 163
 		return err
164 164
 	}
... ...
@@ -34,7 +34,9 @@ func (cli *DockerCli) CmdExec(args ...string) error {
34 34
 	// Send client escape keys
35 35
 	execConfig.DetachKeys = cli.configFile.DetachKeys
36 36
 
37
-	response, err := cli.client.ContainerExecCreate(context.Background(), container, *execConfig)
37
+	ctx := context.Background()
38
+
39
+	response, err := cli.client.ContainerExecCreate(ctx, container, *execConfig)
38 40
 	if err != nil {
39 41
 		return err
40 42
 	}
... ...
@@ -56,7 +58,7 @@ func (cli *DockerCli) CmdExec(args ...string) error {
56 56
 			Tty:    execConfig.Tty,
57 57
 		}
58 58
 
59
-		if err := cli.client.ContainerExecStart(context.Background(), execID, execStartCheck); err != nil {
59
+		if err := cli.client.ContainerExecStart(ctx, execID, execStartCheck); err != nil {
60 60
 			return err
61 61
 		}
62 62
 		// For now don't print this - wait for when we support exec wait()
... ...
@@ -85,17 +87,17 @@ func (cli *DockerCli) CmdExec(args ...string) error {
85 85
 		}
86 86
 	}
87 87
 
88
-	resp, err := cli.client.ContainerExecAttach(context.Background(), execID, *execConfig)
88
+	resp, err := cli.client.ContainerExecAttach(ctx, execID, *execConfig)
89 89
 	if err != nil {
90 90
 		return err
91 91
 	}
92 92
 	defer resp.Close()
93 93
 	errCh = promise.Go(func() error {
94
-		return cli.holdHijackedConnection(context.Background(), execConfig.Tty, in, out, stderr, resp)
94
+		return cli.holdHijackedConnection(ctx, execConfig.Tty, in, out, stderr, resp)
95 95
 	})
96 96
 
97 97
 	if execConfig.Tty && cli.isTerminalIn {
98
-		if err := cli.monitorTtySize(execID, true); err != nil {
98
+		if err := cli.monitorTtySize(ctx, execID, true); err != nil {
99 99
 			fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err)
100 100
 		}
101 101
 	}
... ...
@@ -106,7 +108,7 @@ func (cli *DockerCli) CmdExec(args ...string) error {
106 106
 	}
107 107
 
108 108
 	var status int
109
-	if _, status, err = getExecExitCode(cli, execID); err != nil {
109
+	if _, status, err = cli.getExecExitCode(ctx, execID); err != nil {
110 110
 		return err
111 111
 	}
112 112
 
... ...
@@ -38,5 +38,4 @@ func (cli *DockerCli) CmdExport(args ...string) error {
38 38
 	}
39 39
 
40 40
 	return copyToFile(*outfile, responseBody)
41
-
42 41
 }
... ...
@@ -28,38 +28,40 @@ func (cli *DockerCli) CmdInspect(args ...string) error {
28 28
 		return fmt.Errorf("%q is not a valid value for --type", *inspectType)
29 29
 	}
30 30
 
31
+	ctx := context.Background()
32
+
31 33
 	var elementSearcher inspectSearcher
32 34
 	switch *inspectType {
33 35
 	case "container":
34
-		elementSearcher = cli.inspectContainers(*size)
36
+		elementSearcher = cli.inspectContainers(ctx, *size)
35 37
 	case "image":
36
-		elementSearcher = cli.inspectImages(*size)
38
+		elementSearcher = cli.inspectImages(ctx, *size)
37 39
 	default:
38
-		elementSearcher = cli.inspectAll(*size)
40
+		elementSearcher = cli.inspectAll(ctx, *size)
39 41
 	}
40 42
 
41 43
 	return cli.inspectElements(*tmplStr, cmd.Args(), elementSearcher)
42 44
 }
43 45
 
44
-func (cli *DockerCli) inspectContainers(getSize bool) inspectSearcher {
46
+func (cli *DockerCli) inspectContainers(ctx context.Context, getSize bool) inspectSearcher {
45 47
 	return func(ref string) (interface{}, []byte, error) {
46
-		return cli.client.ContainerInspectWithRaw(context.Background(), ref, getSize)
48
+		return cli.client.ContainerInspectWithRaw(ctx, ref, getSize)
47 49
 	}
48 50
 }
49 51
 
50
-func (cli *DockerCli) inspectImages(getSize bool) inspectSearcher {
52
+func (cli *DockerCli) inspectImages(ctx context.Context, getSize bool) inspectSearcher {
51 53
 	return func(ref string) (interface{}, []byte, error) {
52
-		return cli.client.ImageInspectWithRaw(context.Background(), ref, getSize)
54
+		return cli.client.ImageInspectWithRaw(ctx, ref, getSize)
53 55
 	}
54 56
 }
55 57
 
56
-func (cli *DockerCli) inspectAll(getSize bool) inspectSearcher {
58
+func (cli *DockerCli) inspectAll(ctx context.Context, getSize bool) inspectSearcher {
57 59
 	return func(ref string) (interface{}, []byte, error) {
58
-		c, rawContainer, err := cli.client.ContainerInspectWithRaw(context.Background(), ref, getSize)
60
+		c, rawContainer, err := cli.client.ContainerInspectWithRaw(ctx, ref, getSize)
59 61
 		if err != nil {
60 62
 			// Search for image with that id if a container doesn't exist.
61 63
 			if client.IsErrContainerNotFound(err) {
62
-				i, rawImage, err := cli.client.ImageInspectWithRaw(context.Background(), ref, getSize)
64
+				i, rawImage, err := cli.client.ImageInspectWithRaw(ctx, ref, getSize)
63 65
 				if err != nil {
64 66
 					if client.IsErrImageNotFound(err) {
65 67
 						return nil, nil, fmt.Errorf("Error: No such image or container: %s", ref)
... ...
@@ -40,12 +40,14 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
40 40
 		cli.in = os.Stdin
41 41
 	}
42 42
 
43
+	ctx := context.Background()
44
+
43 45
 	var serverAddress string
44 46
 	var isDefaultRegistry bool
45 47
 	if len(cmd.Args()) > 0 {
46 48
 		serverAddress = cmd.Arg(0)
47 49
 	} else {
48
-		serverAddress = cli.electAuthServer()
50
+		serverAddress = cli.electAuthServer(ctx)
49 51
 		isDefaultRegistry = true
50 52
 	}
51 53
 
... ...
@@ -54,7 +56,7 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
54 54
 		return err
55 55
 	}
56 56
 
57
-	response, err := cli.client.RegistryLogin(context.Background(), authConfig)
57
+	response, err := cli.client.RegistryLogin(ctx, authConfig)
58 58
 	if err != nil {
59 59
 		return err
60 60
 	}
... ...
@@ -3,6 +3,8 @@ package client
3 3
 import (
4 4
 	"fmt"
5 5
 
6
+	"golang.org/x/net/context"
7
+
6 8
 	Cli "github.com/docker/docker/cli"
7 9
 	flag "github.com/docker/docker/pkg/mflag"
8 10
 )
... ...
@@ -22,7 +24,7 @@ func (cli *DockerCli) CmdLogout(args ...string) error {
22 22
 	if len(cmd.Args()) > 0 {
23 23
 		serverAddress = cmd.Arg(0)
24 24
 	} else {
25
-		serverAddress = cli.electAuthServer()
25
+		serverAddress = cli.electAuthServer(context.Background())
26 26
 	}
27 27
 
28 28
 	// check if we're logged in based on the records in the config file
... ...
@@ -33,7 +33,9 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
33 33
 
34 34
 	name := cmd.Arg(0)
35 35
 
36
-	c, err := cli.client.ContainerInspect(context.Background(), name)
36
+	ctx := context.Background()
37
+
38
+	c, err := cli.client.ContainerInspect(ctx, name)
37 39
 	if err != nil {
38 40
 		return err
39 41
 	}
... ...
@@ -51,7 +53,7 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
51 51
 		Tail:       *tail,
52 52
 		Details:    *details,
53 53
 	}
54
-	responseBody, err := cli.client.ContainerLogs(context.Background(), name, options)
54
+	responseBody, err := cli.client.ContainerLogs(ctx, name, options)
55 55
 	if err != nil {
56 56
 		return err
57 57
 	}
... ...
@@ -104,9 +104,11 @@ func (cli *DockerCli) CmdNetworkRm(args ...string) error {
104 104
 		return err
105 105
 	}
106 106
 
107
+	ctx := context.Background()
108
+
107 109
 	status := 0
108 110
 	for _, net := range cmd.Args() {
109
-		if err := cli.client.NetworkRemove(context.Background(), net); err != nil {
111
+		if err := cli.client.NetworkRemove(ctx, net); err != nil {
110 112
 			fmt.Fprintf(cli.err, "%s\n", err)
111 113
 			status = 1
112 114
 			continue
... ...
@@ -239,8 +241,10 @@ func (cli *DockerCli) CmdNetworkInspect(args ...string) error {
239 239
 		return err
240 240
 	}
241 241
 
242
+	ctx := context.Background()
243
+
242 244
 	inspectSearcher := func(name string) (interface{}, []byte, error) {
243
-		i, err := cli.client.NetworkInspect(context.Background(), name)
245
+		i, err := cli.client.NetworkInspect(ctx, name)
244 246
 		return i, nil, err
245 247
 	}
246 248
 
... ...
@@ -19,9 +19,11 @@ func (cli *DockerCli) CmdPause(args ...string) error {
19 19
 
20 20
 	cmd.ParseFlags(args, true)
21 21
 
22
+	ctx := context.Background()
23
+
22 24
 	var errs []string
23 25
 	for _, name := range cmd.Args() {
24
-		if err := cli.client.ContainerPause(context.Background(), name); err != nil {
26
+		if err := cli.client.ContainerPause(ctx, name); err != nil {
25 27
 			errs = append(errs, err.Error())
26 28
 		} else {
27 29
 			fmt.Fprintf(cli.out, "%s\n", name)
... ...
@@ -55,18 +55,20 @@ func (cli *DockerCli) CmdPull(args ...string) error {
55 55
 		return err
56 56
 	}
57 57
 
58
-	authConfig := cli.resolveAuthConfig(repoInfo.Index)
58
+	ctx := context.Background()
59
+
60
+	authConfig := cli.resolveAuthConfig(ctx, repoInfo.Index)
59 61
 	requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "pull")
60 62
 
61 63
 	if isTrusted() && !registryRef.HasDigest() {
62 64
 		// Check if tag is digest
63
-		return cli.trustedPull(repoInfo, registryRef, authConfig, requestPrivilege)
65
+		return cli.trustedPull(ctx, repoInfo, registryRef, authConfig, requestPrivilege)
64 66
 	}
65 67
 
66
-	return cli.imagePullPrivileged(authConfig, distributionRef.String(), requestPrivilege, *allTags)
68
+	return cli.imagePullPrivileged(ctx, authConfig, distributionRef.String(), requestPrivilege, *allTags)
67 69
 }
68 70
 
69
-func (cli *DockerCli) imagePullPrivileged(authConfig types.AuthConfig, ref string, requestPrivilege types.RequestPrivilegeFunc, all bool) error {
71
+func (cli *DockerCli) imagePullPrivileged(ctx context.Context, authConfig types.AuthConfig, ref string, requestPrivilege types.RequestPrivilegeFunc, all bool) error {
70 72
 
71 73
 	encodedAuth, err := encodeAuthToBase64(authConfig)
72 74
 	if err != nil {
... ...
@@ -78,7 +80,7 @@ func (cli *DockerCli) imagePullPrivileged(authConfig types.AuthConfig, ref strin
78 78
 		All:           all,
79 79
 	}
80 80
 
81
-	responseBody, err := cli.client.ImagePull(context.Background(), ref, options)
81
+	responseBody, err := cli.client.ImagePull(ctx, ref, options)
82 82
 	if err != nil {
83 83
 		return err
84 84
 	}
... ...
@@ -33,15 +33,18 @@ func (cli *DockerCli) CmdPush(args ...string) error {
33 33
 	if err != nil {
34 34
 		return err
35 35
 	}
36
-	// Resolve the Auth config relevant for this server
37
-	authConfig := cli.resolveAuthConfig(repoInfo.Index)
38 36
 
37
+	ctx := context.Background()
38
+
39
+	// Resolve the Auth config relevant for this server
40
+	authConfig := cli.resolveAuthConfig(ctx, repoInfo.Index)
39 41
 	requestPrivilege := cli.registryAuthenticationPrivilegedFunc(repoInfo.Index, "push")
42
+
40 43
 	if isTrusted() {
41
-		return cli.trustedPush(repoInfo, ref, authConfig, requestPrivilege)
44
+		return cli.trustedPush(ctx, repoInfo, ref, authConfig, requestPrivilege)
42 45
 	}
43 46
 
44
-	responseBody, err := cli.imagePushPrivileged(authConfig, ref.String(), requestPrivilege)
47
+	responseBody, err := cli.imagePushPrivileged(ctx, authConfig, ref.String(), requestPrivilege)
45 48
 	if err != nil {
46 49
 		return err
47 50
 	}
... ...
@@ -51,7 +54,7 @@ func (cli *DockerCli) CmdPush(args ...string) error {
51 51
 	return jsonmessage.DisplayJSONMessagesStream(responseBody, cli.out, cli.outFd, cli.isTerminalOut, nil)
52 52
 }
53 53
 
54
-func (cli *DockerCli) imagePushPrivileged(authConfig types.AuthConfig, ref string, requestPrivilege types.RequestPrivilegeFunc) (io.ReadCloser, error) {
54
+func (cli *DockerCli) imagePushPrivileged(ctx context.Context, authConfig types.AuthConfig, ref string, requestPrivilege types.RequestPrivilegeFunc) (io.ReadCloser, error) {
55 55
 	encodedAuth, err := encodeAuthToBase64(authConfig)
56 56
 	if err != nil {
57 57
 		return nil, err
... ...
@@ -61,5 +64,5 @@ func (cli *DockerCli) imagePushPrivileged(authConfig types.AuthConfig, ref strin
61 61
 		PrivilegeFunc: requestPrivilege,
62 62
 	}
63 63
 
64
-	return cli.client.ImagePush(context.Background(), ref, options)
64
+	return cli.client.ImagePush(ctx, ref, options)
65 65
 }
... ...
@@ -23,6 +23,8 @@ func (cli *DockerCli) CmdRm(args ...string) error {
23 23
 
24 24
 	cmd.ParseFlags(args, true)
25 25
 
26
+	ctx := context.Background()
27
+
26 28
 	var errs []string
27 29
 	for _, name := range cmd.Args() {
28 30
 		if name == "" {
... ...
@@ -30,7 +32,7 @@ func (cli *DockerCli) CmdRm(args ...string) error {
30 30
 		}
31 31
 		name = strings.Trim(name, "/")
32 32
 
33
-		if err := cli.removeContainer(name, *v, *link, *force); err != nil {
33
+		if err := cli.removeContainer(ctx, name, *v, *link, *force); err != nil {
34 34
 			errs = append(errs, err.Error())
35 35
 		} else {
36 36
 			fmt.Fprintf(cli.out, "%s\n", name)
... ...
@@ -42,13 +44,13 @@ func (cli *DockerCli) CmdRm(args ...string) error {
42 42
 	return nil
43 43
 }
44 44
 
45
-func (cli *DockerCli) removeContainer(container string, removeVolumes, removeLinks, force bool) error {
45
+func (cli *DockerCli) removeContainer(ctx context.Context, container string, removeVolumes, removeLinks, force bool) error {
46 46
 	options := types.ContainerRemoveOptions{
47 47
 		RemoveVolumes: removeVolumes,
48 48
 		RemoveLinks:   removeLinks,
49 49
 		Force:         force,
50 50
 	}
51
-	if err := cli.client.ContainerRemove(context.Background(), container, options); err != nil {
51
+	if err := cli.client.ContainerRemove(ctx, container, options); err != nil {
52 52
 		return err
53 53
 	}
54 54
 	return nil
... ...
@@ -31,6 +31,8 @@ func (cli *DockerCli) CmdRmi(args ...string) error {
31 31
 		v.Set("noprune", "1")
32 32
 	}
33 33
 
34
+	ctx := context.Background()
35
+
34 36
 	var errs []string
35 37
 	for _, image := range cmd.Args() {
36 38
 		options := types.ImageRemoveOptions{
... ...
@@ -38,7 +40,7 @@ func (cli *DockerCli) CmdRmi(args ...string) error {
38 38
 			PruneChildren: !*noprune,
39 39
 		}
40 40
 
41
-		dels, err := cli.client.ImageRemove(context.Background(), image, options)
41
+		dels, err := cli.client.ImageRemove(ctx, image, options)
42 42
 		if err != nil {
43 43
 			errs = append(errs, err.Error())
44 44
 		} else {
... ...
@@ -147,20 +147,20 @@ func (cli *DockerCli) CmdRun(args ...string) error {
147 147
 		hostConfig.ConsoleSize[0], hostConfig.ConsoleSize[1] = cli.getTtySize()
148 148
 	}
149 149
 
150
-	createResponse, err := cli.createContainer(config, hostConfig, networkingConfig, hostConfig.ContainerIDFile, *flName)
150
+	ctx, cancelFun := context.WithCancel(context.Background())
151
+
152
+	createResponse, err := cli.createContainer(ctx, config, hostConfig, networkingConfig, hostConfig.ContainerIDFile, *flName)
151 153
 	if err != nil {
152 154
 		cmd.ReportError(err.Error(), true)
153 155
 		return runStartContainerErr(err)
154 156
 	}
155 157
 	if sigProxy {
156
-		sigc := cli.forwardAllSignals(createResponse.ID)
158
+		sigc := cli.forwardAllSignals(ctx, createResponse.ID)
157 159
 		defer signal.StopCatch(sigc)
158 160
 	}
159 161
 	var (
160 162
 		waitDisplayID chan struct{}
161 163
 		errCh         chan error
162
-		cancelFun     context.CancelFunc
163
-		ctx           context.Context
164 164
 	)
165 165
 	if !config.AttachStdout && !config.AttachStderr {
166 166
 		// Make this asynchronous to allow the client to write to stdin before having to read the ID
... ...
@@ -205,7 +205,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
205 205
 			DetachKeys: cli.configFile.DetachKeys,
206 206
 		}
207 207
 
208
-		resp, errAttach := cli.client.ContainerAttach(context.Background(), createResponse.ID, options)
208
+		resp, errAttach := cli.client.ContainerAttach(ctx, createResponse.ID, options)
209 209
 		if errAttach != nil && errAttach != httputil.ErrPersistEOF {
210 210
 			// ContainerAttach returns an ErrPersistEOF (connection closed)
211 211
 			// means server met an error and put it in Hijacked connection
... ...
@@ -214,7 +214,6 @@ func (cli *DockerCli) CmdRun(args ...string) error {
214 214
 		}
215 215
 		defer resp.Close()
216 216
 
217
-		ctx, cancelFun = context.WithCancel(context.Background())
218 217
 		errCh = promise.Go(func() error {
219 218
 			errHijack := cli.holdHijackedConnection(ctx, config.Tty, in, out, stderr, resp)
220 219
 			if errHijack == nil {
... ...
@@ -226,14 +225,16 @@ func (cli *DockerCli) CmdRun(args ...string) error {
226 226
 
227 227
 	if *flAutoRemove {
228 228
 		defer func() {
229
-			if err := cli.removeContainer(createResponse.ID, true, false, true); err != nil {
229
+			// Explicitly not sharing the context as it could be "Done" (by calling cancelFun)
230
+			// and thus the container would not be removed.
231
+			if err := cli.removeContainer(context.Background(), createResponse.ID, true, false, true); err != nil {
230 232
 				fmt.Fprintf(cli.err, "%v\n", err)
231 233
 			}
232 234
 		}()
233 235
 	}
234 236
 
235 237
 	//start the container
236
-	if err := cli.client.ContainerStart(context.Background(), createResponse.ID); err != nil {
238
+	if err := cli.client.ContainerStart(ctx, createResponse.ID); err != nil {
237 239
 		// If we have holdHijackedConnection, we should notify
238 240
 		// holdHijackedConnection we are going to exit and wait
239 241
 		// to avoid the terminal are not restored.
... ...
@@ -247,7 +248,7 @@ func (cli *DockerCli) CmdRun(args ...string) error {
247 247
 	}
248 248
 
249 249
 	if (config.AttachStdin || config.AttachStdout || config.AttachStderr) && config.Tty && cli.isTerminalOut {
250
-		if err := cli.monitorTtySize(createResponse.ID, false); err != nil {
250
+		if err := cli.monitorTtySize(ctx, createResponse.ID, false); err != nil {
251 251
 			fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err)
252 252
 		}
253 253
 	}
... ...
@@ -272,23 +273,23 @@ func (cli *DockerCli) CmdRun(args ...string) error {
272 272
 	if *flAutoRemove {
273 273
 		// Autoremove: wait for the container to finish, retrieve
274 274
 		// the exit code and remove the container
275
-		if status, err = cli.client.ContainerWait(context.Background(), createResponse.ID); err != nil {
275
+		if status, err = cli.client.ContainerWait(ctx, createResponse.ID); err != nil {
276 276
 			return runStartContainerErr(err)
277 277
 		}
278
-		if _, status, err = getExitCode(cli, createResponse.ID); err != nil {
278
+		if _, status, err = cli.getExitCode(ctx, createResponse.ID); err != nil {
279 279
 			return err
280 280
 		}
281 281
 	} else {
282 282
 		// No Autoremove: Simply retrieve the exit code
283 283
 		if !config.Tty {
284 284
 			// In non-TTY mode, we can't detach, so we must wait for container exit
285
-			if status, err = cli.client.ContainerWait(context.Background(), createResponse.ID); err != nil {
285
+			if status, err = cli.client.ContainerWait(ctx, createResponse.ID); err != nil {
286 286
 				return err
287 287
 			}
288 288
 		} else {
289 289
 			// In TTY mode, there is a race: if the process dies too slowly, the state could
290 290
 			// be updated after the getExitCode call and result in the wrong exit code being reported
291
-			if _, status, err = getExitCode(cli, createResponse.ID); err != nil {
291
+			if _, status, err = cli.getExitCode(ctx, createResponse.ID); err != nil {
292 292
 				return err
293 293
 			}
294 294
 		}
... ...
@@ -58,7 +58,9 @@ func (cli *DockerCli) CmdSearch(args ...string) error {
58 58
 		return err
59 59
 	}
60 60
 
61
-	authConfig := cli.resolveAuthConfig(indexInfo)
61
+	ctx := context.Background()
62
+
63
+	authConfig := cli.resolveAuthConfig(ctx, indexInfo)
62 64
 	requestPrivilege := cli.registryAuthenticationPrivilegedFunc(indexInfo, "search")
63 65
 
64 66
 	encodedAuth, err := encodeAuthToBase64(authConfig)
... ...
@@ -72,7 +74,7 @@ func (cli *DockerCli) CmdSearch(args ...string) error {
72 72
 		Filters:       filterArgs,
73 73
 	}
74 74
 
75
-	unorderedResults, err := cli.client.ImageSearch(context.Background(), name, options)
75
+	unorderedResults, err := cli.client.ImageSearch(ctx, name, options)
76 76
 	if err != nil {
77 77
 		return err
78 78
 	}
... ...
@@ -17,7 +17,7 @@ import (
17 17
 	"github.com/docker/engine-api/types"
18 18
 )
19 19
 
20
-func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
20
+func (cli *DockerCli) forwardAllSignals(ctx context.Context, cid string) chan os.Signal {
21 21
 	sigc := make(chan os.Signal, 128)
22 22
 	signal.CatchAll(sigc)
23 23
 	go func() {
... ...
@@ -37,7 +37,7 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
37 37
 				continue
38 38
 			}
39 39
 
40
-			if err := cli.client.ContainerKill(context.Background(), cid, sig); err != nil {
40
+			if err := cli.client.ContainerKill(ctx, cid, sig); err != nil {
41 41
 				logrus.Debugf("Error sending signal: %s", err)
42 42
 			}
43 43
 		}
... ...
@@ -57,6 +57,8 @@ func (cli *DockerCli) CmdStart(args ...string) error {
57 57
 
58 58
 	cmd.ParseFlags(args, true)
59 59
 
60
+	ctx, cancelFun := context.WithCancel(context.Background())
61
+
60 62
 	if *attach || *openStdin {
61 63
 		// We're going to attach to a container.
62 64
 		// 1. Ensure we only have one container.
... ...
@@ -66,13 +68,13 @@ func (cli *DockerCli) CmdStart(args ...string) error {
66 66
 
67 67
 		// 2. Attach to the container.
68 68
 		container := cmd.Arg(0)
69
-		c, err := cli.client.ContainerInspect(context.Background(), container)
69
+		c, err := cli.client.ContainerInspect(ctx, container)
70 70
 		if err != nil {
71 71
 			return err
72 72
 		}
73 73
 
74 74
 		if !c.Config.Tty {
75
-			sigc := cli.forwardAllSignals(container)
75
+			sigc := cli.forwardAllSignals(ctx, container)
76 76
 			defer signal.StopCatch(sigc)
77 77
 		}
78 78
 
... ...
@@ -94,7 +96,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
94 94
 			in = cli.in
95 95
 		}
96 96
 
97
-		resp, errAttach := cli.client.ContainerAttach(context.Background(), container, options)
97
+		resp, errAttach := cli.client.ContainerAttach(ctx, container, options)
98 98
 		if errAttach != nil && errAttach != httputil.ErrPersistEOF {
99 99
 			// ContainerAttach return an ErrPersistEOF (connection closed)
100 100
 			// means server met an error and put it in Hijacked connection
... ...
@@ -102,7 +104,6 @@ func (cli *DockerCli) CmdStart(args ...string) error {
102 102
 			return errAttach
103 103
 		}
104 104
 		defer resp.Close()
105
-		ctx, cancelFun := context.WithCancel(context.Background())
106 105
 		cErr := promise.Go(func() error {
107 106
 			errHijack := cli.holdHijackedConnection(ctx, c.Config.Tty, in, cli.out, cli.err, resp)
108 107
 			if errHijack == nil {
... ...
@@ -112,7 +113,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
112 112
 		})
113 113
 
114 114
 		// 3. Start the container.
115
-		if err := cli.client.ContainerStart(context.Background(), container); err != nil {
115
+		if err := cli.client.ContainerStart(ctx, container); err != nil {
116 116
 			cancelFun()
117 117
 			<-cErr
118 118
 			return err
... ...
@@ -120,14 +121,14 @@ func (cli *DockerCli) CmdStart(args ...string) error {
120 120
 
121 121
 		// 4. Wait for attachment to break.
122 122
 		if c.Config.Tty && cli.isTerminalOut {
123
-			if err := cli.monitorTtySize(container, false); err != nil {
123
+			if err := cli.monitorTtySize(ctx, container, false); err != nil {
124 124
 				fmt.Fprintf(cli.err, "Error monitoring TTY size: %s\n", err)
125 125
 			}
126 126
 		}
127 127
 		if attchErr := <-cErr; attchErr != nil {
128 128
 			return attchErr
129 129
 		}
130
-		_, status, err := getExitCode(cli, container)
130
+		_, status, err := cli.getExitCode(ctx, container)
131 131
 		if err != nil {
132 132
 			return err
133 133
 		}
... ...
@@ -137,16 +138,16 @@ func (cli *DockerCli) CmdStart(args ...string) error {
137 137
 	} else {
138 138
 		// We're not going to attach to anything.
139 139
 		// Start as many containers as we want.
140
-		return cli.startContainersWithoutAttachments(cmd.Args())
140
+		return cli.startContainersWithoutAttachments(ctx, cmd.Args())
141 141
 	}
142 142
 
143 143
 	return nil
144 144
 }
145 145
 
146
-func (cli *DockerCli) startContainersWithoutAttachments(containers []string) error {
146
+func (cli *DockerCli) startContainersWithoutAttachments(ctx context.Context, containers []string) error {
147 147
 	var failedContainers []string
148 148
 	for _, container := range containers {
149
-		if err := cli.client.ContainerStart(context.Background(), container); err != nil {
149
+		if err := cli.client.ContainerStart(ctx, container); err != nil {
150 150
 			fmt.Fprintf(cli.err, "%s\n", err)
151 151
 			failedContainers = append(failedContainers, container)
152 152
 		} else {
... ...
@@ -33,6 +33,8 @@ func (cli *DockerCli) CmdStats(args ...string) error {
33 33
 	showAll := len(names) == 0
34 34
 	closeChan := make(chan error)
35 35
 
36
+	ctx := context.Background()
37
+
36 38
 	// monitorContainerEvents watches for container creation and removal (only
37 39
 	// used when calling `docker stats` without arguments).
38 40
 	monitorContainerEvents := func(started chan<- struct{}, c chan events.Message) {
... ...
@@ -41,7 +43,7 @@ func (cli *DockerCli) CmdStats(args ...string) error {
41 41
 		options := types.EventsOptions{
42 42
 			Filters: f,
43 43
 		}
44
-		resBody, err := cli.client.Events(context.Background(), options)
44
+		resBody, err := cli.client.Events(ctx, options)
45 45
 		// Whether we successfully subscribed to events or not, we can now
46 46
 		// unblock the main goroutine.
47 47
 		close(started)
... ...
@@ -71,7 +73,7 @@ func (cli *DockerCli) CmdStats(args ...string) error {
71 71
 		options := types.ContainerListOptions{
72 72
 			All: *all,
73 73
 		}
74
-		cs, err := cli.client.ContainerList(context.Background(), options)
74
+		cs, err := cli.client.ContainerList(ctx, options)
75 75
 		if err != nil {
76 76
 			closeChan <- err
77 77
 		}
... ...
@@ -79,7 +81,7 @@ func (cli *DockerCli) CmdStats(args ...string) error {
79 79
 			s := &containerStats{Name: container.ID[:12]}
80 80
 			if cStats.add(s) {
81 81
 				waitFirst.Add(1)
82
-				go s.Collect(cli.client, !*noStream, waitFirst)
82
+				go s.Collect(ctx, cli.client, !*noStream, waitFirst)
83 83
 			}
84 84
 		}
85 85
 	}
... ...
@@ -96,7 +98,7 @@ func (cli *DockerCli) CmdStats(args ...string) error {
96 96
 				s := &containerStats{Name: e.ID[:12]}
97 97
 				if cStats.add(s) {
98 98
 					waitFirst.Add(1)
99
-					go s.Collect(cli.client, !*noStream, waitFirst)
99
+					go s.Collect(ctx, cli.client, !*noStream, waitFirst)
100 100
 				}
101 101
 			}
102 102
 		})
... ...
@@ -105,7 +107,7 @@ func (cli *DockerCli) CmdStats(args ...string) error {
105 105
 			s := &containerStats{Name: e.ID[:12]}
106 106
 			if cStats.add(s) {
107 107
 				waitFirst.Add(1)
108
-				go s.Collect(cli.client, !*noStream, waitFirst)
108
+				go s.Collect(ctx, cli.client, !*noStream, waitFirst)
109 109
 			}
110 110
 		})
111 111
 
... ...
@@ -131,7 +133,7 @@ func (cli *DockerCli) CmdStats(args ...string) error {
131 131
 			s := &containerStats{Name: name}
132 132
 			if cStats.add(s) {
133 133
 				waitFirst.Add(1)
134
-				go s.Collect(cli.client, !*noStream, waitFirst)
134
+				go s.Collect(ctx, cli.client, !*noStream, waitFirst)
135 135
 			}
136 136
 		}
137 137
 
... ...
@@ -63,7 +63,7 @@ func (s *stats) isKnownContainer(cid string) (int, bool) {
63 63
 	return -1, false
64 64
 }
65 65
 
66
-func (s *containerStats) Collect(cli client.APIClient, streamStats bool, waitFirst *sync.WaitGroup) {
66
+func (s *containerStats) Collect(ctx context.Context, cli client.APIClient, streamStats bool, waitFirst *sync.WaitGroup) {
67 67
 	logrus.Debugf("collecting stats for %s", s.Name)
68 68
 	var (
69 69
 		getFirst       bool
... ...
@@ -80,7 +80,7 @@ func (s *containerStats) Collect(cli client.APIClient, streamStats bool, waitFir
80 80
 		}
81 81
 	}()
82 82
 
83
-	responseBody, err := cli.ContainerStats(context.Background(), s.Name, streamStats)
83
+	responseBody, err := cli.ContainerStats(ctx, s.Name, streamStats)
84 84
 	if err != nil {
85 85
 		s.mu.Lock()
86 86
 		s.err = err
... ...
@@ -22,9 +22,11 @@ func (cli *DockerCli) CmdStop(args ...string) error {
22 22
 
23 23
 	cmd.ParseFlags(args, true)
24 24
 
25
+	ctx := context.Background()
26
+
25 27
 	var errs []string
26 28
 	for _, name := range cmd.Args() {
27
-		if err := cli.client.ContainerStop(context.Background(), name, *nSeconds); err != nil {
29
+		if err := cli.client.ContainerStop(ctx, name, *nSeconds); err != nil {
28 30
 			errs = append(errs, err.Error())
29 31
 		} else {
30 32
 			fmt.Fprintf(cli.out, "%s\n", name)
... ...
@@ -229,14 +229,14 @@ func (cli *DockerCli) getPassphraseRetriever() passphrase.Retriever {
229 229
 	}
230 230
 }
231 231
 
232
-func (cli *DockerCli) trustedReference(ref reference.NamedTagged) (reference.Canonical, error) {
232
+func (cli *DockerCli) trustedReference(ctx context.Context, ref reference.NamedTagged) (reference.Canonical, error) {
233 233
 	repoInfo, err := registry.ParseRepositoryInfo(ref)
234 234
 	if err != nil {
235 235
 		return nil, err
236 236
 	}
237 237
 
238 238
 	// Resolve the Auth config relevant for this server
239
-	authConfig := cli.resolveAuthConfig(repoInfo.Index)
239
+	authConfig := cli.resolveAuthConfig(ctx, repoInfo.Index)
240 240
 
241 241
 	notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig, "pull")
242 242
 	if err != nil {
... ...
@@ -262,14 +262,14 @@ func (cli *DockerCli) trustedReference(ref reference.NamedTagged) (reference.Can
262 262
 	return reference.WithDigest(ref, r.digest)
263 263
 }
264 264
 
265
-func (cli *DockerCli) tagTrusted(trustedRef reference.Canonical, ref reference.NamedTagged) error {
265
+func (cli *DockerCli) tagTrusted(ctx context.Context, trustedRef reference.Canonical, ref reference.NamedTagged) error {
266 266
 	fmt.Fprintf(cli.out, "Tagging %s as %s\n", trustedRef.String(), ref.String())
267 267
 
268 268
 	options := types.ImageTagOptions{
269 269
 		Force: true,
270 270
 	}
271 271
 
272
-	return cli.client.ImageTag(context.Background(), trustedRef.String(), ref.String(), options)
272
+	return cli.client.ImageTag(ctx, trustedRef.String(), ref.String(), options)
273 273
 }
274 274
 
275 275
 func notaryError(repoName string, err error) error {
... ...
@@ -302,7 +302,7 @@ func notaryError(repoName string, err error) error {
302 302
 	return err
303 303
 }
304 304
 
305
-func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registry.Reference, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error {
305
+func (cli *DockerCli) trustedPull(ctx context.Context, repoInfo *registry.RepositoryInfo, ref registry.Reference, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error {
306 306
 	var refs []target
307 307
 
308 308
 	notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig, "pull")
... ...
@@ -364,7 +364,7 @@ func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registr
364 364
 		if err != nil {
365 365
 			return err
366 366
 		}
367
-		if err := cli.imagePullPrivileged(authConfig, ref.String(), requestPrivilege, false); err != nil {
367
+		if err := cli.imagePullPrivileged(ctx, authConfig, ref.String(), requestPrivilege, false); err != nil {
368 368
 			return err
369 369
 		}
370 370
 
... ...
@@ -378,7 +378,7 @@ func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registr
378 378
 			if err != nil {
379 379
 				return err
380 380
 			}
381
-			if err := cli.tagTrusted(trustedRef, tagged); err != nil {
381
+			if err := cli.tagTrusted(ctx, trustedRef, tagged); err != nil {
382 382
 				return err
383 383
 			}
384 384
 		}
... ...
@@ -386,8 +386,8 @@ func (cli *DockerCli) trustedPull(repoInfo *registry.RepositoryInfo, ref registr
386 386
 	return nil
387 387
 }
388 388
 
389
-func (cli *DockerCli) trustedPush(repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error {
390
-	responseBody, err := cli.imagePushPrivileged(authConfig, ref.String(), requestPrivilege)
389
+func (cli *DockerCli) trustedPush(ctx context.Context, repoInfo *registry.RepositoryInfo, ref reference.Named, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error {
390
+	responseBody, err := cli.imagePushPrivileged(ctx, authConfig, ref.String(), requestPrivilege)
391 391
 	if err != nil {
392 392
 		return err
393 393
 	}
... ...
@@ -19,9 +19,11 @@ func (cli *DockerCli) CmdUnpause(args ...string) error {
19 19
 
20 20
 	cmd.ParseFlags(args, true)
21 21
 
22
+	ctx := context.Background()
23
+
22 24
 	var errs []string
23 25
 	for _, name := range cmd.Args() {
24
-		if err := cli.client.ContainerUnpause(context.Background(), name); err != nil {
26
+		if err := cli.client.ContainerUnpause(ctx, name); err != nil {
25 27
 			errs = append(errs, err.Error())
26 28
 		} else {
27 29
 			fmt.Fprintf(cli.out, "%s\n", name)
... ...
@@ -99,10 +99,13 @@ func (cli *DockerCli) CmdUpdate(args ...string) error {
99 99
 		RestartPolicy: restartPolicy,
100 100
 	}
101 101
 
102
+	ctx := context.Background()
103
+
102 104
 	names := cmd.Args()
103 105
 	var errs []string
106
+
104 107
 	for _, name := range names {
105
-		if err := cli.client.ContainerUpdate(context.Background(), name, updateConfig); err != nil {
108
+		if err := cli.client.ContainerUpdate(ctx, name, updateConfig); err != nil {
106 109
 			errs = append(errs, err.Error())
107 110
 		} else {
108 111
 			fmt.Fprintf(cli.out, "%s\n", name)
... ...
@@ -23,13 +23,13 @@ import (
23 23
 	registrytypes "github.com/docker/engine-api/types/registry"
24 24
 )
25 25
 
26
-func (cli *DockerCli) electAuthServer() string {
26
+func (cli *DockerCli) electAuthServer(ctx context.Context) string {
27 27
 	// The daemon `/info` endpoint informs us of the default registry being
28 28
 	// used. This is essential in cross-platforms environment, where for
29 29
 	// example a Linux client might be interacting with a Windows daemon, hence
30 30
 	// the default registry URL might be Windows specific.
31 31
 	serverAddress := registry.IndexServer
32
-	if info, err := cli.client.Info(context.Background()); err != nil {
32
+	if info, err := cli.client.Info(ctx); err != nil {
33 33
 		fmt.Fprintf(cli.out, "Warning: failed to get default registry endpoint from daemon (%v). Using system default: %s\n", err, serverAddress)
34 34
 	} else {
35 35
 		serverAddress = info.IndexServerAddress
... ...
@@ -58,12 +58,12 @@ func (cli *DockerCli) registryAuthenticationPrivilegedFunc(index *registrytypes.
58 58
 	}
59 59
 }
60 60
 
61
-func (cli *DockerCli) resizeTty(id string, isExec bool) {
61
+func (cli *DockerCli) resizeTty(ctx context.Context, id string, isExec bool) {
62 62
 	height, width := cli.getTtySize()
63
-	cli.resizeTtyTo(id, height, width, isExec)
63
+	cli.resizeTtyTo(ctx, id, height, width, isExec)
64 64
 }
65 65
 
66
-func (cli *DockerCli) resizeTtyTo(id string, height, width int, isExec bool) {
66
+func (cli *DockerCli) resizeTtyTo(ctx context.Context, id string, height, width int, isExec bool) {
67 67
 	if height == 0 && width == 0 {
68 68
 		return
69 69
 	}
... ...
@@ -75,9 +75,9 @@ func (cli *DockerCli) resizeTtyTo(id string, height, width int, isExec bool) {
75 75
 
76 76
 	var err error
77 77
 	if isExec {
78
-		err = cli.client.ContainerExecResize(context.Background(), id, options)
78
+		err = cli.client.ContainerExecResize(ctx, id, options)
79 79
 	} else {
80
-		err = cli.client.ContainerResize(context.Background(), id, options)
80
+		err = cli.client.ContainerResize(ctx, id, options)
81 81
 	}
82 82
 
83 83
 	if err != nil {
... ...
@@ -87,8 +87,8 @@ func (cli *DockerCli) resizeTtyTo(id string, height, width int, isExec bool) {
87 87
 
88 88
 // getExitCode perform an inspect on the container. It returns
89 89
 // the running state and the exit code.
90
-func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
91
-	c, err := cli.client.ContainerInspect(context.Background(), containerID)
90
+func (cli *DockerCli) getExitCode(ctx context.Context, containerID string) (bool, int, error) {
91
+	c, err := cli.client.ContainerInspect(ctx, containerID)
92 92
 	if err != nil {
93 93
 		// If we can't connect, then the daemon probably died.
94 94
 		if err != client.ErrConnectionFailed {
... ...
@@ -102,8 +102,8 @@ func getExitCode(cli *DockerCli, containerID string) (bool, int, error) {
102 102
 
103 103
 // getExecExitCode perform an inspect on the exec command. It returns
104 104
 // the running state and the exit code.
105
-func getExecExitCode(cli *DockerCli, execID string) (bool, int, error) {
106
-	resp, err := cli.client.ContainerExecInspect(context.Background(), execID)
105
+func (cli *DockerCli) getExecExitCode(ctx context.Context, execID string) (bool, int, error) {
106
+	resp, err := cli.client.ContainerExecInspect(ctx, execID)
107 107
 	if err != nil {
108 108
 		// If we can't connect, then the daemon probably died.
109 109
 		if err != client.ErrConnectionFailed {
... ...
@@ -115,8 +115,8 @@ func getExecExitCode(cli *DockerCli, execID string) (bool, int, error) {
115 115
 	return resp.Running, resp.ExitCode, nil
116 116
 }
117 117
 
118
-func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
119
-	cli.resizeTty(id, isExec)
118
+func (cli *DockerCli) monitorTtySize(ctx context.Context, id string, isExec bool) error {
119
+	cli.resizeTty(ctx, id, isExec)
120 120
 
121 121
 	if runtime.GOOS == "windows" {
122 122
 		go func() {
... ...
@@ -126,7 +126,7 @@ func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
126 126
 				h, w := cli.getTtySize()
127 127
 
128 128
 				if prevW != w || prevH != h {
129
-					cli.resizeTty(id, isExec)
129
+					cli.resizeTty(ctx, id, isExec)
130 130
 				}
131 131
 				prevH = h
132 132
 				prevW = w
... ...
@@ -137,7 +137,7 @@ func (cli *DockerCli) monitorTtySize(id string, isExec bool) error {
137 137
 		gosignal.Notify(sigchan, signal.SIGWINCH)
138 138
 		go func() {
139 139
 			for range sigchan {
140
-				cli.resizeTty(id, isExec)
140
+				cli.resizeTty(ctx, id, isExec)
141 141
 			}
142 142
 		}()
143 143
 	}
... ...
@@ -185,10 +185,10 @@ func copyToFile(outfile string, r io.Reader) error {
185 185
 // resolveAuthConfig is like registry.ResolveAuthConfig, but if using the
186 186
 // default index, it uses the default index name for the daemon's platform,
187 187
 // not the client's platform.
188
-func (cli *DockerCli) resolveAuthConfig(index *registrytypes.IndexInfo) types.AuthConfig {
188
+func (cli *DockerCli) resolveAuthConfig(ctx context.Context, index *registrytypes.IndexInfo) types.AuthConfig {
189 189
 	configKey := index.Name
190 190
 	if index.Official {
191
-		configKey = cli.electAuthServer()
191
+		configKey = cli.electAuthServer(ctx)
192 192
 	}
193 193
 
194 194
 	a, _ := getCredentials(cli.configFile, configKey)
... ...
@@ -110,8 +110,10 @@ func (cli *DockerCli) CmdVolumeInspect(args ...string) error {
110 110
 		return nil
111 111
 	}
112 112
 
113
+	ctx := context.Background()
114
+
113 115
 	inspectSearcher := func(name string) (interface{}, []byte, error) {
114
-		i, err := cli.client.VolumeInspect(context.Background(), name)
116
+		i, err := cli.client.VolumeInspect(ctx, name)
115 117
 		return i, nil, err
116 118
 	}
117 119
 
... ...
@@ -161,8 +163,10 @@ func (cli *DockerCli) CmdVolumeRm(args ...string) error {
161 161
 
162 162
 	var status = 0
163 163
 
164
+	ctx := context.Background()
165
+
164 166
 	for _, name := range cmd.Args() {
165
-		if err := cli.client.VolumeRemove(context.Background(), name); err != nil {
167
+		if err := cli.client.VolumeRemove(ctx, name); err != nil {
166 168
 			fmt.Fprintf(cli.err, "%s\n", err)
167 169
 			status = 1
168 170
 			continue
... ...
@@ -21,9 +21,11 @@ func (cli *DockerCli) CmdWait(args ...string) error {
21 21
 
22 22
 	cmd.ParseFlags(args, true)
23 23
 
24
+	ctx := context.Background()
25
+
24 26
 	var errs []string
25 27
 	for _, name := range cmd.Args() {
26
-		status, err := cli.client.ContainerWait(context.Background(), name)
28
+		status, err := cli.client.ContainerWait(ctx, name)
27 29
 		if err != nil {
28 30
 			errs = append(errs, err.Error())
29 31
 		} else {