create_unix.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. //go:build !windows
  2. package daemon // import "github.com/docker/docker/daemon"
  3. import (
  4. "context"
  5. "fmt"
  6. "os"
  7. "path/filepath"
  8. "github.com/containerd/log"
  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/errdefs"
  13. "github.com/docker/docker/internal/compatcontext"
  14. "github.com/docker/docker/oci"
  15. volumemounts "github.com/docker/docker/volume/mounts"
  16. volumeopts "github.com/docker/docker/volume/service/opts"
  17. "github.com/opencontainers/selinux/go-selinux/label"
  18. "github.com/pkg/errors"
  19. )
  20. // createContainerOSSpecificSettings performs host-OS specific container create functionality
  21. func (daemon *Daemon) createContainerOSSpecificSettings(ctx context.Context, container *container.Container, config *containertypes.Config, hostConfig *containertypes.HostConfig) error {
  22. if err := daemon.Mount(container); err != nil {
  23. return err
  24. }
  25. defer daemon.Unmount(container)
  26. rootIDs := daemon.idMapping.RootPair()
  27. if err := container.SetupWorkingDirectory(rootIDs); err != nil {
  28. return err
  29. }
  30. // Set the default masked and readonly paths with regard to the host config options if they are not set.
  31. if hostConfig.MaskedPaths == nil && !hostConfig.Privileged {
  32. hostConfig.MaskedPaths = oci.DefaultSpec().Linux.MaskedPaths // Set it to the default if nil
  33. container.HostConfig.MaskedPaths = hostConfig.MaskedPaths
  34. }
  35. if hostConfig.ReadonlyPaths == nil && !hostConfig.Privileged {
  36. hostConfig.ReadonlyPaths = oci.DefaultSpec().Linux.ReadonlyPaths // Set it to the default if nil
  37. container.HostConfig.ReadonlyPaths = hostConfig.ReadonlyPaths
  38. }
  39. for spec := range config.Volumes {
  40. destination := filepath.Clean(spec)
  41. // Skip volumes for which we already have something mounted on that
  42. // destination because of a --volume-from.
  43. if container.HasMountFor(destination) {
  44. log.G(ctx).WithField("container", container.ID).WithField("destination", spec).Debug("mountpoint already exists, skipping anonymous volume")
  45. // Not an error, this could easily have come from the image config.
  46. continue
  47. }
  48. path, err := container.GetResourcePath(destination)
  49. if err != nil {
  50. return err
  51. }
  52. stat, err := os.Stat(path)
  53. if err == nil && !stat.IsDir() {
  54. return fmt.Errorf("cannot mount volume over existing file, file exists %s", path)
  55. }
  56. v, err := daemon.volumes.Create(context.TODO(), "", hostConfig.VolumeDriver, volumeopts.WithCreateReference(container.ID))
  57. if err != nil {
  58. return err
  59. }
  60. if err := label.Relabel(v.Mountpoint, container.MountLabel, true); err != nil {
  61. return err
  62. }
  63. container.AddMountPointWithVolume(destination, &volumeWrapper{v: v, s: daemon.volumes}, true)
  64. }
  65. return daemon.populateVolumes(ctx, container)
  66. }
  67. // populateVolumes copies data from the container's rootfs into the volume for non-binds.
  68. // this is only called when the container is created.
  69. func (daemon *Daemon) populateVolumes(ctx context.Context, c *container.Container) error {
  70. for _, mnt := range c.MountPoints {
  71. if mnt.Volume == nil {
  72. continue
  73. }
  74. if mnt.Type != mounttypes.TypeVolume || !mnt.CopyData {
  75. continue
  76. }
  77. if err := daemon.populateVolume(ctx, c, mnt); err != nil {
  78. return err
  79. }
  80. }
  81. return nil
  82. }
  83. func (daemon *Daemon) populateVolume(ctx context.Context, c *container.Container, mnt *volumemounts.MountPoint) error {
  84. ctrDestPath, err := c.GetResourcePath(mnt.Destination)
  85. if err != nil {
  86. return err
  87. }
  88. if _, err := os.Stat(ctrDestPath); err != nil {
  89. if os.IsNotExist(err) {
  90. return nil
  91. }
  92. return err
  93. }
  94. volumePath, cleanup, err := mnt.Setup(ctx, c.MountLabel, daemon.idMapping.RootPair(), nil)
  95. if err != nil {
  96. if errdefs.IsNotFound(err) {
  97. return nil
  98. }
  99. log.G(ctx).WithError(err).Debugf("can't copy data from %s:%s, to %s", c.ID, mnt.Destination, volumePath)
  100. return errors.Wrapf(err, "failed to populate volume")
  101. }
  102. defer mnt.Cleanup(compatcontext.WithoutCancel(ctx))
  103. defer cleanup(compatcontext.WithoutCancel(ctx))
  104. log.G(ctx).Debugf("copying image data from %s:%s, to %s", c.ID, mnt.Destination, volumePath)
  105. if err := c.CopyImagePathContent(volumePath, ctrDestPath); err != nil {
  106. return err
  107. }
  108. return nil
  109. }