mirror of https://github.com/containers/podman.git
volume: new options [no]copy
add two new options to the volume create command: copy and nocopy. When nocopy is specified, the files from the container image are not copied up to the volume. Closes: https://github.com/containers/podman/issues/14722 Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
parent
a4094530bc
commit
aada13f244
|
@ -1295,13 +1295,14 @@ The _options_ is a comma-separated list and can be:
|
||||||
|
|
||||||
* **rw**|**ro**
|
* **rw**|**ro**
|
||||||
* **z**|**Z**
|
* **z**|**Z**
|
||||||
* [**r**]**shared**|[**r**]**slave**|[**r**]**private**[**r**]**unbindable**
|
|
||||||
* [**r**]**bind**
|
|
||||||
* [**no**]**exec**
|
|
||||||
* [**no**]**dev**
|
|
||||||
* [**no**]**suid**
|
|
||||||
* [**O**]
|
* [**O**]
|
||||||
* [**U**]
|
* [**U**]
|
||||||
|
* [**no**]**copy**
|
||||||
|
* [**no**]**dev**
|
||||||
|
* [**no**]**exec**
|
||||||
|
* [**no**]**suid**
|
||||||
|
* [**r**]**bind**
|
||||||
|
* [**r**]**shared**|[**r**]**slave**|[**r**]**private**[**r**]**unbindable**
|
||||||
|
|
||||||
The `CONTAINER-DIR` must be an absolute path such as `/src/docs`. The volume
|
The `CONTAINER-DIR` must be an absolute path such as `/src/docs`. The volume
|
||||||
will be mounted into the container at this directory.
|
will be mounted into the container at this directory.
|
||||||
|
|
|
@ -1362,13 +1362,14 @@ The _options_ is a comma-separated list and can be: <sup>[[1]](#Footnote1)</sup>
|
||||||
|
|
||||||
* **rw**|**ro**
|
* **rw**|**ro**
|
||||||
* **z**|**Z**
|
* **z**|**Z**
|
||||||
* [**r**]**shared**|[**r**]**slave**|[**r**]**private**[**r**]**unbindable**
|
|
||||||
* [**r**]**bind**
|
|
||||||
* [**no**]**exec**
|
|
||||||
* [**no**]**dev**
|
|
||||||
* [**no**]**suid**
|
|
||||||
* [**O**]
|
* [**O**]
|
||||||
* [**U**]
|
* [**U**]
|
||||||
|
* [**no**]**copy**
|
||||||
|
* [**no**]**dev**
|
||||||
|
* [**no**]**exec**
|
||||||
|
* [**no**]**suid**
|
||||||
|
* [**r**]**bind**
|
||||||
|
* [**r**]**shared**|[**r**]**slave**|[**r**]**private**[**r**]**unbindable**
|
||||||
|
|
||||||
The `CONTAINER-DIR` must be an absolute path such as `/src/docs`. The volume
|
The `CONTAINER-DIR` must be an absolute path such as `/src/docs`. The volume
|
||||||
will be mounted into the container at this directory.
|
will be mounted into the container at this directory.
|
||||||
|
|
|
@ -31,9 +31,10 @@ Set metadata for a volume (e.g., --label mykey=value).
|
||||||
|
|
||||||
Set driver specific options.
|
Set driver specific options.
|
||||||
For the default driver, **local**, this allows a volume to be configured to mount a filesystem on the host.
|
For the default driver, **local**, this allows a volume to be configured to mount a filesystem on the host.
|
||||||
For the `local` driver the following options are supported: `type`, `device`, and `o`.
|
For the `local` driver the following options are supported: `type`, `device`, `o`, and `[no]copy`.
|
||||||
The `type` option sets the type of the filesystem to be mounted, and is equivalent to the `-t` flag to **mount(8)**.
|
The `type` option sets the type of the filesystem to be mounted, and is equivalent to the `-t` flag to **mount(8)**.
|
||||||
The `device` option sets the device to be mounted, and is equivalent to the `device` argument to **mount(8)**.
|
The `device` option sets the device to be mounted, and is equivalent to the `device` argument to **mount(8)**.
|
||||||
|
The `copy` option enables copying files from the container image path where the mount is created to the newly created volume on the first run. `copy` is the default.
|
||||||
|
|
||||||
The `o` option sets options for the mount, and is equivalent to the `-o` flag to **mount(8)** with these exceptions:
|
The `o` option sets options for the mount, and is equivalent to the `-o` flag to **mount(8)** with these exceptions:
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"github.com/containers/common/pkg/cgroups"
|
"github.com/containers/common/pkg/cgroups"
|
||||||
"github.com/containers/common/pkg/chown"
|
"github.com/containers/common/pkg/chown"
|
||||||
"github.com/containers/common/pkg/config"
|
"github.com/containers/common/pkg/config"
|
||||||
|
cutil "github.com/containers/common/pkg/util"
|
||||||
"github.com/containers/podman/v4/libpod/define"
|
"github.com/containers/podman/v4/libpod/define"
|
||||||
"github.com/containers/podman/v4/libpod/events"
|
"github.com/containers/podman/v4/libpod/events"
|
||||||
"github.com/containers/podman/v4/pkg/ctime"
|
"github.com/containers/podman/v4/pkg/ctime"
|
||||||
|
@ -1639,7 +1640,8 @@ func (c *Container) mountNamedVolume(v *ContainerNamedVolume, mountpoint string)
|
||||||
if err := vol.update(); err != nil {
|
if err := vol.update(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if vol.state.NeedsCopyUp {
|
_, hasNoCopy := vol.config.Options["nocopy"]
|
||||||
|
if vol.state.NeedsCopyUp && !cutil.StringInSlice("nocopy", v.Options) && !hasNoCopy {
|
||||||
logrus.Debugf("Copying up contents from container %s to volume %s", c.ID(), vol.Name())
|
logrus.Debugf("Copying up contents from container %s to volume %s", c.ID(), vol.Name())
|
||||||
|
|
||||||
srcDir, err := securejoin.SecureJoin(mountpoint, v.Dest)
|
srcDir, err := securejoin.SecureJoin(mountpoint, v.Dest)
|
||||||
|
|
|
@ -73,7 +73,7 @@ func (r *Runtime) newVolume(options ...VolumeCreateOption) (_ *Volume, deferredE
|
||||||
return nil, errors.Wrapf(err, "invalid volume option %s for driver 'local'", key)
|
return nil, errors.Wrapf(err, "invalid volume option %s for driver 'local'", key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case "o", "type", "uid", "gid", "size", "inodes", "noquota":
|
case "o", "type", "uid", "gid", "size", "inodes", "noquota", "copy", "nocopy":
|
||||||
// Do nothing, valid keys
|
// Do nothing, valid keys
|
||||||
default:
|
default:
|
||||||
return nil, errors.Wrapf(define.ErrInvalidArg, "invalid mount option %s for driver 'local'", key)
|
return nil, errors.Wrapf(define.ErrInvalidArg, "invalid mount option %s for driver 'local'", key)
|
||||||
|
|
|
@ -55,6 +55,12 @@ func (v *Volume) needsMount() bool {
|
||||||
if _, ok := v.config.Options["NOQUOTA"]; ok {
|
if _, ok := v.config.Options["NOQUOTA"]; ok {
|
||||||
index++
|
index++
|
||||||
}
|
}
|
||||||
|
if _, ok := v.config.Options["nocopy"]; ok {
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
if _, ok := v.config.Options["copy"]; ok {
|
||||||
|
index++
|
||||||
|
}
|
||||||
// when uid or gid is set there is also the "o" option
|
// when uid or gid is set there is also the "o" option
|
||||||
// set so we have to ignore this one as well
|
// set so we have to ignore this one as well
|
||||||
if index > 0 {
|
if index > 0 {
|
||||||
|
|
|
@ -25,7 +25,7 @@ type defaultMountOptions struct {
|
||||||
// The sourcePath variable, if not empty, contains a bind mount source.
|
// The sourcePath variable, if not empty, contains a bind mount source.
|
||||||
func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string, error) {
|
func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string, error) {
|
||||||
var (
|
var (
|
||||||
foundWrite, foundSize, foundProp, foundMode, foundExec, foundSuid, foundDev, foundCopyUp, foundBind, foundZ, foundU, foundOverlay, foundIdmap bool
|
foundWrite, foundSize, foundProp, foundMode, foundExec, foundSuid, foundDev, foundCopyUp, foundBind, foundZ, foundU, foundOverlay, foundIdmap, foundCopy bool
|
||||||
)
|
)
|
||||||
|
|
||||||
newOptions := make([]string, 0, len(options))
|
newOptions := make([]string, 0, len(options))
|
||||||
|
@ -55,6 +55,11 @@ func ProcessOptions(options []string, isTmpfs bool, sourcePath string) ([]string
|
||||||
}
|
}
|
||||||
|
|
||||||
switch splitOpt[0] {
|
switch splitOpt[0] {
|
||||||
|
case "copy", "nocopy":
|
||||||
|
if foundCopy {
|
||||||
|
return nil, errors.Wrapf(ErrDupeMntOption, "only one of 'nocopy' and 'copy' can be used")
|
||||||
|
}
|
||||||
|
foundCopy = true
|
||||||
case "O":
|
case "O":
|
||||||
foundOverlay = true
|
foundOverlay = true
|
||||||
case "volume-opt":
|
case "volume-opt":
|
||||||
|
|
|
@ -452,6 +452,14 @@ var _ = Describe("Podman run with volumes", func() {
|
||||||
separateVolumeSession.WaitWithDefaultTimeout()
|
separateVolumeSession.WaitWithDefaultTimeout()
|
||||||
Expect(separateVolumeSession).Should(Exit(0))
|
Expect(separateVolumeSession).Should(Exit(0))
|
||||||
Expect(separateVolumeSession.OutputToString()).To(Equal(baselineOutput))
|
Expect(separateVolumeSession.OutputToString()).To(Equal(baselineOutput))
|
||||||
|
|
||||||
|
copySession := podmanTest.Podman([]string{"run", "--rm", "-v", "testvol3:/etc/apk:copy", ALPINE, "stat", "-c", "%h", "/etc/apk/arch"})
|
||||||
|
copySession.WaitWithDefaultTimeout()
|
||||||
|
Expect(copySession).Should(Exit(0))
|
||||||
|
|
||||||
|
noCopySession := podmanTest.Podman([]string{"run", "--rm", "-v", "testvol4:/etc/apk:nocopy", ALPINE, "stat", "-c", "%h", "/etc/apk/arch"})
|
||||||
|
noCopySession.WaitWithDefaultTimeout()
|
||||||
|
Expect(noCopySession).Should(Exit(1))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman named volume copyup symlink", func() {
|
It("podman named volume copyup symlink", func() {
|
||||||
|
|
Loading…
Reference in New Issue