mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
docker run [-a [stdin|stdout|stderr] [...]]: choose which streams to attach to when running a command. Fixes #234.
This commit is contained in:
parent
c77063afcd
commit
c04af2a330
2 changed files with 87 additions and 40 deletions
58
commands.go
58
commands.go
|
@ -827,6 +827,33 @@ func (opts *ListOpts) Set(value string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// AttachOpts stores arguments to 'docker run -a', eg. which streams to attach to
|
||||
type AttachOpts map[string]bool
|
||||
|
||||
func NewAttachOpts() *AttachOpts {
|
||||
opts := make(map[string]bool)
|
||||
return (*AttachOpts)(&opts)
|
||||
}
|
||||
|
||||
func (opts *AttachOpts) String() string {
|
||||
return fmt.Sprint(*opts)
|
||||
}
|
||||
|
||||
func (opts *AttachOpts) Set(val string) error {
|
||||
if val != "stdin" && val != "stdout" && val != "stderr" {
|
||||
return fmt.Errorf("Unsupported stream name: %s", val)
|
||||
}
|
||||
(*opts)[val] = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (opts *AttachOpts) Get(val string) bool {
|
||||
if res, exists := (*opts)[val]; exists {
|
||||
return res
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (srv *Server) CmdTag(stdin io.ReadCloser, stdout io.Writer, args ...string) error {
|
||||
cmd := rcli.Subcmd(stdout, "tag", "[OPTIONS] IMAGE REPOSITORY [TAG]", "Tag an image into a repository")
|
||||
force := cmd.Bool("f", false, "Force")
|
||||
|
@ -870,29 +897,30 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string)
|
|||
return err
|
||||
}
|
||||
}
|
||||
// Run the container
|
||||
if !config.Detach {
|
||||
var attachErr chan error
|
||||
if config.OpenStdin {
|
||||
Debugf("Attaching with stdin\n")
|
||||
attachErr = container.Attach(stdin, stdout, stdout)
|
||||
} else {
|
||||
Debugf("Attaching without stdin\n")
|
||||
attachErr = container.Attach(nil, stdout, nil)
|
||||
var (
|
||||
cStdin io.Reader
|
||||
cStdout, cStderr io.Writer
|
||||
)
|
||||
if config.AttachStdin {
|
||||
cStdin = stdin
|
||||
}
|
||||
if config.AttachStdout {
|
||||
cStdout = stdout
|
||||
}
|
||||
if config.AttachStderr {
|
||||
cStderr = stdout // FIXME: rcli can't differentiate stdout from stderr
|
||||
}
|
||||
attachErr := container.Attach(cStdin, cStdout, cStderr)
|
||||
Debugf("Starting\n")
|
||||
if err := container.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
if cStdout == nil && cStderr == nil {
|
||||
fmt.Fprintln(stdout, container.ShortId())
|
||||
}
|
||||
Debugf("Waiting for attach to return\n")
|
||||
return <-attachErr
|
||||
}
|
||||
if err := container.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(stdout, container.ShortId())
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewServer() (*Server, error) {
|
||||
if runtime.GOARCH != "amd64" {
|
||||
|
|
25
container.go
25
container.go
|
@ -52,7 +52,9 @@ type Config struct {
|
|||
User string
|
||||
Memory int64 // Memory limit (in bytes)
|
||||
MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap
|
||||
Detach bool
|
||||
AttachStdin bool
|
||||
AttachStdout bool
|
||||
AttachStderr bool
|
||||
Ports []int
|
||||
Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
|
||||
OpenStdin bool // Open stdin
|
||||
|
@ -70,6 +72,8 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
|
|||
|
||||
flUser := cmd.String("u", "", "Username or UID")
|
||||
flDetach := cmd.Bool("d", false, "Detached mode: leave the container running in the background")
|
||||
flAttach := NewAttachOpts()
|
||||
cmd.Var(flAttach, "a", "Attach to stdin, stdout or stderr.")
|
||||
flStdin := cmd.Bool("i", false, "Keep stdin open even if not attached")
|
||||
flTty := cmd.Bool("t", false, "Allocate a pseudo-tty")
|
||||
flMemory := cmd.Int64("m", 0, "Memory limit (in bytes)")
|
||||
|
@ -81,6 +85,19 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
|
|||
if err := cmd.Parse(args); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if *flDetach && len(*flAttach) > 0 {
|
||||
return nil, fmt.Errorf("Conflicting options: -a and -d")
|
||||
}
|
||||
// If neither -d or -a are set, attach to everything by default
|
||||
if len(*flAttach) == 0 && !*flDetach {
|
||||
if !*flDetach {
|
||||
flAttach.Set("stdout")
|
||||
flAttach.Set("stderr")
|
||||
if *flStdin {
|
||||
flAttach.Set("stdin")
|
||||
}
|
||||
}
|
||||
}
|
||||
parsedArgs := cmd.Args()
|
||||
runCmd := []string{}
|
||||
image := ""
|
||||
|
@ -96,13 +113,15 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
|
|||
Tty: *flTty,
|
||||
OpenStdin: *flStdin,
|
||||
Memory: *flMemory,
|
||||
Detach: *flDetach,
|
||||
AttachStdin: flAttach.Get("stdin"),
|
||||
AttachStdout: flAttach.Get("stdout"),
|
||||
AttachStderr: flAttach.Get("stderr"),
|
||||
Env: flEnv,
|
||||
Cmd: runCmd,
|
||||
Image: image,
|
||||
}
|
||||
// When allocating stdin in attached mode, close stdin at client disconnect
|
||||
if config.OpenStdin && !config.Detach {
|
||||
if config.OpenStdin && config.AttachStdin {
|
||||
config.StdinOnce = true
|
||||
}
|
||||
return config, nil
|
||||
|
|
Loading…
Add table
Reference in a new issue