github.com/devdivbcp/moby@v17.12.0-ce-rc1.0.20200726071732-2d4bfdc789ad+incompatible/daemon/create_unix.go (about) 1 // +build !windows 2 3 package daemon // import "github.com/docker/docker/daemon" 4 5 import ( 6 "context" 7 "fmt" 8 "os" 9 "path/filepath" 10 11 containertypes "github.com/docker/docker/api/types/container" 12 mounttypes "github.com/docker/docker/api/types/mount" 13 "github.com/docker/docker/container" 14 "github.com/docker/docker/oci" 15 "github.com/docker/docker/pkg/stringid" 16 volumeopts "github.com/docker/docker/volume/service/opts" 17 "github.com/opencontainers/selinux/go-selinux/label" 18 "github.com/sirupsen/logrus" 19 ) 20 21 // createContainerOSSpecificSettings performs host-OS specific container create functionality 22 func (daemon *Daemon) createContainerOSSpecificSettings(container *container.Container, config *containertypes.Config, hostConfig *containertypes.HostConfig) error { 23 if err := daemon.Mount(container); err != nil { 24 return err 25 } 26 defer daemon.Unmount(container) 27 28 rootIDs := daemon.idMapping.RootPair() 29 if err := container.SetupWorkingDirectory(rootIDs); err != nil { 30 return err 31 } 32 33 // Set the default masked and readonly paths with regard to the host config options if they are not set. 34 if hostConfig.MaskedPaths == nil && !hostConfig.Privileged { 35 hostConfig.MaskedPaths = oci.DefaultSpec().Linux.MaskedPaths // Set it to the default if nil 36 container.HostConfig.MaskedPaths = hostConfig.MaskedPaths 37 } 38 if hostConfig.ReadonlyPaths == nil && !hostConfig.Privileged { 39 hostConfig.ReadonlyPaths = oci.DefaultSpec().Linux.ReadonlyPaths // Set it to the default if nil 40 container.HostConfig.ReadonlyPaths = hostConfig.ReadonlyPaths 41 } 42 43 for spec := range config.Volumes { 44 name := stringid.GenerateRandomID() 45 destination := filepath.Clean(spec) 46 47 // Skip volumes for which we already have something mounted on that 48 // destination because of a --volume-from. 49 if container.HasMountFor(destination) { 50 logrus.WithField("container", container.ID).WithField("destination", spec).Debug("mountpoint already exists, skipping anonymous volume") 51 // Not an error, this could easily have come from the image config. 52 continue 53 } 54 path, err := container.GetResourcePath(destination) 55 if err != nil { 56 return err 57 } 58 59 stat, err := os.Stat(path) 60 if err == nil && !stat.IsDir() { 61 return fmt.Errorf("cannot mount volume over existing file, file exists %s", path) 62 } 63 64 v, err := daemon.volumes.Create(context.TODO(), name, hostConfig.VolumeDriver, volumeopts.WithCreateReference(container.ID)) 65 if err != nil { 66 return err 67 } 68 69 if err := label.Relabel(v.Mountpoint, container.MountLabel, true); err != nil { 70 return err 71 } 72 73 container.AddMountPointWithVolume(destination, &volumeWrapper{v: v, s: daemon.volumes}, true) 74 } 75 return daemon.populateVolumes(container) 76 } 77 78 // populateVolumes copies data from the container's rootfs into the volume for non-binds. 79 // this is only called when the container is created. 80 func (daemon *Daemon) populateVolumes(c *container.Container) error { 81 for _, mnt := range c.MountPoints { 82 if mnt.Volume == nil { 83 continue 84 } 85 86 if mnt.Type != mounttypes.TypeVolume || !mnt.CopyData { 87 continue 88 } 89 90 logrus.Debugf("copying image data from %s:%s, to %s", c.ID, mnt.Destination, mnt.Name) 91 if err := c.CopyImagePathContent(mnt.Volume, mnt.Destination); err != nil { 92 return err 93 } 94 } 95 return nil 96 }