diff --git a/cli/command/container/opts.go b/cli/command/container/opts.go index 97906b672252..668902d9907a 100644 --- a/cli/command/container/opts.go +++ b/cli/command/container/opts.go @@ -62,6 +62,8 @@ type containerOptions struct { storageOpt opts.ListOpts labelsFile opts.ListOpts loggingOpts opts.ListOpts + maskedPaths opts.ListOpts + readonlyPaths opts.ListOpts privileged bool pidMode string utsMode string @@ -150,7 +152,9 @@ func addFlags(flags *pflag.FlagSet) *containerOptions { linkLocalIPs: opts.NewListOpts(nil), links: opts.NewListOpts(opts.ValidateLink), loggingOpts: opts.NewListOpts(nil), + maskedPaths: opts.NewListOpts(nil), publish: opts.NewListOpts(nil), + readonlyPaths: opts.NewListOpts(nil), securityOpt: opts.NewListOpts(nil), storageOpt: opts.NewListOpts(nil), sysctls: opts.NewMapOpts(nil, opts.ValidateSysctl), @@ -183,6 +187,8 @@ func addFlags(flags *pflag.FlagSet) *containerOptions { flags.StringVarP(&copts.user, "user", "u", "", "Username or UID (format: [:])") flags.StringVarP(&copts.workingDir, "workdir", "w", "", "Working directory inside the container") flags.BoolVar(&copts.autoRemove, "rm", false, "Automatically remove the container when it exits") + flags.Var(&copts.maskedPaths, "masked-paths", "Denote the paths to be masked for the container, empty implies none") + flags.Var(&copts.readonlyPaths, "readonly-paths", "Denote the paths to be set as readonly for the container, empty implies none") // Security flags.Var(&copts.capAdd, "cap-add", "Add Linux capabilities") @@ -471,6 +477,16 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err return nil, err } + maskedPathOpts, err := parsePaths(copts.maskedPaths.GetAll()) + if err != nil { + return nil, err + } + + readonlyPathOpts, err := parsePaths(copts.readonlyPaths.GetAll()) + if err != nil { + return nil, err + } + // Healthcheck var healthConfig *container.HealthConfig haveHealthSettings := copts.healthCmd != "" || @@ -614,6 +630,8 @@ func parse(flags *pflag.FlagSet, copts *containerOptions) (*containerConfig, err Sysctls: copts.sysctls.GetAll(), Runtime: copts.runtime, Mounts: mounts, + MaskedPaths: maskedPathOpts, + ReadonlyPaths: readonlyPathOpts, } if copts.autoRemove && !hostConfig.RestartPolicy.IsNone() { @@ -777,6 +795,18 @@ func parseDevice(device string) (container.DeviceMapping, error) { return deviceMapping, nil } +func parsePaths(paths []string) ([]string, error) { + for _, p := range paths { + if p == "none" { + if len(paths) > 1 { + return nil, errors.New("Passing 'none' and other paths is not allowed") + } + return []string{}, nil + } + } + return paths, nil +} + // validateDeviceCgroupRule validates a device cgroup rule string format // It will make sure 'val' is in the form: // 'type major:minor mode' diff --git a/e2e/container/run_test.go b/e2e/container/run_test.go index 68a3e40027f7..1764286be618 100644 --- a/e2e/container/run_test.go +++ b/e2e/container/run_test.go @@ -50,6 +50,19 @@ func TestRunWithContentTrust(t *testing.T) { }) } +func TestRunMaskedPaths(t *testing.T) { + result := icmd.RunCmd( + icmd.Command("docker", "run", image), + fixtures.WithConfig(dir.Path()), + fixtures.WithTrust, + fixtures.WithNotary, + ) + result.Assert(t, icmd.Expected{ + Err: fmt.Sprintf("Tagging %s@sha", image[:len(image)-7]), + }) + +} + // TODO: create this with registry API instead of engine API func createRemoteImage(t *testing.T) string { image := "registry:5000/alpine:test-run-pulls"