| 860 | } |
| 861 | |
| 862 | func (s *composeService) buildContainerVolumes( |
| 863 | ctx context.Context, |
| 864 | p types.Project, |
| 865 | service types.ServiceConfig, |
| 866 | inherit *container.Summary, |
| 867 | ) ([]string, []mount.Mount, error) { |
| 868 | var mounts []mount.Mount |
| 869 | var binds []string |
| 870 | |
| 871 | mountOptions, err := s.buildContainerMountOptions(ctx, p, service, inherit) |
| 872 | if err != nil { |
| 873 | return nil, nil, err |
| 874 | } |
| 875 | |
| 876 | for _, m := range mountOptions { |
| 877 | switch m.Type { |
| 878 | case mount.TypeBind: |
| 879 | // `Mount` is preferred but does not offer option to created host path if missing |
| 880 | // so `Bind` API is used here with raw volume string |
| 881 | // see https://github.com/moby/moby/issues/43483 |
| 882 | v := findVolumeByTarget(service.Volumes, m.Target) |
| 883 | if v != nil { |
| 884 | if v.Type != types.VolumeTypeBind { |
| 885 | v.Source = m.Source |
| 886 | } |
| 887 | if !bindRequiresMountAPI(v.Bind) { |
| 888 | source := m.Source |
| 889 | if vol := findVolumeByName(p.Volumes, m.Source); vol != nil { |
| 890 | source = m.Source |
| 891 | } |
| 892 | binds = append(binds, toBindString(source, v)) |
| 893 | continue |
| 894 | } |
| 895 | } |
| 896 | case mount.TypeVolume: |
| 897 | v := findVolumeByTarget(service.Volumes, m.Target) |
| 898 | vol := findVolumeByName(p.Volumes, m.Source) |
| 899 | if v != nil && vol != nil { |
| 900 | // Prefer the bind API if no advanced option is used, to preserve backward compatibility |
| 901 | if !volumeRequiresMountAPI(v.Volume) { |
| 902 | binds = append(binds, toBindString(vol.Name, v)) |
| 903 | continue |
| 904 | } |
| 905 | } |
| 906 | case mount.TypeImage: |
| 907 | // The daemon validates image mounts against the negotiated API version |
| 908 | // from the request path, not the server's own max version. |
| 909 | version, err := s.RuntimeAPIVersion(ctx) |
| 910 | if err != nil { |
| 911 | return nil, nil, err |
| 912 | } |
| 913 | if versions.LessThan(version, apiVersion148) { |
| 914 | return nil, nil, fmt.Errorf("volume with type=image require Docker Engine %s or later", dockerEngineV28) |
| 915 | } |
| 916 | } |
| 917 | mounts = append(mounts, m) |
| 918 | } |
| 919 | return binds, mounts, nil |