volumes.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. package daemon
  2. import (
  3. "errors"
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. "strings"
  8. "github.com/docker/docker/container"
  9. "github.com/docker/docker/volume"
  10. "github.com/docker/engine-api/types"
  11. containertypes "github.com/docker/engine-api/types/container"
  12. )
  13. var (
  14. // ErrVolumeReadonly is used to signal an error when trying to copy data into
  15. // a volume mount that is not writable.
  16. ErrVolumeReadonly = errors.New("mounted volume is marked read-only")
  17. )
  18. type mounts []container.Mount
  19. // volumeToAPIType converts a volume.Volume to the type used by the remote API
  20. func volumeToAPIType(v volume.Volume) *types.Volume {
  21. tv := &types.Volume{
  22. Name: v.Name(),
  23. Driver: v.DriverName(),
  24. }
  25. if v, ok := v.(volume.LabeledVolume); ok {
  26. tv.Labels = v.Labels()
  27. }
  28. if v, ok := v.(volume.ScopedVolume); ok {
  29. tv.Scope = v.Scope()
  30. }
  31. return tv
  32. }
  33. // Len returns the number of mounts. Used in sorting.
  34. func (m mounts) Len() int {
  35. return len(m)
  36. }
  37. // Less returns true if the number of parts (a/b/c would be 3 parts) in the
  38. // mount indexed by parameter 1 is less than that of the mount indexed by
  39. // parameter 2. Used in sorting.
  40. func (m mounts) Less(i, j int) bool {
  41. return m.parts(i) < m.parts(j)
  42. }
  43. // Swap swaps two items in an array of mounts. Used in sorting
  44. func (m mounts) Swap(i, j int) {
  45. m[i], m[j] = m[j], m[i]
  46. }
  47. // parts returns the number of parts in the destination of a mount. Used in sorting.
  48. func (m mounts) parts(i int) int {
  49. return strings.Count(filepath.Clean(m[i].Destination), string(os.PathSeparator))
  50. }
  51. // registerMountPoints initializes the container mount points with the configured volumes and bind mounts.
  52. // It follows the next sequence to decide what to mount in each final destination:
  53. //
  54. // 1. Select the previously configured mount points for the containers, if any.
  55. // 2. Select the volumes mounted from another containers. Overrides previously configured mount point destination.
  56. // 3. Select the bind mounts set by the client. Overrides previously configured mount point destinations.
  57. // 4. Cleanup old volumes that are about to be reassigned.
  58. func (daemon *Daemon) registerMountPoints(container *container.Container, hostConfig *containertypes.HostConfig) (retErr error) {
  59. binds := map[string]bool{}
  60. mountPoints := map[string]*volume.MountPoint{}
  61. defer func() {
  62. // clean up the container mountpoints once return with error
  63. if retErr != nil {
  64. for _, m := range mountPoints {
  65. if m.Volume == nil {
  66. continue
  67. }
  68. daemon.volumes.Dereference(m.Volume, container.ID)
  69. }
  70. }
  71. }()
  72. // 1. Read already configured mount points.
  73. for name, point := range container.MountPoints {
  74. mountPoints[name] = point
  75. }
  76. // 2. Read volumes from other containers.
  77. for _, v := range hostConfig.VolumesFrom {
  78. containerID, mode, err := volume.ParseVolumesFrom(v)
  79. if err != nil {
  80. return err
  81. }
  82. c, err := daemon.GetContainer(containerID)
  83. if err != nil {
  84. return err
  85. }
  86. for _, m := range c.MountPoints {
  87. cp := &volume.MountPoint{
  88. Name: m.Name,
  89. Source: m.Source,
  90. RW: m.RW && volume.ReadWrite(mode),
  91. Driver: m.Driver,
  92. Destination: m.Destination,
  93. Propagation: m.Propagation,
  94. Named: m.Named,
  95. }
  96. if len(cp.Source) == 0 {
  97. v, err := daemon.volumes.GetWithRef(cp.Name, cp.Driver, container.ID)
  98. if err != nil {
  99. return err
  100. }
  101. cp.Volume = v
  102. }
  103. mountPoints[cp.Destination] = cp
  104. }
  105. }
  106. // 3. Read bind mounts
  107. for _, b := range hostConfig.Binds {
  108. // #10618
  109. bind, err := volume.ParseMountSpec(b, hostConfig.VolumeDriver)
  110. if err != nil {
  111. return err
  112. }
  113. _, tmpfsExists := hostConfig.Tmpfs[bind.Destination]
  114. if binds[bind.Destination] || tmpfsExists {
  115. return fmt.Errorf("Duplicate mount point '%s'", bind.Destination)
  116. }
  117. if len(bind.Name) > 0 {
  118. // create the volume
  119. v, err := daemon.volumes.CreateWithRef(bind.Name, bind.Driver, container.ID, nil, nil)
  120. if err != nil {
  121. return err
  122. }
  123. bind.Volume = v
  124. bind.Source = v.Path()
  125. // bind.Name is an already existing volume, we need to use that here
  126. bind.Driver = v.DriverName()
  127. bind.Named = true
  128. if bind.Driver == "local" {
  129. bind = setBindModeIfNull(bind)
  130. }
  131. }
  132. binds[bind.Destination] = true
  133. mountPoints[bind.Destination] = bind
  134. }
  135. container.Lock()
  136. // 4. Cleanup old volumes that are about to be reassigned.
  137. for _, m := range mountPoints {
  138. if m.BackwardsCompatible() {
  139. if mp, exists := container.MountPoints[m.Destination]; exists && mp.Volume != nil {
  140. daemon.volumes.Dereference(mp.Volume, container.ID)
  141. }
  142. }
  143. }
  144. container.MountPoints = mountPoints
  145. container.Unlock()
  146. return nil
  147. }
  148. // lazyInitializeVolume initializes a mountpoint's volume if needed.
  149. // This happens after a daemon restart.
  150. func (daemon *Daemon) lazyInitializeVolume(containerID string, m *volume.MountPoint) error {
  151. if len(m.Driver) > 0 && m.Volume == nil {
  152. v, err := daemon.volumes.GetWithRef(m.Name, m.Driver, containerID)
  153. if err != nil {
  154. return err
  155. }
  156. m.Volume = v
  157. }
  158. return nil
  159. }