create_unix.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. // +build !windows
  2. package daemon // import "github.com/docker/docker/daemon"
  3. import (
  4. "context"
  5. "fmt"
  6. "os"
  7. "path/filepath"
  8. containertypes "github.com/docker/docker/api/types/container"
  9. mounttypes "github.com/docker/docker/api/types/mount"
  10. "github.com/docker/docker/container"
  11. "github.com/docker/docker/pkg/stringid"
  12. volumeopts "github.com/docker/docker/volume/service/opts"
  13. "github.com/opencontainers/selinux/go-selinux/label"
  14. "github.com/sirupsen/logrus"
  15. )
  16. // createContainerOSSpecificSettings performs host-OS specific container create functionality
  17. func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Container, config *containertypes.Config, hostConfig *containertypes.HostConfig) error {
  18. if err := daemon.Mount(container); err != nil {
  19. return err
  20. }
  21. defer daemon.Unmount(container)
  22. rootIDs := daemon.idMappings.RootPair()
  23. if err := container.SetupWorkingDirectory(rootIDs); err != nil {
  24. return err
  25. }
  26. for spec := range config.Volumes {
  27. name := stringid.GenerateNonCryptoID()
  28. destination := filepath.Clean(spec)
  29. // Skip volumes for which we already have something mounted on that
  30. // destination because of a --volume-from.
  31. if container.IsDestinationMounted(destination) {
  32. continue
  33. }
  34. path, err := container.GetResourcePath(destination)
  35. if err != nil {
  36. return err
  37. }
  38. stat, err := os.Stat(path)
  39. if err == nil && !stat.IsDir() {
  40. return fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
  41. }
  42. v, err := daemon.volumes.Create(context.TODO(), name, hostConfig.VolumeDriver, volumeopts.WithCreateReference(container.ID))
  43. if err != nil {
  44. return err
  45. }
  46. if err := label.Relabel(v.Mountpoint, container.MountLabel, true); err != nil {
  47. return err
  48. }
  49. container.AddMountPointWithVolume(destination, &volumeWrapper{v: v, s: daemon.volumes}, true)
  50. }
  51. return daemon.populateVolumes(container)
  52. }
  53. // populateVolumes copies data from the container's rootfs into the volume for non-binds.
  54. // this is only called when the container is created.
  55. func (daemon *Daemon) populateVolumes(c *container.Container) error {
  56. for _, mnt := range c.MountPoints {
  57. if mnt.Volume == nil {
  58. continue
  59. }
  60. if mnt.Type != mounttypes.TypeVolume || !mnt.CopyData {
  61. continue
  62. }
  63. logrus.Debugf("copying image data from %s:%s, to %s", c.ID, mnt.Destination, mnt.Name)
  64. if err := c.CopyImagePathContent(mnt.Volume, mnt.Destination); err != nil {
  65. return err
  66. }
  67. }
  68. return nil
  69. }