mirror of https://github.com/docker/cli.git
Merge pull request #1430 from AkihiroSuda/non-recursive-bind
support --mount type=bind,bind-nonrecursive,...
This commit is contained in:
commit
f5280d60ee
|
@ -66,6 +66,10 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *createOptions,
|
||||||
reportError(dockerCli.Err(), "create", err.Error(), true)
|
reportError(dockerCli.Err(), "create", err.Error(), true)
|
||||||
return cli.StatusError{StatusCode: 125}
|
return cli.StatusError{StatusCode: 125}
|
||||||
}
|
}
|
||||||
|
if err = validateAPIVersion(containerConfig, dockerCli.Client().ClientVersion()); err != nil {
|
||||||
|
reportError(dockerCli.Err(), "create", err.Error(), true)
|
||||||
|
return cli.StatusError{StatusCode: 125}
|
||||||
|
}
|
||||||
response, err := createContainer(context.Background(), dockerCli, containerConfig, opts)
|
response, err := createContainer(context.Background(), dockerCli, containerConfig, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
networktypes "github.com/docker/docker/api/types/network"
|
networktypes "github.com/docker/docker/api/types/network"
|
||||||
"github.com/docker/docker/api/types/strslice"
|
"github.com/docker/docker/api/types/strslice"
|
||||||
|
"github.com/docker/docker/api/types/versions"
|
||||||
"github.com/docker/docker/pkg/signal"
|
"github.com/docker/docker/pkg/signal"
|
||||||
"github.com/docker/go-connections/nat"
|
"github.com/docker/go-connections/nat"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -869,3 +870,12 @@ func validateAttach(val string) (string, error) {
|
||||||
}
|
}
|
||||||
return val, errors.Errorf("valid streams are STDIN, STDOUT and STDERR")
|
return val, errors.Errorf("valid streams are STDIN, STDOUT and STDERR")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func validateAPIVersion(c *containerConfig, serverAPIVersion string) error {
|
||||||
|
for _, m := range c.HostConfig.Mounts {
|
||||||
|
if m.BindOptions != nil && m.BindOptions.NonRecursive && versions.LessThan(serverAPIVersion, "1.40") {
|
||||||
|
return errors.Errorf("bind-nonrecursive requires API v1.40 or later")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -84,6 +84,10 @@ func runRun(dockerCli command.Cli, flags *pflag.FlagSet, ropts *runOptions, copt
|
||||||
reportError(dockerCli.Err(), "run", err.Error(), true)
|
reportError(dockerCli.Err(), "run", err.Error(), true)
|
||||||
return cli.StatusError{StatusCode: 125}
|
return cli.StatusError{StatusCode: 125}
|
||||||
}
|
}
|
||||||
|
if err = validateAPIVersion(containerConfig, dockerCli.Client().ClientVersion()); err != nil {
|
||||||
|
reportError(dockerCli.Err(), "run", err.Error(), true)
|
||||||
|
return cli.StatusError{StatusCode: 125}
|
||||||
|
}
|
||||||
return runContainer(dockerCli, ropts, copts, containerConfig)
|
return runContainer(dockerCli, ropts, copts, containerConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,10 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *serviceOptions
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = validateAPIVersion(service, dockerCli.Client().ClientVersion()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
specifiedSecrets := opts.secrets.Value()
|
specifiedSecrets := opts.secrets.Value()
|
||||||
if len(specifiedSecrets) > 0 {
|
if len(specifiedSecrets) > 0 {
|
||||||
// parse and validate secrets
|
// parse and validate secrets
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"github.com/docker/docker/api/types"
|
"github.com/docker/docker/api/types"
|
||||||
"github.com/docker/docker/api/types/container"
|
"github.com/docker/docker/api/types/container"
|
||||||
"github.com/docker/docker/api/types/swarm"
|
"github.com/docker/docker/api/types/swarm"
|
||||||
|
"github.com/docker/docker/api/types/versions"
|
||||||
"github.com/docker/docker/client"
|
"github.com/docker/docker/client"
|
||||||
"github.com/docker/swarmkit/api"
|
"github.com/docker/swarmkit/api"
|
||||||
"github.com/docker/swarmkit/api/defaults"
|
"github.com/docker/swarmkit/api/defaults"
|
||||||
|
@ -909,3 +910,12 @@ const (
|
||||||
flagConfigRemove = "config-rm"
|
flagConfigRemove = "config-rm"
|
||||||
flagIsolation = "isolation"
|
flagIsolation = "isolation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func validateAPIVersion(c swarm.ServiceSpec, serverAPIVersion string) error {
|
||||||
|
for _, m := range c.TaskTemplate.ContainerSpec.Mounts {
|
||||||
|
if m.BindOptions != nil && m.BindOptions.NonRecursive && versions.LessThan(serverAPIVersion, "1.40") {
|
||||||
|
return errors.Errorf("bind-nonrecursive requires API v1.40 or later")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -363,16 +363,34 @@ volumes in a service:
|
||||||
<td></td>
|
<td></td>
|
||||||
<td>
|
<td>
|
||||||
<p>The Engine mounts binds and volumes <tt>read-write</tt> unless <tt>readonly</tt> option
|
<p>The Engine mounts binds and volumes <tt>read-write</tt> unless <tt>readonly</tt> option
|
||||||
is given when mounting the bind or volume.
|
is given when mounting the bind or volume. Note that setting <tt>readonly</tt> for a
|
||||||
|
bind-mount does not make its submounts <tt>readonly</tt> on the current Linux implementation. See also <tt>bind-nonrecursive</tt>.
|
||||||
<ul>
|
<ul>
|
||||||
<li><tt>true</tt> or <tt>1</tt> or no value: Mounts the bind or volume read-only.</li>
|
<li><tt>true</tt> or <tt>1</tt> or no value: Mounts the bind or volume read-only.</li>
|
||||||
<li><tt>false</tt> or <tt>0</tt>: Mounts the bind or volume read-write.</li>
|
<li><tt>false</tt> or <tt>0</tt>: Mounts the bind or volume read-write.</li>
|
||||||
</ul></p>
|
</ul></p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
#### Options for Bind Mounts
|
||||||
|
|
||||||
|
The following options can only be used for bind mounts (`type=bind`):
|
||||||
|
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>Option</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>bind-propagation</b></td>
|
||||||
|
<td>
|
||||||
|
<p>See the <a href="#bind-propagation">bind propagation section</a>.</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><b>consistency</b></td>
|
<td><b>consistency</b></td>
|
||||||
<td></td>
|
|
||||||
<td>
|
<td>
|
||||||
<p>The consistency requirements for the mount; one of
|
<p>The consistency requirements for the mount; one of
|
||||||
<ul>
|
<ul>
|
||||||
|
@ -384,9 +402,24 @@ volumes in a service:
|
||||||
</p>
|
</p>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>bind-nonrecursive</b></td>
|
||||||
|
<td>
|
||||||
|
By default, submounts are recursively bind-mounted as well. However, this behavior can be confusing when a
|
||||||
|
bind mount is configured with <tt>readonly</tt> option, because submounts are not mounted as read-only.
|
||||||
|
Set <tt>bind-nonrecursive</tt> to disable recursive bind-mount.<br />
|
||||||
|
<br />
|
||||||
|
A value is optional:<br />
|
||||||
|
<br />
|
||||||
|
<ul>
|
||||||
|
<li><tt>true</tt> or <tt>1</tt>: Disables recursive bind-mount.</li>
|
||||||
|
<li><tt>false</tt> or <tt>0</tt>: Default if you do not provide a value. Enables recursive bind-mount.</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
#### Bind Propagation
|
##### Bind propagation
|
||||||
|
|
||||||
Bind propagation refers to whether or not mounts created within a given
|
Bind propagation refers to whether or not mounts created within a given
|
||||||
bind mount or named volume can be propagated to replicas of that mount. Consider
|
bind mount or named volume can be propagated to replicas of that mount. Consider
|
||||||
|
@ -423,7 +456,7 @@ volumes do not support bind propagation.
|
||||||
For more information about bind propagation, see the
|
For more information about bind propagation, see the
|
||||||
[Linux kernel documentation for shared subtree](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt).
|
[Linux kernel documentation for shared subtree](https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt).
|
||||||
|
|
||||||
#### Options for Named Volumes
|
#### Options for named volumes
|
||||||
|
|
||||||
The following options can only be used for named volumes (`type=volume`):
|
The following options can only be used for named volumes (`type=volume`):
|
||||||
|
|
||||||
|
@ -459,9 +492,9 @@ The following options can only be used for named volumes (`type=volume`):
|
||||||
the Engine copies those files and directories into the volume, allowing
|
the Engine copies those files and directories into the volume, allowing
|
||||||
the host to access them. Set <tt>volume-nocopy</tt> to disable copying files
|
the host to access them. Set <tt>volume-nocopy</tt> to disable copying files
|
||||||
from the container's filesystem to the volume and mount the empty volume.<br />
|
from the container's filesystem to the volume and mount the empty volume.<br />
|
||||||
|
<br />
|
||||||
A value is optional:
|
A value is optional:<br />
|
||||||
|
<br />
|
||||||
<ul>
|
<ul>
|
||||||
<li><tt>true</tt> or <tt>1</tt>: Default if you do not provide a value. Disables copying.</li>
|
<li><tt>true</tt> or <tt>1</tt>: Default if you do not provide a value. Disables copying.</li>
|
||||||
<li><tt>false</tt> or <tt>0</tt>: Enables copying.</li>
|
<li><tt>false</tt> or <tt>0</tt>: Enables copying.</li>
|
||||||
|
|
|
@ -453,12 +453,18 @@ according to RFC4862.
|
||||||
|
|
||||||
* `src`, `source`: mount source spec for `bind` and `volume`. Mandatory for `bind`.
|
* `src`, `source`: mount source spec for `bind` and `volume`. Mandatory for `bind`.
|
||||||
* `dst`, `destination`, `target`: mount destination spec.
|
* `dst`, `destination`, `target`: mount destination spec.
|
||||||
* `ro`, `read-only`: `true` or `false` (default).
|
* `ro`, `readonly`: `true` or `false` (default).
|
||||||
|
|
||||||
|
**Note**: setting `readonly` for a bind mount does not make its submounts
|
||||||
|
read-only on the current Linux implementation. See also `bind-nonrecursive`.
|
||||||
|
|
||||||
Options specific to `bind`:
|
Options specific to `bind`:
|
||||||
|
|
||||||
* `bind-propagation`: `shared`, `slave`, `private`, `rshared`, `rslave`, or `rprivate`(default). See also `mount(2)`.
|
* `bind-propagation`: `shared`, `slave`, `private`, `rshared`, `rslave`, or `rprivate`(default). See also `mount(2)`.
|
||||||
* `consistency`: `consistent`(default), `cached`, or `delegated`. Currently, only effective for Docker for Mac.
|
* `consistency`: `consistent`(default), `cached`, or `delegated`. Currently, only effective for Docker for Mac.
|
||||||
|
* `bind-nonrecursive`: `true` or `false` (default). If set to `true`,
|
||||||
|
submounts are not recursively bind-mounted. This option is useful for
|
||||||
|
`readonly` bind mount.
|
||||||
|
|
||||||
Options specific to `volume`:
|
Options specific to `volume`:
|
||||||
|
|
||||||
|
|
|
@ -76,6 +76,9 @@ func (m *MountOpt) Set(value string) error {
|
||||||
case "volume-nocopy":
|
case "volume-nocopy":
|
||||||
volumeOptions().NoCopy = true
|
volumeOptions().NoCopy = true
|
||||||
continue
|
continue
|
||||||
|
case "bind-nonrecursive":
|
||||||
|
bindOptions().NonRecursive = true
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +103,11 @@ func (m *MountOpt) Set(value string) error {
|
||||||
mount.Consistency = mounttypes.Consistency(strings.ToLower(value))
|
mount.Consistency = mounttypes.Consistency(strings.ToLower(value))
|
||||||
case "bind-propagation":
|
case "bind-propagation":
|
||||||
bindOptions().Propagation = mounttypes.Propagation(strings.ToLower(value))
|
bindOptions().Propagation = mounttypes.Propagation(strings.ToLower(value))
|
||||||
|
case "bind-nonrecursive":
|
||||||
|
bindOptions().NonRecursive, err = strconv.ParseBool(value)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid value for %s: %s", key, value)
|
||||||
|
}
|
||||||
case "volume-nocopy":
|
case "volume-nocopy":
|
||||||
volumeOptions().NoCopy, err = strconv.ParseBool(value)
|
volumeOptions().NoCopy, err = strconv.ParseBool(value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue