diff --git a/api/server/router/container/container_routes.go b/api/server/router/container/container_routes.go index db821942db..057a7b0b52 100644 --- a/api/server/router/container/container_routes.go +++ b/api/server/router/container/container_routes.go @@ -16,6 +16,7 @@ import ( "github.com/docker/docker/api/types/backend" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/filters" + "github.com/docker/docker/api/types/mount" "github.com/docker/docker/api/types/versions" containerpkg "github.com/docker/docker/container" "github.com/docker/docker/errdefs" @@ -513,9 +514,42 @@ func (s *containerRouter) postContainersCreate(ctx context.Context, w http.Respo } } + if hostConfig != nil && versions.LessThan(version, "1.42") { + for _, m := range hostConfig.Mounts { + // Ignore BindOptions.CreateMountpoint because it was added in API 1.42. + if bo := m.BindOptions; bo != nil { + bo.CreateMountpoint = false + } + + // These combinations are invalid, but weren't validated in API < 1.42. + // We reset them here, so that validation doesn't produce an error. + if o := m.VolumeOptions; o != nil && m.Type != mount.TypeVolume { + m.VolumeOptions = nil + } + if o := m.TmpfsOptions; o != nil && m.Type != mount.TypeTmpfs { + m.TmpfsOptions = nil + } + if bo := m.BindOptions; bo != nil { + // Ignore BindOptions.CreateMountpoint because it was added in API 1.42. + bo.CreateMountpoint = false + } + } + } + if hostConfig != nil && versions.GreaterThanOrEqualTo(version, "1.42") { // Ignore KernelMemory removed in API 1.42. hostConfig.KernelMemory = 0 + for _, m := range hostConfig.Mounts { + if o := m.VolumeOptions; o != nil && m.Type != mount.TypeVolume { + return errdefs.InvalidParameter(fmt.Errorf("VolumeOptions must not be specified on mount type %q", m.Type)) + } + if o := m.BindOptions; o != nil && m.Type != mount.TypeBind { + return errdefs.InvalidParameter(fmt.Errorf("BindOptions must not be specified on mount type %q", m.Type)) + } + if o := m.TmpfsOptions; o != nil && m.Type != mount.TypeTmpfs { + return errdefs.InvalidParameter(fmt.Errorf("TmpfsOptions must not be specified on mount type %q", m.Type)) + } + } } if hostConfig != nil && runtime.GOOS == "linux" && versions.LessThan(version, "1.42") { diff --git a/api/swagger.yaml b/api/swagger.yaml index 19053217a4..34fe3d4e19 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -380,6 +380,10 @@ definitions: description: "Disable recursive bind mount." type: "boolean" default: false + CreateMountpoint: + description: "Create mount point on host if missing" + type: "boolean" + default: false VolumeOptions: description: "Optional configuration for the `volume` type." type: "object" diff --git a/api/types/mount/mount.go b/api/types/mount/mount.go index 6fc77f7c81..751dcbaeba 100644 --- a/api/types/mount/mount.go +++ b/api/types/mount/mount.go @@ -82,8 +82,9 @@ const ( // BindOptions defines options specific to mounts of type "bind". type BindOptions struct { - Propagation Propagation `json:",omitempty"` - NonRecursive bool `json:",omitempty"` + Propagation Propagation `json:",omitempty"` + NonRecursive bool `json:",omitempty"` + CreateMountpoint bool `json:",omitempty"` } // VolumeOptions represents the options for a mount of type volume. diff --git a/daemon/volumes.go b/daemon/volumes.go index beb65a3e89..6148018aff 100644 --- a/daemon/volumes.go +++ b/daemon/volumes.go @@ -216,7 +216,7 @@ func (daemon *Daemon) registerMountPoints(container *container.Container, hostCo } } - if mp.Type == mounttypes.TypeBind { + if mp.Type == mounttypes.TypeBind && (cfg.BindOptions == nil || !cfg.BindOptions.CreateMountpoint) { mp.SkipMountpointCreation = true } diff --git a/docs/api/version-history.md b/docs/api/version-history.md index 7cdcaeea98..2bcddffe67 100644 --- a/docs/api/version-history.md +++ b/docs/api/version-history.md @@ -97,6 +97,10 @@ keywords: "API, Docker, rcli, REST, documentation" * `POST /containers/create` on Linux now respects the `HostConfig.ConsoleSize` property. Container is immediately created with the desired terminal size and clients no longer need to set the desired size on their own. +* `POST /containers/create` allow to set `CreateMountpoint` for host path to be + created if missing. This brings parity with `Binds` +* `POST /containers/create` rejects request if BindOptions|VolumeOptions|TmpfsOptions + is set with a non-matching mount Type. ## v1.41 API changes