summaryrefslogtreecommitdiff
path: root/cmd/podman
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/podman')
-rw-r--r--cmd/podman/common.go4
-rw-r--r--cmd/podman/create.go6
-rw-r--r--cmd/podman/create_cli.go90
3 files changed, 100 insertions, 0 deletions
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 8d20081f6..9ab0e57e5 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -418,6 +418,10 @@ var createFlags = []cli.Flag{
Usage: "UTS namespace to use",
},
cli.StringSliceFlag{
+ Name: "mount",
+ Usage: "Attach a filesystem mount to the container (default [])",
+ },
+ cli.StringSliceFlag{
Name: "volume, v",
Usage: "Bind mount a volume into the container (default [])",
},
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index ff912560b..fc0c71536 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -24,6 +24,7 @@ import (
"github.com/docker/docker/pkg/signal"
"github.com/docker/go-connections/nat"
"github.com/docker/go-units"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/opencontainers/selinux/go-selinux/label"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -459,6 +460,10 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
}
blkioWeight = uint16(u)
}
+ var mountList []spec.Mount
+ if mountList, err = parseMounts(c.StringSlice("mount")); err != nil {
+ return nil, err
+ }
if err = parseVolumes(c.StringSlice("volume")); err != nil {
return nil, err
@@ -772,6 +777,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
Tty: tty,
User: user,
UsernsMode: usernsMode,
+ Mounts: mountList,
Volumes: c.StringSlice("volume"),
WorkDir: workDir,
Rootfs: rootfs,
diff --git a/cmd/podman/create_cli.go b/cmd/podman/create_cli.go
index 812b62058..218e9b806 100644
--- a/cmd/podman/create_cli.go
+++ b/cmd/podman/create_cli.go
@@ -8,6 +8,8 @@ import (
cc "github.com/containers/libpod/pkg/spec"
"github.com/docker/docker/pkg/sysinfo"
+ "github.com/docker/go-units"
+ spec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
@@ -74,6 +76,94 @@ func addWarning(warnings []string, msg string) []string {
return append(warnings, msg)
}
+// Format supported.
+// podman run --mount type=bind,src=/etc/resolv.conf,target=/etc/resolv.conf ...
+// podman run --mount type=tmpfs,target=/dev/shm ..
+func parseMounts(mounts []string) ([]spec.Mount, error) {
+ var mountList []spec.Mount
+ errInvalidSyntax := errors.Errorf("incorrect mount format : should be --mount type=<bind|tmpfs>,[src=<host-dir>,]target=<ctr-dir>,[options]")
+ for _, mount := range mounts {
+ var tokenCount int
+ var mountInfo spec.Mount
+
+ arr := strings.SplitN(mount, ",", 2)
+ if len(arr) < 2 {
+ return nil, errInvalidSyntax
+ }
+ kv := strings.Split(arr[0], "=")
+ if kv[0] != "type" {
+ return nil, errInvalidSyntax
+ }
+ switch kv[1] {
+ case "bind":
+ mountInfo.Type = string(cc.TypeBind)
+ case "tmpfs":
+ mountInfo.Type = string(cc.TypeTmpfs)
+ mountInfo.Source = string(cc.TypeTmpfs)
+ mountInfo.Options = append(mountInfo.Options, []string{"rprivate", "noexec", "nosuid", "nodev", "size=65536k"}...)
+
+ default:
+ return nil, errors.Errorf("invalid filesystem type %q", kv[1])
+ }
+
+ tokens := strings.Split(arr[1], ",")
+ for i, val := range tokens {
+ if i == (tokenCount - 1) {
+ //Parse tokens before options.
+ break
+ }
+ kv := strings.Split(val, "=")
+ switch kv[0] {
+ case "ro", "nosuid", "nodev", "noexec":
+ mountInfo.Options = append(mountInfo.Options, kv[0])
+ case "shared", "rshared", "private", "rprivate", "slave", "rslave", "Z", "z":
+ if mountInfo.Type != "bind" {
+ return nil, errors.Errorf("%s can only be used with bind mounts", kv[0])
+ }
+ mountInfo.Options = append(mountInfo.Options, kv[0])
+ case "tmpfs-mode":
+ if mountInfo.Type != "tmpfs" {
+ return nil, errors.Errorf("%s can only be used with tmpfs mounts", kv[0])
+ }
+ mountInfo.Options = append(mountInfo.Options, fmt.Sprintf("mode=%s", kv[1]))
+ case "tmpfs-size":
+ if mountInfo.Type != "tmpfs" {
+ return nil, errors.Errorf("%s can only be used with tmpfs mounts", kv[0])
+ }
+ shmSize, err := units.FromHumanSize(kv[1])
+ if err != nil {
+ return nil, errors.Wrapf(err, "unable to translate tmpfs-size")
+ }
+
+ mountInfo.Options = append(mountInfo.Options, fmt.Sprintf("size=%d", shmSize))
+
+ case "bind-propagation":
+ if mountInfo.Type != "bind" {
+ return nil, errors.Errorf("%s can only be used with bind mounts", kv[0])
+ }
+ mountInfo.Options = append(mountInfo.Options, kv[1])
+ case "src", "source":
+ if mountInfo.Type == "tmpfs" {
+ return nil, errors.Errorf("can not use src= on a tmpfs file system")
+ }
+ if err := validateVolumeHostDir(kv[1]); err != nil {
+ return nil, err
+ }
+ mountInfo.Source = kv[1]
+ case "target", "dst", "destination":
+ if err := validateVolumeCtrDir(kv[1]); err != nil {
+ return nil, err
+ }
+ mountInfo.Destination = kv[1]
+ default:
+ return nil, errors.Errorf("incorrect mount option : %s", kv[0])
+ }
+ }
+ mountList = append(mountList, mountInfo)
+ }
+ return mountList, nil
+}
+
func parseVolumes(volumes []string) error {
for _, volume := range volumes {
arr := strings.SplitN(volume, ":", 3)