Side effects:
- Decouple daemon and container to start containers.
- Decouple daemon and container to copy files.
Signed-off-by: David Calavera <david.calavera@gmail.com>
... | ... |
@@ -130,6 +130,12 @@ type Docker interface { |
130 | 130 |
Release(sessionID string, activeImages []string) |
131 | 131 |
// Kill stops the container execution abruptly. |
132 | 132 |
Kill(c *daemon.Container) error |
133 |
+ // Mount mounts the root filesystem for the container. |
|
134 |
+ Mount(c *daemon.Container) error |
|
135 |
+ // Unmount unmounts the root filesystem for the container. |
|
136 |
+ Unmount(c *daemon.Container) error |
|
137 |
+ // Start starts a new container |
|
138 |
+ Start(c *daemon.Container) error |
|
133 | 139 |
} |
134 | 140 |
|
135 | 141 |
// ImageCache abstracts an image cache store. |
... | ... |
@@ -399,8 +399,8 @@ func run(b *Builder, args []string, attributes map[string]bool, original string) |
399 | 399 |
|
400 | 400 |
// Ensure that we keep the container mounted until the commit |
401 | 401 |
// to avoid unmounting and then mounting directly again |
402 |
- c.Mount() |
|
403 |
- defer c.Unmount() |
|
402 |
+ b.docker.Mount(c) |
|
403 |
+ defer b.docker.Unmount(c) |
|
404 | 404 |
|
405 | 405 |
err = b.run(c) |
406 | 406 |
if err != nil { |
... | ... |
@@ -67,10 +67,10 @@ func (b *Builder) commit(id string, autoCmd *stringutils.StrSlice, comment strin |
67 | 67 |
} |
68 | 68 |
id = container.ID |
69 | 69 |
|
70 |
- if err := container.Mount(); err != nil { |
|
70 |
+ if err := b.docker.Mount(container); err != nil { |
|
71 | 71 |
return err |
72 | 72 |
} |
73 |
- defer container.Unmount() |
|
73 |
+ defer b.docker.Unmount(container) |
|
74 | 74 |
} |
75 | 75 |
|
76 | 76 |
container, err := b.docker.Container(id) |
... | ... |
@@ -201,7 +201,7 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowLocalD |
201 | 201 |
if err != nil { |
202 | 202 |
return err |
203 | 203 |
} |
204 |
- defer container.Unmount() |
|
204 |
+ defer b.docker.Unmount(container) |
|
205 | 205 |
b.tmpContainers[container.ID] = struct{}{} |
206 | 206 |
|
207 | 207 |
comment := fmt.Sprintf("%s %s in %s", cmdName, origPaths, dest) |
... | ... |
@@ -524,7 +524,7 @@ func (b *Builder) create() (*daemon.Container, error) { |
524 | 524 |
if err != nil { |
525 | 525 |
return nil, err |
526 | 526 |
} |
527 |
- defer c.Unmount() |
|
527 |
+ defer b.docker.Unmount(c) |
|
528 | 528 |
for _, warning := range warnings { |
529 | 529 |
fmt.Fprintf(b.Stdout, " ---> [Warning] %s\n", warning) |
530 | 530 |
} |
... | ... |
@@ -549,7 +549,7 @@ func (b *Builder) run(c *daemon.Container) error { |
549 | 549 |
} |
550 | 550 |
|
551 | 551 |
//start the container |
552 |
- if err := c.Start(); err != nil { |
|
552 |
+ if err := b.docker.Start(c); err != nil { |
|
553 | 553 |
return err |
554 | 554 |
} |
555 | 555 |
|
... | ... |
@@ -30,7 +30,7 @@ func (daemon *Daemon) ContainerCopy(name string, res string) (io.ReadCloser, err |
30 | 30 |
res = res[1:] |
31 | 31 |
} |
32 | 32 |
|
33 |
- return container.copy(res) |
|
33 |
+ return daemon.containerCopy(container, res) |
|
34 | 34 |
} |
35 | 35 |
|
36 | 36 |
// ContainerStatPath stats the filesystem resource at the specified path in the |
... | ... |
@@ -41,7 +41,7 @@ func (daemon *Daemon) ContainerStatPath(name string, path string) (stat *types.C |
41 | 41 |
return nil, err |
42 | 42 |
} |
43 | 43 |
|
44 |
- return container.StatPath(path) |
|
44 |
+ return daemon.containerStatPath(container, path) |
|
45 | 45 |
} |
46 | 46 |
|
47 | 47 |
// ContainerArchivePath creates an archive of the filesystem resource at the |
... | ... |
@@ -53,7 +53,7 @@ func (daemon *Daemon) ContainerArchivePath(name string, path string) (content io |
53 | 53 |
return nil, nil, err |
54 | 54 |
} |
55 | 55 |
|
56 |
- return container.ArchivePath(path) |
|
56 |
+ return daemon.containerArchivePath(container, path) |
|
57 | 57 |
} |
58 | 58 |
|
59 | 59 |
// ContainerExtractToDir extracts the given archive to the specified location |
... | ... |
@@ -68,7 +68,7 @@ func (daemon *Daemon) ContainerExtractToDir(name, path string, noOverwriteDirNon |
68 | 68 |
return err |
69 | 69 |
} |
70 | 70 |
|
71 |
- return container.ExtractToDir(path, noOverwriteDirNonDir, content) |
|
71 |
+ return daemon.containerExtractToDir(container, path, noOverwriteDirNonDir, content) |
|
72 | 72 |
} |
73 | 73 |
|
74 | 74 |
// resolvePath resolves the given path in the container to a resource on the |
... | ... |
@@ -131,16 +131,16 @@ func (container *Container) statPath(resolvedPath, absPath string) (stat *types. |
131 | 131 |
}, nil |
132 | 132 |
} |
133 | 133 |
|
134 |
-// StatPath stats the filesystem resource at the specified path in this |
|
134 |
+// containerStatPath stats the filesystem resource at the specified path in this |
|
135 | 135 |
// container. Returns stat info about the resource. |
136 |
-func (container *Container) StatPath(path string) (stat *types.ContainerPathStat, err error) { |
|
136 |
+func (daemon *Daemon) containerStatPath(container *Container, path string) (stat *types.ContainerPathStat, err error) { |
|
137 | 137 |
container.Lock() |
138 | 138 |
defer container.Unlock() |
139 | 139 |
|
140 |
- if err = container.Mount(); err != nil { |
|
140 |
+ if err = daemon.Mount(container); err != nil { |
|
141 | 141 |
return nil, err |
142 | 142 |
} |
143 |
- defer container.Unmount() |
|
143 |
+ defer daemon.Unmount(container) |
|
144 | 144 |
|
145 | 145 |
err = container.mountVolumes() |
146 | 146 |
defer container.unmountVolumes(true) |
... | ... |
@@ -156,10 +156,10 @@ func (container *Container) StatPath(path string) (stat *types.ContainerPathStat |
156 | 156 |
return container.statPath(resolvedPath, absPath) |
157 | 157 |
} |
158 | 158 |
|
159 |
-// ArchivePath creates an archive of the filesystem resource at the specified |
|
159 |
+// containerArchivePath creates an archive of the filesystem resource at the specified |
|
160 | 160 |
// path in this container. Returns a tar archive of the resource and stat info |
161 | 161 |
// about the resource. |
162 |
-func (container *Container) ArchivePath(path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error) { |
|
162 |
+func (daemon *Daemon) containerArchivePath(container *Container, path string) (content io.ReadCloser, stat *types.ContainerPathStat, err error) { |
|
163 | 163 |
container.Lock() |
164 | 164 |
|
165 | 165 |
defer func() { |
... | ... |
@@ -171,7 +171,7 @@ func (container *Container) ArchivePath(path string) (content io.ReadCloser, sta |
171 | 171 |
} |
172 | 172 |
}() |
173 | 173 |
|
174 |
- if err = container.Mount(); err != nil { |
|
174 |
+ if err = daemon.Mount(container); err != nil { |
|
175 | 175 |
return nil, nil, err |
176 | 176 |
} |
177 | 177 |
|
... | ... |
@@ -180,7 +180,7 @@ func (container *Container) ArchivePath(path string) (content io.ReadCloser, sta |
180 | 180 |
// unmount any volumes |
181 | 181 |
container.unmountVolumes(true) |
182 | 182 |
// unmount the container's rootfs |
183 |
- container.Unmount() |
|
183 |
+ daemon.Unmount(container) |
|
184 | 184 |
} |
185 | 185 |
}() |
186 | 186 |
|
... | ... |
@@ -214,7 +214,7 @@ func (container *Container) ArchivePath(path string) (content io.ReadCloser, sta |
214 | 214 |
content = ioutils.NewReadCloserWrapper(data, func() error { |
215 | 215 |
err := data.Close() |
216 | 216 |
container.unmountVolumes(true) |
217 |
- container.Unmount() |
|
217 |
+ daemon.Unmount(container) |
|
218 | 218 |
container.Unlock() |
219 | 219 |
return err |
220 | 220 |
}) |
... | ... |
@@ -224,20 +224,20 @@ func (container *Container) ArchivePath(path string) (content io.ReadCloser, sta |
224 | 224 |
return content, stat, nil |
225 | 225 |
} |
226 | 226 |
|
227 |
-// ExtractToDir extracts the given tar archive to the specified location in the |
|
227 |
+// containerExtractToDir extracts the given tar archive to the specified location in the |
|
228 | 228 |
// filesystem of this container. The given path must be of a directory in the |
229 | 229 |
// container. If it is not, the error will be ErrExtractPointNotDirectory. If |
230 | 230 |
// noOverwriteDirNonDir is true then it will be an error if unpacking the |
231 | 231 |
// given content would cause an existing directory to be replaced with a non- |
232 | 232 |
// directory and vice versa. |
233 |
-func (container *Container) ExtractToDir(path string, noOverwriteDirNonDir bool, content io.Reader) (err error) { |
|
233 |
+func (daemon *Daemon) containerExtractToDir(container *Container, path string, noOverwriteDirNonDir bool, content io.Reader) (err error) { |
|
234 | 234 |
container.Lock() |
235 | 235 |
defer container.Unlock() |
236 | 236 |
|
237 |
- if err = container.Mount(); err != nil { |
|
237 |
+ if err = daemon.Mount(container); err != nil { |
|
238 | 238 |
return err |
239 | 239 |
} |
240 |
- defer container.Unmount() |
|
240 |
+ defer daemon.Unmount(container) |
|
241 | 241 |
|
242 | 242 |
err = container.mountVolumes() |
243 | 243 |
defer container.unmountVolumes(true) |
... | ... |
@@ -225,76 +225,6 @@ func (container *Container) getRootResourcePath(path string) (string, error) { |
225 | 225 |
return symlink.FollowSymlinkInScope(filepath.Join(container.root, cleanPath), container.root) |
226 | 226 |
} |
227 | 227 |
|
228 |
-// Start prepares the container to run by setting up everything the |
|
229 |
-// container needs, such as storage and networking, as well as links |
|
230 |
-// between containers. The container is left waiting for a signal to |
|
231 |
-// begin running. |
|
232 |
-func (container *Container) Start() (err error) { |
|
233 |
- container.Lock() |
|
234 |
- defer container.Unlock() |
|
235 |
- |
|
236 |
- if container.Running { |
|
237 |
- return nil |
|
238 |
- } |
|
239 |
- |
|
240 |
- if container.removalInProgress || container.Dead { |
|
241 |
- return derr.ErrorCodeContainerBeingRemoved |
|
242 |
- } |
|
243 |
- |
|
244 |
- // if we encounter an error during start we need to ensure that any other |
|
245 |
- // setup has been cleaned up properly |
|
246 |
- defer func() { |
|
247 |
- if err != nil { |
|
248 |
- container.setError(err) |
|
249 |
- // if no one else has set it, make sure we don't leave it at zero |
|
250 |
- if container.ExitCode == 0 { |
|
251 |
- container.ExitCode = 128 |
|
252 |
- } |
|
253 |
- container.toDisk() |
|
254 |
- container.cleanup() |
|
255 |
- container.logEvent("die") |
|
256 |
- } |
|
257 |
- }() |
|
258 |
- |
|
259 |
- if err := container.conditionalMountOnStart(); err != nil { |
|
260 |
- return err |
|
261 |
- } |
|
262 |
- |
|
263 |
- // Make sure NetworkMode has an acceptable value. We do this to ensure |
|
264 |
- // backwards API compatibility. |
|
265 |
- container.hostConfig = runconfig.SetDefaultNetModeIfBlank(container.hostConfig) |
|
266 |
- |
|
267 |
- if err := container.initializeNetworking(); err != nil { |
|
268 |
- return err |
|
269 |
- } |
|
270 |
- linkedEnv, err := container.setupLinkedContainers() |
|
271 |
- if err != nil { |
|
272 |
- return err |
|
273 |
- } |
|
274 |
- if err := container.setupWorkingDirectory(); err != nil { |
|
275 |
- return err |
|
276 |
- } |
|
277 |
- env := container.createDaemonEnvironment(linkedEnv) |
|
278 |
- if err := populateCommand(container, env); err != nil { |
|
279 |
- return err |
|
280 |
- } |
|
281 |
- |
|
282 |
- if !container.hostConfig.IpcMode.IsContainer() && !container.hostConfig.IpcMode.IsHost() { |
|
283 |
- if err := container.setupIpcDirs(); err != nil { |
|
284 |
- return err |
|
285 |
- } |
|
286 |
- } |
|
287 |
- |
|
288 |
- mounts, err := container.setupMounts() |
|
289 |
- if err != nil { |
|
290 |
- return err |
|
291 |
- } |
|
292 |
- mounts = append(mounts, container.ipcMounts()...) |
|
293 |
- |
|
294 |
- container.command.Mounts = mounts |
|
295 |
- return container.waitForStart() |
|
296 |
-} |
|
297 |
- |
|
298 | 228 |
// streamConfig.StdinPipe returns a WriteCloser which can be used to feed data |
299 | 229 |
// to the standard input of the container's active process. |
300 | 230 |
// Container.StdoutPipe and Container.StderrPipe each return a ReadCloser |
... | ... |
@@ -326,7 +256,7 @@ func (container *Container) cleanup() { |
326 | 326 |
|
327 | 327 |
container.unmountIpcMounts(detachMounted) |
328 | 328 |
|
329 |
- container.conditionalUnmountOnCleanup() |
|
329 |
+ container.daemon.conditionalUnmountOnCleanup(container) |
|
330 | 330 |
|
331 | 331 |
for _, eConfig := range container.execCommands.s { |
332 | 332 |
container.daemon.unregisterExecCommand(eConfig) |
... | ... |
@@ -356,11 +286,6 @@ func (container *Container) Resize(h, w int) error { |
356 | 356 |
return nil |
357 | 357 |
} |
358 | 358 |
|
359 |
-// Mount sets container.basefs |
|
360 |
-func (container *Container) Mount() error { |
|
361 |
- return container.daemon.Mount(container) |
|
362 |
-} |
|
363 |
- |
|
364 | 359 |
func (container *Container) changes() ([]archive.Change, error) { |
365 | 360 |
container.Lock() |
366 | 361 |
defer container.Unlock() |
... | ... |
@@ -374,12 +299,6 @@ func (container *Container) getImage() (*image.Image, error) { |
374 | 374 |
return container.daemon.graph.Get(container.ImageID) |
375 | 375 |
} |
376 | 376 |
|
377 |
-// Unmount asks the daemon to release the layered filesystems that are |
|
378 |
-// mounted by the container. |
|
379 |
-func (container *Container) Unmount() error { |
|
380 |
- return container.daemon.unmount(container) |
|
381 |
-} |
|
382 |
- |
|
383 | 377 |
func (container *Container) hostConfigPath() (string, error) { |
384 | 378 |
return container.getRootResourcePath("hostconfig.json") |
385 | 379 |
} |
... | ... |
@@ -401,7 +320,7 @@ func validateID(id string) error { |
401 | 401 |
return nil |
402 | 402 |
} |
403 | 403 |
|
404 |
-func (container *Container) copy(resource string) (rc io.ReadCloser, err error) { |
|
404 |
+func (daemon *Daemon) containerCopy(container *Container, resource string) (rc io.ReadCloser, err error) { |
|
405 | 405 |
container.Lock() |
406 | 406 |
|
407 | 407 |
defer func() { |
... | ... |
@@ -413,7 +332,7 @@ func (container *Container) copy(resource string) (rc io.ReadCloser, err error) |
413 | 413 |
} |
414 | 414 |
}() |
415 | 415 |
|
416 |
- if err := container.Mount(); err != nil { |
|
416 |
+ if err := daemon.Mount(container); err != nil { |
|
417 | 417 |
return nil, err |
418 | 418 |
} |
419 | 419 |
|
... | ... |
@@ -422,7 +341,7 @@ func (container *Container) copy(resource string) (rc io.ReadCloser, err error) |
422 | 422 |
// unmount any volumes |
423 | 423 |
container.unmountVolumes(true) |
424 | 424 |
// unmount the container's rootfs |
425 |
- container.Unmount() |
|
425 |
+ daemon.Unmount(container) |
|
426 | 426 |
} |
427 | 427 |
}() |
428 | 428 |
|
... | ... |
@@ -458,11 +377,11 @@ func (container *Container) copy(resource string) (rc io.ReadCloser, err error) |
458 | 458 |
reader := ioutils.NewReadCloserWrapper(archive, func() error { |
459 | 459 |
err := archive.Close() |
460 | 460 |
container.unmountVolumes(true) |
461 |
- container.Unmount() |
|
461 |
+ daemon.Unmount(container) |
|
462 | 462 |
container.Unlock() |
463 | 463 |
return err |
464 | 464 |
}) |
465 |
- container.logEvent("copy") |
|
465 |
+ daemon.logContainerEvent(container, "copy") |
|
466 | 466 |
return reader, nil |
467 | 467 |
} |
468 | 468 |
|
... | ... |
@@ -379,24 +379,23 @@ func mergeDevices(defaultDevices, userDevices []*configs.Device) []*configs.Devi |
379 | 379 |
return append(devs, userDevices...) |
380 | 380 |
} |
381 | 381 |
|
382 |
-// GetSize returns the real size & virtual size of the container. |
|
383 |
-func (container *Container) getSize() (int64, int64) { |
|
382 |
+// getSize returns the real size & virtual size of the container. |
|
383 |
+func (daemon *Daemon) getSize(container *Container) (int64, int64) { |
|
384 | 384 |
var ( |
385 | 385 |
sizeRw, sizeRootfs int64 |
386 | 386 |
err error |
387 |
- driver = container.daemon.driver |
|
388 | 387 |
) |
389 | 388 |
|
390 |
- if err := container.Mount(); err != nil { |
|
389 |
+ if err := daemon.Mount(container); err != nil { |
|
391 | 390 |
logrus.Errorf("Failed to compute size of container rootfs %s: %s", container.ID, err) |
392 | 391 |
return sizeRw, sizeRootfs |
393 | 392 |
} |
394 |
- defer container.Unmount() |
|
393 |
+ defer daemon.Unmount(container) |
|
395 | 394 |
|
396 | 395 |
initID := fmt.Sprintf("%s-init", container.ID) |
397 |
- sizeRw, err = driver.DiffSize(container.ID, initID) |
|
396 |
+ sizeRw, err = daemon.driver.DiffSize(container.ID, initID) |
|
398 | 397 |
if err != nil { |
399 |
- logrus.Errorf("Driver %s couldn't return diff size of container %s: %s", driver, container.ID, err) |
|
398 |
+ logrus.Errorf("Driver %s couldn't return diff size of container %s: %s", daemon.driver, container.ID, err) |
|
400 | 399 |
// FIXME: GetSize should return an error. Not changing it now in case |
401 | 400 |
// there is a side-effect. |
402 | 401 |
sizeRw = -1 |
... | ... |
@@ -1444,20 +1443,3 @@ func (container *Container) ipcMounts() []execdriver.Mount { |
1444 | 1444 |
func detachMounted(path string) error { |
1445 | 1445 |
return syscall.Unmount(path, syscall.MNT_DETACH) |
1446 | 1446 |
} |
1447 |
- |
|
1448 |
-// conditionalMountOnStart is a platform specific helper function during the |
|
1449 |
-// container start to call mount. |
|
1450 |
-func (container *Container) conditionalMountOnStart() error { |
|
1451 |
- if err := container.Mount(); err != nil { |
|
1452 |
- return err |
|
1453 |
- } |
|
1454 |
- return nil |
|
1455 |
-} |
|
1456 |
- |
|
1457 |
-// conditionalUnmountOnCleanup is a platform specific helper function called |
|
1458 |
-// during the cleanup of a container to unmount. |
|
1459 |
-func (container *Container) conditionalUnmountOnCleanup() { |
|
1460 |
- if err := container.Unmount(); err != nil { |
|
1461 |
- logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err) |
|
1462 |
- } |
|
1463 |
-} |
... | ... |
@@ -5,7 +5,6 @@ package daemon |
5 | 5 |
import ( |
6 | 6 |
"strings" |
7 | 7 |
|
8 |
- "github.com/Sirupsen/logrus" |
|
9 | 8 |
"github.com/docker/docker/daemon/execdriver" |
10 | 9 |
derr "github.com/docker/docker/errors" |
11 | 10 |
"github.com/docker/docker/volume" |
... | ... |
@@ -143,8 +142,8 @@ func populateCommand(c *Container, env []string) error { |
143 | 143 |
return nil |
144 | 144 |
} |
145 | 145 |
|
146 |
-// GetSize returns real size & virtual size |
|
147 |
-func (container *Container) getSize() (int64, int64) { |
|
146 |
+// getSize returns real size & virtual size |
|
147 |
+func (daemon *Daemon) getSize(container *Container) (int64, int64) { |
|
148 | 148 |
// TODO Windows |
149 | 149 |
return 0, 0 |
150 | 150 |
} |
... | ... |
@@ -191,26 +190,3 @@ func (container *Container) ipcMounts() []execdriver.Mount { |
191 | 191 |
func getDefaultRouteMtu() (int, error) { |
192 | 192 |
return -1, errSystemNotSupported |
193 | 193 |
} |
194 |
- |
|
195 |
-// conditionalMountOnStart is a platform specific helper function during the |
|
196 |
-// container start to call mount. |
|
197 |
-func (container *Container) conditionalMountOnStart() error { |
|
198 |
- // We do not mount if a Hyper-V container |
|
199 |
- if !container.hostConfig.Isolation.IsHyperV() { |
|
200 |
- if err := container.Mount(); err != nil { |
|
201 |
- return err |
|
202 |
- } |
|
203 |
- } |
|
204 |
- return nil |
|
205 |
-} |
|
206 |
- |
|
207 |
-// conditionalUnmountOnCleanup is a platform specific helper function called |
|
208 |
-// during the cleanup of a container to unmount. |
|
209 |
-func (container *Container) conditionalUnmountOnCleanup() { |
|
210 |
- // We do not unmount if a Hyper-V container |
|
211 |
- if !container.hostConfig.Isolation.IsHyperV() { |
|
212 |
- if err := container.Unmount(); err != nil { |
|
213 |
- logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err) |
|
214 |
- } |
|
215 |
- } |
|
216 |
-} |
... | ... |
@@ -114,10 +114,10 @@ func (daemon *Daemon) create(params *ContainerCreateConfig) (retC *Container, re |
114 | 114 |
} |
115 | 115 |
} |
116 | 116 |
}() |
117 |
- if err := container.Mount(); err != nil { |
|
117 |
+ if err := daemon.Mount(container); err != nil { |
|
118 | 118 |
return nil, err |
119 | 119 |
} |
120 |
- defer container.Unmount() |
|
120 |
+ defer daemon.Unmount(container) |
|
121 | 121 |
|
122 | 122 |
if err := createContainerPlatformSpecificSettings(container, params.Config, params.HostConfig, img); err != nil { |
123 | 123 |
return nil, err |
... | ... |
@@ -127,7 +127,7 @@ func (daemon *Daemon) create(params *ContainerCreateConfig) (retC *Container, re |
127 | 127 |
logrus.Errorf("Error saving new container to disk: %v", err) |
128 | 128 |
return nil, err |
129 | 129 |
} |
130 |
- container.logEvent("create") |
|
130 |
+ daemon.logContainerEvent(container, "create") |
|
131 | 131 |
return container, nil |
132 | 132 |
} |
133 | 133 |
|
... | ... |
@@ -234,7 +234,7 @@ func (daemon *Daemon) Register(container *Container) error { |
234 | 234 |
|
235 | 235 |
container.unmountIpcMounts(mount.Unmount) |
236 | 236 |
|
237 |
- if err := container.Unmount(); err != nil { |
|
237 |
+ if err := daemon.Unmount(container); err != nil { |
|
238 | 238 |
logrus.Debugf("unmount error %s", err) |
239 | 239 |
} |
240 | 240 |
if err := container.toDiskLocking(); err != nil { |
... | ... |
@@ -349,7 +349,7 @@ func (daemon *Daemon) restore() error { |
349 | 349 |
if daemon.configStore.AutoRestart && container.shouldRestart() { |
350 | 350 |
logrus.Debugf("Starting container %s", container.ID) |
351 | 351 |
|
352 |
- if err := container.Start(); err != nil { |
|
352 |
+ if err := daemon.containerStart(container); err != nil { |
|
353 | 353 |
logrus.Errorf("Failed to start container %s: %s", container.ID, err) |
354 | 354 |
} |
355 | 355 |
} |
... | ... |
@@ -947,7 +947,8 @@ func (daemon *Daemon) Mount(container *Container) error { |
947 | 947 |
return nil |
948 | 948 |
} |
949 | 949 |
|
950 |
-func (daemon *Daemon) unmount(container *Container) error { |
|
950 |
+// Unmount unsets the container base filesystem |
|
951 |
+func (daemon *Daemon) Unmount(container *Container) error { |
|
951 | 952 |
return daemon.driver.Put(container.ID) |
952 | 953 |
} |
953 | 954 |
|
... | ... |
@@ -610,6 +610,20 @@ func (daemon *Daemon) newBaseContainer(id string) *Container { |
610 | 610 |
} |
611 | 611 |
} |
612 | 612 |
|
613 |
+// conditionalMountOnStart is a platform specific helper function during the |
|
614 |
+// container start to call mount. |
|
615 |
+func (daemon *Daemon) conditionalMountOnStart(container *Container) error { |
|
616 |
+ return daemon.Mount(container) |
|
617 |
+} |
|
618 |
+ |
|
619 |
+// conditionalUnmountOnCleanup is a platform specific helper function called |
|
620 |
+// during the cleanup of a container to unmount. |
|
621 |
+func (daemon *Daemon) conditionalUnmountOnCleanup(container *Container) { |
|
622 |
+ if err := daemon.Unmount(container); err != nil { |
|
623 |
+ logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err) |
|
624 |
+ } |
|
625 |
+} |
|
626 |
+ |
|
613 | 627 |
// getDefaultRouteMtu returns the MTU for the default route's interface. |
614 | 628 |
func getDefaultRouteMtu() (int, error) { |
615 | 629 |
routes, err := netlink.RouteList(nil, 0) |
... | ... |
@@ -154,3 +154,26 @@ func (daemon *Daemon) newBaseContainer(id string) *Container { |
154 | 154 |
func (daemon *Daemon) cleanupMounts() error { |
155 | 155 |
return nil |
156 | 156 |
} |
157 |
+ |
|
158 |
+// conditionalMountOnStart is a platform specific helper function during the |
|
159 |
+// container start to call mount. |
|
160 |
+func (daemon *Daemon) conditionalMountOnStart(container *Container) error { |
|
161 |
+ // We do not mount if a Hyper-V container |
|
162 |
+ if !container.hostConfig.Isolation.IsHyperV() { |
|
163 |
+ if err := daemon.Mount(container); err != nil { |
|
164 |
+ return err |
|
165 |
+ } |
|
166 |
+ } |
|
167 |
+ return nil |
|
168 |
+} |
|
169 |
+ |
|
170 |
+// conditionalUnmountOnCleanup is a platform specific helper function called |
|
171 |
+// during the cleanup of a container to unmount. |
|
172 |
+func (daemon *Daemon) conditionalUnmountOnCleanup(container *Container) { |
|
173 |
+ // We do not unmount if a Hyper-V container |
|
174 |
+ if !container.hostConfig.Isolation.IsHyperV() { |
|
175 |
+ if err := daemon.Unmount(container); err != nil { |
|
176 |
+ logrus.Errorf("%v: Failed to umount filesystem: %v", container.ID, err) |
|
177 |
+ } |
|
178 |
+ } |
|
179 |
+} |
... | ... |
@@ -96,7 +96,8 @@ func (d Docker) Create(cfg *runconfig.Config, hostCfg *runconfig.HostConfig) (*d |
96 | 96 |
if err != nil { |
97 | 97 |
return nil, ccr.Warnings, err |
98 | 98 |
} |
99 |
- return container, ccr.Warnings, container.Mount() |
|
99 |
+ |
|
100 |
+ return container, ccr.Warnings, d.Mount(container) |
|
100 | 101 |
} |
101 | 102 |
|
102 | 103 |
// Remove removes a container specified by `id`. |
... | ... |
@@ -210,6 +211,21 @@ func (d Docker) Kill(container *daemon.Container) error { |
210 | 210 |
return d.Daemon.Kill(container) |
211 | 211 |
} |
212 | 212 |
|
213 |
+// Mount mounts the root filesystem for the container. |
|
214 |
+func (d Docker) Mount(c *daemon.Container) error { |
|
215 |
+ return d.Daemon.Mount(c) |
|
216 |
+} |
|
217 |
+ |
|
218 |
+// Unmount unmounts the root filesystem for the container. |
|
219 |
+func (d Docker) Unmount(c *daemon.Container) error { |
|
220 |
+ return d.Daemon.Unmount(c) |
|
221 |
+} |
|
222 |
+ |
|
223 |
+// Start starts a container |
|
224 |
+func (d Docker) Start(c *daemon.Container) error { |
|
225 |
+ return d.Daemon.Start(c) |
|
226 |
+} |
|
227 |
+ |
|
213 | 228 |
// Following is specific to builder contexts |
214 | 229 |
|
215 | 230 |
// DetectContextFromRemoteURL returns a context and in certain cases the name of the dockerfile to be used |
... | ... |
@@ -41,12 +41,12 @@ func (daemon *Daemon) containerExport(container *Container) (archive.Archive, er |
41 | 41 |
GIDMaps: gidMaps, |
42 | 42 |
}) |
43 | 43 |
if err != nil { |
44 |
- daemon.unmount(container) |
|
44 |
+ daemon.Unmount(container) |
|
45 | 45 |
return nil, err |
46 | 46 |
} |
47 | 47 |
arch := ioutils.NewReadCloserWrapper(archive, func() error { |
48 | 48 |
err := archive.Close() |
49 |
- container.Unmount() |
|
49 |
+ daemon.Unmount(container) |
|
50 | 50 |
return err |
51 | 51 |
}) |
52 | 52 |
daemon.logContainerEvent(container, "export") |
... | ... |
@@ -140,7 +140,7 @@ func (daemon *Daemon) getInspectData(container *Container, size bool) (*types.Co |
140 | 140 |
sizeRootFs int64 |
141 | 141 |
) |
142 | 142 |
if size { |
143 |
- sizeRw, sizeRootFs = container.getSize() |
|
143 |
+ sizeRw, sizeRootFs = daemon.getSize(container) |
|
144 | 144 |
contJSONBase.SizeRw = &sizeRw |
145 | 145 |
contJSONBase.SizeRootFs = &sizeRootFs |
146 | 146 |
} |
... | ... |
@@ -369,7 +369,7 @@ func (daemon *Daemon) transformContainer(container *Container, ctx *listContext) |
369 | 369 |
} |
370 | 370 |
|
371 | 371 |
if ctx.Size { |
372 |
- sizeRw, sizeRootFs := container.getSize() |
|
372 |
+ sizeRw, sizeRootFs := daemon.getSize(container) |
|
373 | 373 |
newC.SizeRw = sizeRw |
374 | 374 |
newC.SizeRootFs = sizeRootFs |
375 | 375 |
} |
... | ... |
@@ -29,15 +29,15 @@ func (daemon *Daemon) containerRestart(container *Container, seconds int) error |
29 | 29 |
// Avoid unnecessarily unmounting and then directly mounting |
30 | 30 |
// the container when the container stops and then starts |
31 | 31 |
// again |
32 |
- if err := container.Mount(); err == nil { |
|
33 |
- defer container.Unmount() |
|
32 |
+ if err := daemon.Mount(container); err == nil { |
|
33 |
+ defer daemon.Unmount(container) |
|
34 | 34 |
} |
35 | 35 |
|
36 | 36 |
if err := daemon.containerStop(container, seconds); err != nil { |
37 | 37 |
return err |
38 | 38 |
} |
39 | 39 |
|
40 |
- if err := container.Start(); err != nil { |
|
40 |
+ if err := daemon.containerStart(container); err != nil { |
|
41 | 41 |
return err |
42 | 42 |
} |
43 | 43 |
|
... | ... |
@@ -44,9 +44,84 @@ func (daemon *Daemon) ContainerStart(name string, hostConfig *runconfig.HostConf |
44 | 44 |
return err |
45 | 45 |
} |
46 | 46 |
|
47 |
- if err := container.Start(); err != nil { |
|
47 |
+ if err := daemon.containerStart(container); err != nil { |
|
48 | 48 |
return derr.ErrorCodeCantStart.WithArgs(name, utils.GetErrorMessage(err)) |
49 | 49 |
} |
50 | 50 |
|
51 | 51 |
return nil |
52 | 52 |
} |
53 |
+ |
|
54 |
+// Start starts a container |
|
55 |
+func (daemon *Daemon) Start(container *Container) error { |
|
56 |
+ return daemon.containerStart(container) |
|
57 |
+} |
|
58 |
+ |
|
59 |
+// containerStart prepares the container to run by setting up everything the |
|
60 |
+// container needs, such as storage and networking, as well as links |
|
61 |
+// between containers. The container is left waiting for a signal to |
|
62 |
+// begin running. |
|
63 |
+func (daemon *Daemon) containerStart(container *Container) (err error) { |
|
64 |
+ container.Lock() |
|
65 |
+ defer container.Unlock() |
|
66 |
+ |
|
67 |
+ if container.Running { |
|
68 |
+ return nil |
|
69 |
+ } |
|
70 |
+ |
|
71 |
+ if container.removalInProgress || container.Dead { |
|
72 |
+ return derr.ErrorCodeContainerBeingRemoved |
|
73 |
+ } |
|
74 |
+ |
|
75 |
+ // if we encounter an error during start we need to ensure that any other |
|
76 |
+ // setup has been cleaned up properly |
|
77 |
+ defer func() { |
|
78 |
+ if err != nil { |
|
79 |
+ container.setError(err) |
|
80 |
+ // if no one else has set it, make sure we don't leave it at zero |
|
81 |
+ if container.ExitCode == 0 { |
|
82 |
+ container.ExitCode = 128 |
|
83 |
+ } |
|
84 |
+ container.toDisk() |
|
85 |
+ container.cleanup() |
|
86 |
+ daemon.logContainerEvent(container, "die") |
|
87 |
+ } |
|
88 |
+ }() |
|
89 |
+ |
|
90 |
+ if err := daemon.conditionalMountOnStart(container); err != nil { |
|
91 |
+ return err |
|
92 |
+ } |
|
93 |
+ |
|
94 |
+ // Make sure NetworkMode has an acceptable value. We do this to ensure |
|
95 |
+ // backwards API compatibility. |
|
96 |
+ container.hostConfig = runconfig.SetDefaultNetModeIfBlank(container.hostConfig) |
|
97 |
+ |
|
98 |
+ if err := container.initializeNetworking(); err != nil { |
|
99 |
+ return err |
|
100 |
+ } |
|
101 |
+ linkedEnv, err := container.setupLinkedContainers() |
|
102 |
+ if err != nil { |
|
103 |
+ return err |
|
104 |
+ } |
|
105 |
+ if err := container.setupWorkingDirectory(); err != nil { |
|
106 |
+ return err |
|
107 |
+ } |
|
108 |
+ env := container.createDaemonEnvironment(linkedEnv) |
|
109 |
+ if err := populateCommand(container, env); err != nil { |
|
110 |
+ return err |
|
111 |
+ } |
|
112 |
+ |
|
113 |
+ if !container.hostConfig.IpcMode.IsContainer() && !container.hostConfig.IpcMode.IsHost() { |
|
114 |
+ if err := container.setupIpcDirs(); err != nil { |
|
115 |
+ return err |
|
116 |
+ } |
|
117 |
+ } |
|
118 |
+ |
|
119 |
+ mounts, err := container.setupMounts() |
|
120 |
+ if err != nil { |
|
121 |
+ return err |
|
122 |
+ } |
|
123 |
+ mounts = append(mounts, container.ipcMounts()...) |
|
124 |
+ |
|
125 |
+ container.command.Mounts = mounts |
|
126 |
+ return container.waitForStart() |
|
127 |
+} |