|
|
@@ -801,28 +801,28 @@ func (s *composeService) buildContainerVolumes(
|
|
|
return nil, nil, err
|
|
|
}
|
|
|
|
|
|
- mountOptions, err := s.buildContainerMountOptions(ctx, p, service, imgInspect, inherit)
|
|
|
+ mountOptions, err := buildContainerMountOptions(p, service, imgInspect, inherit)
|
|
|
if err != nil {
|
|
|
return nil, nil, err
|
|
|
}
|
|
|
|
|
|
- version, err := s.RuntimeVersion(ctx)
|
|
|
- if err != nil {
|
|
|
- return nil, nil, err
|
|
|
- }
|
|
|
- if versions.GreaterThan(version, "1.42") {
|
|
|
- // We can fully leverage `Mount` API as a replacement for legacy `Bind`
|
|
|
- return nil, mountOptions, nil
|
|
|
- }
|
|
|
-
|
|
|
MOUNTS:
|
|
|
for _, m := range mountOptions {
|
|
|
+ if m.Type == mount.TypeNamedPipe {
|
|
|
+ mounts = append(mounts, m)
|
|
|
+ continue
|
|
|
+ }
|
|
|
if m.Type == mount.TypeBind {
|
|
|
- // `Mount` does not offer option to created host path if missing
|
|
|
+ // `Mount` is preferred but does not offer option to created host path if missing
|
|
|
// so `Bind` API is used here with raw volume string
|
|
|
+ // see https://github.com/moby/moby/issues/43483
|
|
|
for _, v := range service.Volumes {
|
|
|
if v.Target == m.Target {
|
|
|
- if v.Bind != nil && v.Bind.CreateHostPath {
|
|
|
+ switch {
|
|
|
+ case string(m.Type) != v.Type:
|
|
|
+ v.Source = m.Source
|
|
|
+ fallthrough
|
|
|
+ case v.Bind != nil && v.Bind.CreateHostPath:
|
|
|
binds = append(binds, v.String())
|
|
|
continue MOUNTS
|
|
|
}
|
|
|
@@ -834,7 +834,7 @@ MOUNTS:
|
|
|
return binds, mounts, nil
|
|
|
}
|
|
|
|
|
|
-func (s *composeService) buildContainerMountOptions(ctx context.Context, p types.Project, service types.ServiceConfig, img moby.ImageInspect, inherit *moby.Container) ([]mount.Mount, error) {
|
|
|
+func buildContainerMountOptions(p types.Project, s types.ServiceConfig, img moby.ImageInspect, inherit *moby.Container) ([]mount.Mount, error) {
|
|
|
var mounts = map[string]mount.Mount{}
|
|
|
if inherit != nil {
|
|
|
for _, m := range inherit.Mounts {
|
|
|
@@ -859,7 +859,7 @@ func (s *composeService) buildContainerMountOptions(ctx context.Context, p types
|
|
|
}
|
|
|
}
|
|
|
volumes := []types.ServiceVolumeConfig{}
|
|
|
- for _, v := range service.Volumes {
|
|
|
+ for _, v := range s.Volumes {
|
|
|
if v.Target != m.Destination || v.Source != "" {
|
|
|
volumes = append(volumes, v)
|
|
|
continue
|
|
|
@@ -872,11 +872,11 @@ func (s *composeService) buildContainerMountOptions(ctx context.Context, p types
|
|
|
ReadOnly: !m.RW,
|
|
|
}
|
|
|
}
|
|
|
- service.Volumes = volumes
|
|
|
+ s.Volumes = volumes
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- mounts, err := s.fillBindMounts(ctx, p, service, mounts)
|
|
|
+ mounts, err := fillBindMounts(p, s, mounts)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
@@ -888,27 +888,27 @@ func (s *composeService) buildContainerMountOptions(ctx context.Context, p types
|
|
|
return values, nil
|
|
|
}
|
|
|
|
|
|
-func (s *composeService) fillBindMounts(ctx context.Context, p types.Project, service types.ServiceConfig, m map[string]mount.Mount) (map[string]mount.Mount, error) {
|
|
|
- for _, v := range service.Volumes {
|
|
|
- bindMount, err := s.buildMount(ctx, p, v)
|
|
|
+func fillBindMounts(p types.Project, s types.ServiceConfig, m map[string]mount.Mount) (map[string]mount.Mount, error) {
|
|
|
+ for _, v := range s.Volumes {
|
|
|
+ bindMount, err := buildMount(p, v)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
m[bindMount.Target] = bindMount
|
|
|
}
|
|
|
|
|
|
- secrets, err := s.buildContainerSecretMounts(ctx, p, service)
|
|
|
+ secrets, err := buildContainerSecretMounts(p, s)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- for _, secret := range secrets {
|
|
|
- if _, found := m[secret.Target]; found {
|
|
|
+ for _, s := range secrets {
|
|
|
+ if _, found := m[s.Target]; found {
|
|
|
continue
|
|
|
}
|
|
|
- m[secret.Target] = secret
|
|
|
+ m[s.Target] = s
|
|
|
}
|
|
|
|
|
|
- configs, err := s.buildContainerConfigMounts(ctx, p, service)
|
|
|
+ configs, err := buildContainerConfigMounts(p, s)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
@@ -921,11 +921,11 @@ func (s *composeService) fillBindMounts(ctx context.Context, p types.Project, se
|
|
|
return m, nil
|
|
|
}
|
|
|
|
|
|
-func (s *composeService) buildContainerConfigMounts(ctx context.Context, p types.Project, service types.ServiceConfig) ([]mount.Mount, error) {
|
|
|
+func buildContainerConfigMounts(p types.Project, s types.ServiceConfig) ([]mount.Mount, error) {
|
|
|
var mounts = map[string]mount.Mount{}
|
|
|
|
|
|
configsBaseDir := "/"
|
|
|
- for _, config := range service.Configs {
|
|
|
+ for _, config := range s.Configs {
|
|
|
target := config.Target
|
|
|
if config.Target == "" {
|
|
|
target = configsBaseDir + config.Source
|
|
|
@@ -953,7 +953,7 @@ func (s *composeService) buildContainerConfigMounts(ctx context.Context, p types
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
- bindMount, err := s.buildMount(ctx, p, types.ServiceVolumeConfig{
|
|
|
+ bindMount, err := buildMount(p, types.ServiceVolumeConfig{
|
|
|
Type: types.VolumeTypeBind,
|
|
|
Source: definedConfig.File,
|
|
|
Target: target,
|
|
|
@@ -971,11 +971,11 @@ func (s *composeService) buildContainerConfigMounts(ctx context.Context, p types
|
|
|
return values, nil
|
|
|
}
|
|
|
|
|
|
-func (s *composeService) buildContainerSecretMounts(ctx context.Context, p types.Project, service types.ServiceConfig) ([]mount.Mount, error) {
|
|
|
+func buildContainerSecretMounts(p types.Project, s types.ServiceConfig) ([]mount.Mount, error) {
|
|
|
var mounts = map[string]mount.Mount{}
|
|
|
|
|
|
secretsDir := "/run/secrets/"
|
|
|
- for _, secret := range service.Secrets {
|
|
|
+ for _, secret := range s.Secrets {
|
|
|
target := secret.Target
|
|
|
if secret.Target == "" {
|
|
|
target = secretsDir + secret.Source
|
|
|
@@ -1003,7 +1003,7 @@ func (s *composeService) buildContainerSecretMounts(ctx context.Context, p types
|
|
|
continue
|
|
|
}
|
|
|
|
|
|
- mnt, err := s.buildMount(ctx, p, types.ServiceVolumeConfig{
|
|
|
+ mnt, err := buildMount(p, types.ServiceVolumeConfig{
|
|
|
Type: types.VolumeTypeBind,
|
|
|
Source: definedSecret.File,
|
|
|
Target: target,
|
|
|
@@ -1039,7 +1039,7 @@ func isWindowsAbs(p string) bool {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
-func (s *composeService) buildMount(ctx context.Context, project types.Project, volume types.ServiceVolumeConfig) (mount.Mount, error) {
|
|
|
+func buildMount(project types.Project, volume types.ServiceVolumeConfig) (mount.Mount, error) {
|
|
|
source := volume.Source
|
|
|
// on windows, filepath.IsAbs(source) is false for unix style abs path like /var/run/docker.sock.
|
|
|
// do not replace these with filepath.Abs(source) that will include a default drive.
|
|
|
@@ -1060,10 +1060,7 @@ func (s *composeService) buildMount(ctx context.Context, project types.Project,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- bind, vol, tmpfs, err := s.buildMountOptions(ctx, volume)
|
|
|
- if err != nil {
|
|
|
- return mount.Mount{}, err
|
|
|
- }
|
|
|
+ bind, vol, tmpfs := buildMountOptions(project, volume)
|
|
|
|
|
|
volume.Target = path.Clean(volume.Target)
|
|
|
|
|
|
@@ -1083,7 +1080,7 @@ func (s *composeService) buildMount(ctx context.Context, project types.Project,
|
|
|
}, nil
|
|
|
}
|
|
|
|
|
|
-func (s *composeService) buildMountOptions(ctx context.Context, volume types.ServiceVolumeConfig) (*mount.BindOptions, *mount.VolumeOptions, *mount.TmpfsOptions, error) {
|
|
|
+func buildMountOptions(project types.Project, volume types.ServiceVolumeConfig) (*mount.BindOptions, *mount.VolumeOptions, *mount.TmpfsOptions) {
|
|
|
switch volume.Type {
|
|
|
case "bind":
|
|
|
if volume.Volume != nil {
|
|
|
@@ -1092,8 +1089,7 @@ func (s *composeService) buildMountOptions(ctx context.Context, volume types.Ser
|
|
|
if volume.Tmpfs != nil {
|
|
|
logrus.Warnf("mount of type `bind` should not define `tmpfs` option")
|
|
|
}
|
|
|
- option, err := s.buildBindOption(ctx, volume.Bind)
|
|
|
- return option, nil, nil, err
|
|
|
+ return buildBindOption(volume.Bind), nil, nil
|
|
|
case "volume":
|
|
|
if volume.Bind != nil {
|
|
|
logrus.Warnf("mount of type `volume` should not define `bind` option")
|
|
|
@@ -1101,7 +1097,12 @@ func (s *composeService) buildMountOptions(ctx context.Context, volume types.Ser
|
|
|
if volume.Tmpfs != nil {
|
|
|
logrus.Warnf("mount of type `volume` should not define `tmpfs` option")
|
|
|
}
|
|
|
- return nil, buildVolumeOptions(volume.Volume), nil, nil
|
|
|
+ if v, ok := project.Volumes[volume.Source]; ok && v.DriverOpts["o"] == types.VolumeTypeBind {
|
|
|
+ return buildBindOption(&types.ServiceVolumeBind{
|
|
|
+ CreateHostPath: true,
|
|
|
+ }), nil, nil
|
|
|
+ }
|
|
|
+ return nil, buildVolumeOptions(volume.Volume), nil
|
|
|
case "tmpfs":
|
|
|
if volume.Bind != nil {
|
|
|
logrus.Warnf("mount of type `tmpfs` should not define `bind` option")
|
|
|
@@ -1109,30 +1110,19 @@ func (s *composeService) buildMountOptions(ctx context.Context, volume types.Ser
|
|
|
if volume.Volume != nil {
|
|
|
logrus.Warnf("mount of type `tmpfs` should not define `volume` option")
|
|
|
}
|
|
|
- return nil, nil, buildTmpfsOptions(volume.Tmpfs), nil
|
|
|
+ return nil, nil, buildTmpfsOptions(volume.Tmpfs)
|
|
|
}
|
|
|
- return nil, nil, nil, nil
|
|
|
+ return nil, nil, nil
|
|
|
}
|
|
|
|
|
|
-func (s *composeService) buildBindOption(ctx context.Context, bind *types.ServiceVolumeBind) (*mount.BindOptions, error) {
|
|
|
+func buildBindOption(bind *types.ServiceVolumeBind) *mount.BindOptions {
|
|
|
if bind == nil {
|
|
|
- return nil, nil
|
|
|
- }
|
|
|
-
|
|
|
- propagation := bind.Propagation
|
|
|
- isWindowsContainer, err := s.isWindowsContainer(ctx)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- if propagation == "" && !isWindowsContainer {
|
|
|
- propagation = types.PropagationRPrivate
|
|
|
+ return nil
|
|
|
}
|
|
|
-
|
|
|
return &mount.BindOptions{
|
|
|
- Propagation: mount.Propagation(propagation),
|
|
|
- CreateMountpoint: bind.CreateHostPath,
|
|
|
+ Propagation: mount.Propagation(bind.Propagation),
|
|
|
// NonRecursive: false, FIXME missing from model ?
|
|
|
- }, nil
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func buildVolumeOptions(vol *types.ServiceVolumeVolume) *mount.VolumeOptions {
|