浏览代码

Add `-u|--user` flag to docker exec for running command as a different user

Signed-off-by: Lei Jitang <leijitang@huawei.com>
Lei Jitang 10 年之前
父节点
当前提交
2cce4791b0

+ 1 - 1
contrib/completion/bash/docker

@@ -407,7 +407,7 @@ _docker_events() {
 _docker_exec() {
 	case "$cur" in
 		-*)
-			COMPREPLY=( $( compgen -W "--detach -d --help --interactive -i -t --tty" -- "$cur" ) )
+			COMPREPLY=( $( compgen -W "--detach -d --help --interactive -i -t --tty -u --user" -- "$cur" ) )
 			;;
 		*)
 			__docker_containers_running

+ 1 - 0
daemon/exec.go

@@ -138,6 +138,7 @@ func (d *Daemon) ContainerExecCreate(job *engine.Job) error {
 		Tty:        config.Tty,
 		Entrypoint: entrypoint,
 		Arguments:  args,
+		User:       config.User,
 	}
 
 	execConfig := &execConfig{

+ 2 - 2
daemon/execdriver/native/exec.go

@@ -14,7 +14,7 @@ import (
 	"github.com/docker/libcontainer/utils"
 )
 
-// TODO(vishh): Add support for running in privileged mode and running as a different user.
+// TODO(vishh): Add support for running in privileged mode.
 func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
 	active := d.activeContainers[c.ID]
 	if active == nil {
@@ -28,7 +28,7 @@ func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
 		Args: append([]string{processConfig.Entrypoint}, processConfig.Arguments...),
 		Env:  c.ProcessConfig.Env,
 		Cwd:  c.WorkingDir,
-		User: c.ProcessConfig.User,
+		User: processConfig.User,
 	}
 
 	if processConfig.Tty {

+ 9 - 0
docs/man/docker-exec.1.md

@@ -10,6 +10,7 @@ docker-exec - Run a command in a running container
 [**--help**]
 [**-i**|**--interactive**[=*false*]]
 [**-t**|**--tty**[=*false*]]
+[**-u**|**--user**[=*USER*]]
 CONTAINER COMMAND [ARG...]
 
 # DESCRIPTION
@@ -35,6 +36,14 @@ container is unpaused, and then run
 **-t**, **--tty**=*true*|*false*
    Allocate a pseudo-TTY. The default is *false*.
 
+**-u**, **--user**=""
+   Sets the username or UID used and optionally the groupname or GID for the specified command.
+
+   The followings examples are all valid:
+   --user [user | user:group | uid | uid:gid | user:gid | uid:group ]
+
+   Without this argument the command will be run as root in the container.
+
 The **-t** option is incompatible with a redirection of the docker client
 standard input.
 

+ 1 - 0
docs/sources/reference/commandline/cli.md

@@ -1115,6 +1115,7 @@ You'll need two shells for this example.
       -d, --detach=false         Detached mode: run command in the background
       -i, --interactive=false    Keep STDIN open even if not attached
       -t, --tty=false            Allocate a pseudo-TTY
+      -u, --user=                Username or UID (format: <name|uid>[:<group|gid>])
 
 The `docker exec` command runs a new command in a running container.
 

+ 29 - 0
integration-cli/docker_cli_exec_test.go

@@ -665,3 +665,32 @@ func TestRunMutableNetworkFiles(t *testing.T) {
 	}
 	logDone("run - mutable network files")
 }
+
+func TestExecWithUser(t *testing.T) {
+	defer deleteAllContainers()
+
+	runCmd := exec.Command(dockerBinary, "run", "-d", "--name", "parent", "busybox", "top")
+	if out, _, err := runCommandWithOutput(runCmd); err != nil {
+		t.Fatal(out, err)
+	}
+
+	cmd := exec.Command(dockerBinary, "exec", "-u", "1", "parent", "id")
+	out, _, err := runCommandWithOutput(cmd)
+	if err != nil {
+		t.Fatal(err, out)
+	}
+	if !strings.Contains(out, "uid=1(daemon) gid=1(daemon)") {
+		t.Fatalf("exec with user by id expected daemon user got %s", out)
+	}
+
+	cmd = exec.Command(dockerBinary, "exec", "-u", "root", "parent", "id")
+	out, _, err = runCommandWithOutput(cmd)
+	if err != nil {
+		t.Fatal(err, out)
+	}
+	if !strings.Contains(out, "uid=0(root) gid=0(root)") {
+		t.Fatalf("exec with user by root expected root user got %s", out)
+	}
+
+	logDone("exec - with user")
+}

+ 3 - 4
runconfig/exec.go

@@ -21,8 +21,7 @@ type ExecConfig struct {
 
 func ExecConfigFromJob(job *engine.Job) (*ExecConfig, error) {
 	execConfig := &ExecConfig{
-		// TODO(vishh): Expose 'User' once it is supported.
-		//User:         job.Getenv("User"),
+		User:         job.Getenv("User"),
 		// TODO(vishh): Expose 'Privileged' once it is supported.
 		//Privileged:   job.GetenvBool("Privileged"),
 		Tty:          job.GetenvBool("Tty"),
@@ -45,6 +44,7 @@ func ParseExec(cmd *flag.FlagSet, args []string) (*ExecConfig, error) {
 		flStdin   = cmd.Bool([]string{"i", "-interactive"}, false, "Keep STDIN open even if not attached")
 		flTty     = cmd.Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-TTY")
 		flDetach  = cmd.Bool([]string{"d", "-detach"}, false, "Detached mode: run command in the background")
+		flUser    = cmd.String([]string{"u", "-user"}, "", "Username or UID (format: <name|uid>[:<group|gid>])")
 		execCmd   []string
 		container string
 	)
@@ -57,8 +57,7 @@ func ParseExec(cmd *flag.FlagSet, args []string) (*ExecConfig, error) {
 	execCmd = parsedArgs[1:]
 
 	execConfig := &ExecConfig{
-		// TODO(vishh): Expose '-u' flag once it is supported.
-		User: "",
+		User: *flUser,
 		// TODO(vishh): Expose '-p' flag once it is supported.
 		Privileged: false,
 		Tty:        *flTty,