diff --git a/README.md b/README.md index 0a9b69c6d..7e8af5757 100644 --- a/README.md +++ b/README.md @@ -76,7 +76,7 @@ Installing on Ubuntu 12.04 and 12.10 ```bash cd docker-master - sudo ./docker run -a -i -t base /bin/bash + sudo ./docker run -i -t base /bin/bash ``` Consider adding docker to your `PATH` for simplicity. @@ -136,7 +136,7 @@ docker import base # Run an interactive shell in the base image, # allocate a tty, attach stdin and stdout -docker run -a -i -t base /bin/bash +docker run -i -t base /bin/bash ``` @@ -148,7 +148,7 @@ Starting a long-running worker process (docker -d || echo "Docker daemon already running") & # Start a very useful long-running process -JOB=$(docker run base /bin/sh -c "while true; do echo Hello world; sleep 1; done") +JOB=$(docker run -d base /bin/sh -c "while true; do echo Hello world; sleep 1; done") # Collect the output of the job so far docker logs $JOB @@ -171,7 +171,7 @@ Expose a service on a TCP port ```bash # Expose port 4444 of this container, and tell netcat to listen on it -JOB=$(docker run -p 4444 base /bin/nc -l -p 4444) +JOB=$(docker run -d -p 4444 base /bin/nc -l -p 4444) # Which public port is NATed to my container? PORT=$(docker port $JOB 4444) diff --git a/commands.go b/commands.go index 443d192bd..9e2bdbc70 100644 --- a/commands.go +++ b/commands.go @@ -783,6 +783,18 @@ func (p *ports) Set(value string) error { return nil } +// ListOpts type +type ListOpts []string + +func (opts *ListOpts) String() string { + return fmt.Sprint(*opts) +} + +func (opts *ListOpts) Set(value string) error { + *opts = append(*opts, value) + return nil +} + 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") @@ -799,35 +811,24 @@ func (srv *Server) CmdTag(stdin io.ReadCloser, stdout io.Writer, args ...string) func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string) error { cmd := rcli.Subcmd(stdout, "run", "[OPTIONS] IMAGE COMMAND [ARG...]", "Run a command in a new container") fl_user := cmd.String("u", "", "Username or UID") - fl_attach := cmd.Bool("a", false, "Attach stdin and stdout") + fl_detach := cmd.Bool("d", false, "Detached mode: leave the container running in the background") fl_stdin := cmd.Bool("i", false, "Keep stdin open even if not attached") fl_tty := cmd.Bool("t", false, "Allocate a pseudo-tty") fl_memory := cmd.Int64("m", 0, "Memory limit (in bytes)") var fl_ports ports cmd.Var(&fl_ports, "p", "Map a network port to the container") + var fl_env ListOpts + cmd.Var(&fl_env, "e", "Set environment variables") if err := cmd.Parse(args); err != nil { return nil } + if cmd.NArg() < 2 { + cmd.Usage() + return nil + } name := cmd.Arg(0) - var cmdline []string - - if len(cmd.Args()) >= 2 { - cmdline = cmd.Args()[1:] - } - // Choose a default image if needed - if name == "" { - name = "base" - } - - // Choose a default command if needed - if len(cmdline) == 0 { - *fl_stdin = true - *fl_tty = true - *fl_attach = true - cmdline = []string{"/bin/bash", "-i"} - } - + cmdline := cmd.Args()[1:] // Create new container container, err := srv.runtime.Create(cmdline[0], cmdline[1:], name, &Config{ @@ -836,6 +837,7 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string) Tty: *fl_tty, OpenStdin: *fl_stdin, Memory: *fl_memory, + Env: fl_env, }) if err != nil { return errors.New("Error creating container: " + err.Error()) @@ -845,7 +847,7 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string) if err != nil { return err } - if *fl_attach { + if !*fl_detach { Go(func() error { _, err := io.Copy(cmd_stdin, stdin) cmd_stdin.Close() @@ -854,7 +856,7 @@ func (srv *Server) CmdRun(stdin io.ReadCloser, stdout io.Writer, args ...string) } } // Run the container - if *fl_attach { + if !*fl_detach { cmd_stderr, err := container.StderrPipe() if err != nil { return err diff --git a/container.go b/container.go index ea091b8fa..2b94fa7e0 100644 --- a/container.go +++ b/container.go @@ -53,6 +53,7 @@ type Config struct { Ports []int Tty bool // Attach standard streams to a tty, including stdin if it is not closed. OpenStdin bool // Open stdin + Env []string } type NetworkSettings struct { @@ -200,6 +201,15 @@ func (container *Container) Start() error { container.cmd = exec.Command("/usr/bin/lxc-start", params...) + // Setup environment + container.cmd.Env = append( + []string{ + "HOME=/", + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + }, + container.Config.Env..., + ) + var err error if container.Config.Tty { err = container.startPty() diff --git a/sysinit.go b/sysinit.go index c475b3365..f70141797 100644 --- a/sysinit.go +++ b/sysinit.go @@ -52,13 +52,6 @@ func changeUser(u string) { } } -// Set the environment to a known, repeatable state -func setupEnv() { - os.Clearenv() - os.Setenv("HOME", "/") - os.Setenv("PATH", "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin") -} - func executeProgram(name string, args []string) { path, err := exec.LookPath(name) if err != nil { @@ -86,6 +79,5 @@ func SysInit() { setupNetworking(*gw) changeUser(*u) - setupEnv() executeProgram(flag.Arg(0), flag.Args()) }