@@ -858,24 +858,67 @@ 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+ switch {
863+ case string (m .Type ) != v .Type :
864+ v .Source = m .Source
865+ fallthrough
866+ case ! requireMountAPI (v .Bind ):
867+ vol := findVolumeByName (p .Volumes , m .Source )
868+ binds = append (binds , toBindString (vol .Name , v ))
869+ continue MOUNTS
870+ }
871+ }
872+ if m .Type == mount .TypeVolume {
873+ v := findVolumeByTarget (service .Volumes , m .Target )
874+ vol := findVolumeByName (p .Volumes , m .Source )
875+ if vol .Driver == "local" && vol .DriverOpts ["o" ] == "bind" {
876+ // Looks like a volume, but actually a bind mount which requires the bind API
877+ binds = append (binds , toBindString (vol .Name , v ))
878+ continue MOUNTS
872879 }
873880 }
874881 mounts = append (mounts , m )
875882 }
876883 return binds , mounts , nil
877884}
878885
886+ func toBindString (name string , v * types.ServiceVolumeConfig ) string {
887+ access := "rw"
888+ if v .ReadOnly {
889+ access = "ro"
890+ }
891+ options := []string {access }
892+ if v .Bind != nil && v .Bind .SELinux != "" {
893+ options = append (options , v .Bind .SELinux )
894+ }
895+ if v .Bind != nil && v .Bind .Propagation != "" {
896+ options = append (options , v .Bind .Propagation )
897+ }
898+ if v .Volume != nil && v .Volume .NoCopy {
899+ options = append (options , "nocopy" )
900+ }
901+ return fmt .Sprintf ("%s:%s:%s" , name , v .Target , strings .Join (options , "," ))
902+ }
903+
904+ func findVolumeByName (volumes types.Volumes , name string ) * types.VolumeConfig {
905+ for _ , vol := range volumes {
906+ if vol .Name == name {
907+ return & vol
908+ }
909+ }
910+ return nil
911+ }
912+
913+ func findVolumeByTarget (volumes []types.ServiceVolumeConfig , target string ) * types.ServiceVolumeConfig {
914+ for _ , v := range volumes {
915+ if v .Target == target {
916+ return & v
917+ }
918+ }
919+ return nil
920+ }
921+
879922// requireMountAPI check if Bind declaration can be implemented by the plain old Bind API or uses any of the advanced
880923// options which require use of Mount API
881924func requireMountAPI (bind * types.ServiceVolumeBind ) bool {
0 commit comments