mirror of https://github.com/docker/docs.git
Add `-u|--user` flag to docker exec for running command as a different user
Signed-off-by: Lei Jitang <leijitang@huawei.com>
This commit is contained in:
parent
5c3b228b61
commit
2cce4791b0
|
@ -407,7 +407,7 @@ _docker_events() {
|
||||||
_docker_exec() {
|
_docker_exec() {
|
||||||
case "$cur" in
|
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
|
__docker_containers_running
|
||||||
|
|
|
@ -138,6 +138,7 @@ func (d *Daemon) ContainerExecCreate(job *engine.Job) error {
|
||||||
Tty: config.Tty,
|
Tty: config.Tty,
|
||||||
Entrypoint: entrypoint,
|
Entrypoint: entrypoint,
|
||||||
Arguments: args,
|
Arguments: args,
|
||||||
|
User: config.User,
|
||||||
}
|
}
|
||||||
|
|
||||||
execConfig := &execConfig{
|
execConfig := &execConfig{
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"github.com/docker/libcontainer/utils"
|
"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) {
|
func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessConfig, pipes *execdriver.Pipes, startCallback execdriver.StartCallback) (int, error) {
|
||||||
active := d.activeContainers[c.ID]
|
active := d.activeContainers[c.ID]
|
||||||
if active == nil {
|
if active == nil {
|
||||||
|
@ -28,7 +28,7 @@ func (d *driver) Exec(c *execdriver.Command, processConfig *execdriver.ProcessCo
|
||||||
Args: append([]string{processConfig.Entrypoint}, processConfig.Arguments...),
|
Args: append([]string{processConfig.Entrypoint}, processConfig.Arguments...),
|
||||||
Env: c.ProcessConfig.Env,
|
Env: c.ProcessConfig.Env,
|
||||||
Cwd: c.WorkingDir,
|
Cwd: c.WorkingDir,
|
||||||
User: c.ProcessConfig.User,
|
User: processConfig.User,
|
||||||
}
|
}
|
||||||
|
|
||||||
if processConfig.Tty {
|
if processConfig.Tty {
|
||||||
|
|
|
@ -10,6 +10,7 @@ docker-exec - Run a command in a running container
|
||||||
[**--help**]
|
[**--help**]
|
||||||
[**-i**|**--interactive**[=*false*]]
|
[**-i**|**--interactive**[=*false*]]
|
||||||
[**-t**|**--tty**[=*false*]]
|
[**-t**|**--tty**[=*false*]]
|
||||||
|
[**-u**|**--user**[=*USER*]]
|
||||||
CONTAINER COMMAND [ARG...]
|
CONTAINER COMMAND [ARG...]
|
||||||
|
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
|
@ -35,6 +36,14 @@ container is unpaused, and then run
|
||||||
**-t**, **--tty**=*true*|*false*
|
**-t**, **--tty**=*true*|*false*
|
||||||
Allocate a pseudo-TTY. The default is *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
|
The **-t** option is incompatible with a redirection of the docker client
|
||||||
standard input.
|
standard input.
|
||||||
|
|
||||||
|
|
|
@ -1115,6 +1115,7 @@ You'll need two shells for this example.
|
||||||
-d, --detach=false Detached mode: run command in the background
|
-d, --detach=false Detached mode: run command in the background
|
||||||
-i, --interactive=false Keep STDIN open even if not attached
|
-i, --interactive=false Keep STDIN open even if not attached
|
||||||
-t, --tty=false Allocate a pseudo-TTY
|
-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.
|
The `docker exec` command runs a new command in a running container.
|
||||||
|
|
||||||
|
|
|
@ -665,3 +665,32 @@ func TestRunMutableNetworkFiles(t *testing.T) {
|
||||||
}
|
}
|
||||||
logDone("run - mutable network files")
|
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")
|
||||||
|
}
|
||||||
|
|
|
@ -21,8 +21,7 @@ type ExecConfig struct {
|
||||||
|
|
||||||
func ExecConfigFromJob(job *engine.Job) (*ExecConfig, error) {
|
func ExecConfigFromJob(job *engine.Job) (*ExecConfig, error) {
|
||||||
execConfig := &ExecConfig{
|
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.
|
// TODO(vishh): Expose 'Privileged' once it is supported.
|
||||||
//Privileged: job.GetenvBool("Privileged"),
|
//Privileged: job.GetenvBool("Privileged"),
|
||||||
Tty: job.GetenvBool("Tty"),
|
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")
|
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")
|
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")
|
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
|
execCmd []string
|
||||||
container string
|
container string
|
||||||
)
|
)
|
||||||
|
@ -57,8 +57,7 @@ func ParseExec(cmd *flag.FlagSet, args []string) (*ExecConfig, error) {
|
||||||
execCmd = parsedArgs[1:]
|
execCmd = parsedArgs[1:]
|
||||||
|
|
||||||
execConfig := &ExecConfig{
|
execConfig := &ExecConfig{
|
||||||
// TODO(vishh): Expose '-u' flag once it is supported.
|
User: *flUser,
|
||||||
User: "",
|
|
||||||
// TODO(vishh): Expose '-p' flag once it is supported.
|
// TODO(vishh): Expose '-p' flag once it is supported.
|
||||||
Privileged: false,
|
Privileged: false,
|
||||||
Tty: *flTty,
|
Tty: *flTty,
|
||||||
|
|
Loading…
Reference in New Issue