create_unix.go 3.1 KB

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