Skip to content

Commit 3707c1a

Browse files
committed
mount API is not strictly equivalent to bind
Signed-off-by: Nicolas De Loof <nicolas.deloof@gmail.com>
1 parent ee33143 commit 3707c1a

2 files changed

Lines changed: 68 additions & 12 deletions

File tree

pkg/compose/create.go

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -858,24 +858,73 @@ MOUNTS:
858858
// `Mount` is preferred but does not offer option to created host path if missing
859859
// so `Bind` API is used here with raw volume string
860860
// see https://github.com/moby/moby/issues/43483
861-
for _, v := range service.Volumes {
862-
if v.Target == m.Target {
863-
switch {
864-
case string(m.Type) != v.Type:
865-
v.Source = m.Source
866-
fallthrough
867-
case !requireMountAPI(v.Bind):
868-
binds = append(binds, v.String())
869-
continue MOUNTS
870-
}
871-
}
861+
v := findVolumeByTarget(service.Volumes, m.Target)
862+
if v == nil {
863+
continue MOUNTS
864+
}
865+
switch {
866+
case v.Type != types.VolumeTypeBind:
867+
v.Source = m.Source
868+
fallthrough
869+
case !requireMountAPI(v.Bind):
870+
vol := findVolumeByName(p.Volumes, m.Source)
871+
binds = append(binds, toBindString(vol.Name, v))
872+
continue MOUNTS
873+
}
874+
}
875+
if m.Type == mount.TypeVolume {
876+
v := findVolumeByTarget(service.Volumes, m.Target)
877+
if v == nil {
878+
continue MOUNTS
879+
}
880+
vol := findVolumeByName(p.Volumes, m.Source)
881+
if _,ok := vol.DriverOpts["device"]; ok && vol.Driver == "local" && vol.DriverOpts["o"] == "bind" && {
882+
// Looks like a volume, but actually a bind mount which requires the bind API
883+
binds = append(binds, toBindString(vol.Name, v))
884+
continue MOUNTS
872885
}
873886
}
874887
mounts = append(mounts, m)
875888
}
876889
return binds, mounts, nil
877890
}
878891

892+
func toBindString(name string, v *types.ServiceVolumeConfig) string {
893+
access := "rw"
894+
if v.ReadOnly {
895+
access = "ro"
896+
}
897+
options := []string{access}
898+
if v.Bind != nil && v.Bind.SELinux != "" {
899+
options = append(options, v.Bind.SELinux)
900+
}
901+
if v.Bind != nil && v.Bind.Propagation != "" {
902+
options = append(options, v.Bind.Propagation)
903+
}
904+
if v.Volume != nil && v.Volume.NoCopy {
905+
options = append(options, "nocopy")
906+
}
907+
return fmt.Sprintf("%s:%s:%s", name, v.Target, strings.Join(options, ","))
908+
}
909+
910+
func findVolumeByName(volumes types.Volumes, name string) *types.VolumeConfig {
911+
for _, vol := range volumes {
912+
if vol.Name == name {
913+
return &vol
914+
}
915+
}
916+
return nil
917+
}
918+
919+
func findVolumeByTarget(volumes []types.ServiceVolumeConfig, target string) *types.ServiceVolumeConfig {
920+
for _, v := range volumes {
921+
if v.Target == target {
922+
return &v
923+
}
924+
}
925+
return nil
926+
}
927+
879928
// requireMountAPI check if Bind declaration can be implemented by the plain old Bind API or uses any of the advanced
880929
// options which require use of Mount API
881930
func requireMountAPI(bind *types.ServiceVolumeBind) bool {

pkg/compose/down.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,15 @@ func (s *composeService) removeImage(ctx context.Context, image string, w progre
282282

283283
func (s *composeService) removeVolume(ctx context.Context, id string, w progress.Writer) error {
284284
resource := fmt.Sprintf("Volume %s", id)
285+
286+
_, err := s.apiClient().VolumeInspect(ctx, id)
287+
if errdefs.IsNotFound(err) {
288+
// Already gone
289+
return nil
290+
}
291+
285292
w.Event(progress.NewEvent(resource, progress.Working, "Removing"))
286-
err := s.apiClient().VolumeRemove(ctx, id, true)
293+
err = s.apiClient().VolumeRemove(ctx, id, true)
287294
if err == nil {
288295
w.Event(progress.NewEvent(resource, progress.Done, "Removed"))
289296
return nil

0 commit comments

Comments
 (0)