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
64
commands.go
64
commands.go
|
@ -827,6 +827,33 @@ func (opts *ListOpts) Set(value string) error {
|
||||||
return nil
|
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 {
|
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")
|
cmd := rcli.Subcmd(stdout, "tag", "[OPTIONS] IMAGE REPOSITORY [TAG]", "Tag an image into a repository")
|
||||||
force := cmd.Bool("f", false, "Force")
|
force := cmd.Bool("f", false, "Force")
|
||||||
|
@ -870,28 +897,29 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Run the container
|
var (
|
||||||
if !config.Detach {
|
cStdin io.Reader
|
||||||
var attachErr chan error
|
cStdout, cStderr io.Writer
|
||||||
if config.OpenStdin {
|
)
|
||||||
Debugf("Attaching with stdin\n")
|
if config.AttachStdin {
|
||||||
attachErr = container.Attach(stdin, stdout, stdout)
|
cStdin = stdin
|
||||||
} else {
|
|
||||||
Debugf("Attaching without stdin\n")
|
|
||||||
attachErr = container.Attach(nil, stdout, nil)
|
|
||||||
}
|
|
||||||
Debugf("Starting\n")
|
|
||||||
if err := container.Start(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
Debugf("Waiting for attach to return\n")
|
|
||||||
return <-attachErr
|
|
||||||
}
|
}
|
||||||
|
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 {
|
if err := container.Start(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Fprintln(stdout, container.ShortId())
|
if cStdout == nil && cStderr == nil {
|
||||||
return nil
|
fmt.Fprintln(stdout, container.ShortId())
|
||||||
|
}
|
||||||
|
Debugf("Waiting for attach to return\n")
|
||||||
|
return <-attachErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServer() (*Server, error) {
|
func NewServer() (*Server, error) {
|
||||||
|
|
63
container.go
63
container.go
|
@ -48,18 +48,20 @@ type Container struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Hostname string
|
Hostname string
|
||||||
User string
|
User string
|
||||||
Memory int64 // Memory limit (in bytes)
|
Memory int64 // Memory limit (in bytes)
|
||||||
MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap
|
MemorySwap int64 // Total memory usage (memory + swap); set `-1' to disable swap
|
||||||
Detach bool
|
AttachStdin bool
|
||||||
Ports []int
|
AttachStdout bool
|
||||||
Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
|
AttachStderr bool
|
||||||
OpenStdin bool // Open stdin
|
Ports []int
|
||||||
StdinOnce bool // If true, close stdin after the 1 attached client disconnects.
|
Tty bool // Attach standard streams to a tty, including stdin if it is not closed.
|
||||||
Env []string
|
OpenStdin bool // Open stdin
|
||||||
Cmd []string
|
StdinOnce bool // If true, close stdin after the 1 attached client disconnects.
|
||||||
Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
|
Env []string
|
||||||
|
Cmd []string
|
||||||
|
Image string // Name of the image as it was passed by the operator (eg. could be symbolic)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseRun(args []string, stdout io.Writer) (*Config, error) {
|
func ParseRun(args []string, stdout io.Writer) (*Config, error) {
|
||||||
|
@ -70,6 +72,8 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
|
||||||
|
|
||||||
flUser := cmd.String("u", "", "Username or UID")
|
flUser := cmd.String("u", "", "Username or UID")
|
||||||
flDetach := cmd.Bool("d", false, "Detached mode: leave the container running in the background")
|
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")
|
flStdin := cmd.Bool("i", false, "Keep stdin open even if not attached")
|
||||||
flTty := cmd.Bool("t", false, "Allocate a pseudo-tty")
|
flTty := cmd.Bool("t", false, "Allocate a pseudo-tty")
|
||||||
flMemory := cmd.Int64("m", 0, "Memory limit (in bytes)")
|
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 {
|
if err := cmd.Parse(args); err != nil {
|
||||||
return nil, err
|
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()
|
parsedArgs := cmd.Args()
|
||||||
runCmd := []string{}
|
runCmd := []string{}
|
||||||
image := ""
|
image := ""
|
||||||
|
@ -91,18 +108,20 @@ func ParseRun(args []string, stdout io.Writer) (*Config, error) {
|
||||||
runCmd = parsedArgs[1:]
|
runCmd = parsedArgs[1:]
|
||||||
}
|
}
|
||||||
config := &Config{
|
config := &Config{
|
||||||
Ports: flPorts,
|
Ports: flPorts,
|
||||||
User: *flUser,
|
User: *flUser,
|
||||||
Tty: *flTty,
|
Tty: *flTty,
|
||||||
OpenStdin: *flStdin,
|
OpenStdin: *flStdin,
|
||||||
Memory: *flMemory,
|
Memory: *flMemory,
|
||||||
Detach: *flDetach,
|
AttachStdin: flAttach.Get("stdin"),
|
||||||
Env: flEnv,
|
AttachStdout: flAttach.Get("stdout"),
|
||||||
Cmd: runCmd,
|
AttachStderr: flAttach.Get("stderr"),
|
||||||
Image: image,
|
Env: flEnv,
|
||||||
|
Cmd: runCmd,
|
||||||
|
Image: image,
|
||||||
}
|
}
|
||||||
// When allocating stdin in attached mode, close stdin at client disconnect
|
// When allocating stdin in attached mode, close stdin at client disconnect
|
||||||
if config.OpenStdin && !config.Detach {
|
if config.OpenStdin && config.AttachStdin {
|
||||||
config.StdinOnce = true
|
config.StdinOnce = true
|
||||||
}
|
}
|
||||||
return config, nil
|
return config, nil
|
||||||
|
|
Loading…
Add table
Reference in a new issue