+ Runtime: 'docker build' builds a container, layer by layer, from a source repository containing a Dockerfile
+ Runtime: 'docker build -t FOO' applies the tag FOO to the newly built container.
diff --git a/MAINTAINERS b/MAINTAINERS
index 6203fee..dc0d1a1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1,4 +1,5 @@
 Solomon Hykes <solomon@dotcloud.com>
 Guillaume Charmes <guillaume@dotcloud.com>
+Victor Vieux <victor@dotcloud.com>
 api.go: Victor Vieux <victor@dotcloud.com>
 Vagrantfile: Daniel Mizyrycki <daniel@dotcloud.com>
diff --git a/commands.go b/commands.go
index ca49579..38deb1a 100644
--- a/commands.go
+++ b/commands.go
@@ -993,7 +993,7 @@
 	v.Set("stdout", "1")
 	v.Set("stderr", "1")
 
-	if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), false); err != nil {
+	if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), false, nil, os.Stdout); err != nil {
 		return err
 	}
 	return nil
@@ -1020,15 +1020,35 @@
 		return err
 	}
 
+	splitStderr := container.Config.Tty
+
+	connections := 1
+	if splitStderr {
+		connections += 1
+	}
+	chErrors := make(chan error, connections)
+	cli.monitorTtySize(cmd.Arg(0))
+	if splitStderr {
+		go func() {
+			chErrors <- cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?stream=1&stderr=1", false, nil, os.Stderr)
+		}()
+	}
 	v := url.Values{}
 	v.Set("stream", "1")
-	v.Set("stdout", "1")
-	v.Set("stderr", "1")
 	v.Set("stdin", "1")
-
-	cli.monitorTtySize(cmd.Arg(0))
-	if err := cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty); err != nil {
-		return err
+	v.Set("stdout", "1")
+	if !splitStderr {
+		v.Set("stderr", "1")
+	}
+	go func() {
+		chErrors <- cli.hijack("POST", "/containers/"+cmd.Arg(0)+"/attach?"+v.Encode(), container.Config.Tty, os.Stdin, os.Stdout)
+	}()
+	for connections > 0 {
+		err := <-chErrors
+		if err != nil {
+			return err
+		}
+		connections -= 1
 	}
 	return nil
 }
@@ -1192,19 +1212,14 @@
 		fmt.Fprintln(os.Stderr, "WARNING: ", warning)
 	}
 
-	v := url.Values{}
-	v.Set("logs", "1")
-	v.Set("stream", "1")
+	splitStderr := !config.Tty
 
-	if config.AttachStdin {
-		v.Set("stdin", "1")
+	connections := 0
+	if config.AttachStdin || config.AttachStdout || (!splitStderr && config.AttachStderr) {
+		connections += 1
 	}
-	if config.AttachStdout {
-		v.Set("stdout", "1")
-	}
-	if config.AttachStderr {
-		v.Set("stderr", "1")
-
+	if splitStderr && config.AttachStderr {
+		connections += 1
 	}
 
 	//start the container
@@ -1213,10 +1228,38 @@
 		return err
 	}
 
-	if config.AttachStdin || config.AttachStdout || config.AttachStderr {
+	if connections > 0 {
+		chErrors := make(chan error, connections)
 		cli.monitorTtySize(out.Id)
-		if err := cli.hijack("POST", "/containers/"+out.Id+"/attach?"+v.Encode(), config.Tty); err != nil {
-			return err
+
+		if splitStderr && config.AttachStderr {
+			go func() {
+				chErrors <- cli.hijack("POST", "/containers/"+out.Id+"/attach?logs=1&stream=1&stderr=1", config.Tty, nil, os.Stderr)
+			}()
+		}
+
+		v := url.Values{}
+		v.Set("logs", "1")
+		v.Set("stream", "1")
+
+		if config.AttachStdin {
+			v.Set("stdin", "1")
+		}
+		if config.AttachStdout {
+			v.Set("stdout", "1")
+		}
+		if !splitStderr && config.AttachStderr {
+			v.Set("stderr", "1")
+		}
+		go func() {
+			chErrors <- cli.hijack("POST", "/containers/"+out.Id+"/attach?"+v.Encode(), config.Tty, os.Stdin, os.Stdout)
+		}()
+		for connections > 0 {
+			err := <-chErrors
+			if err != nil {
+				return err
+			}
+			connections -= 1
 		}
 	}
 	if !config.AttachStdout && !config.AttachStderr {
@@ -1352,7 +1395,7 @@
 	return nil
 }
 
-func (cli *DockerCli) hijack(method, path string, setRawTerminal bool) error {
+func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in *os.File, out io.Writer) error {
 	req, err := http.NewRequest(method, fmt.Sprintf("/v%g%s", API_VERSION, path), nil)
 	if err != nil {
 		return err
@@ -1370,20 +1413,19 @@
 	defer rwc.Close()
 
 	receiveStdout := utils.Go(func() error {
-		_, err := io.Copy(os.Stdout, br)
+		_, err := io.Copy(out, br)
 		return err
 	})
 
-	if setRawTerminal && term.IsTerminal(int(os.Stdin.Fd())) && os.Getenv("NORAW") == "" {
+	if in != nil && setRawTerminal && term.IsTerminal(int(in.Fd())) && os.Getenv("NORAW") == "" {
 		if oldState, err := term.SetRawTerminal(); err != nil {
 			return err
 		} else {
 			defer term.RestoreTerminal(oldState)
 		}
 	}
-
 	sendStdin := utils.Go(func() error {
-		_, err := io.Copy(rwc, os.Stdin)
+		_, err := io.Copy(rwc, in)
 		if err := rwc.(*net.TCPConn).CloseWrite(); err != nil {
 			fmt.Fprintf(os.Stderr, "Couldn't send EOF: %s\n", err)
 		}
diff --git a/runtime_test.go b/runtime_test.go
index 384cbd1..adb5e55 100644
--- a/runtime_test.go
+++ b/runtime_test.go
@@ -5,9 +5,12 @@
 	"github.com/dotcloud/docker/utils"
 	"io"
 	"io/ioutil"
+	"log"
 	"net"
 	"os"
 	"os/user"
+	"strconv"
+	"strings"
 	"sync"
 	"testing"
 	"time"
@@ -277,24 +280,50 @@
 
 }
 
+func findAvailalblePort(runtime *Runtime, port int) (*Container, error) {
+	strPort := strconv.Itoa(port)
+	container, err := NewBuilder(runtime).Create(&Config{
+		Image:     GetTestImage(runtime).Id,
+		Cmd:       []string{"sh", "-c", "echo well hello there | nc -l -p " + strPort},
+		PortSpecs: []string{strPort},
+	},
+	)
+	if err != nil {
+		return nil, err
+	}
+	if err := container.Start(); err != nil {
+		if strings.Contains(err.Error(), "address already in use") {
+			return nil, nil
+		}
+		return nil, err
+	}
+	return container, nil
+}
+
 // Run a container with a TCP port allocated, and test that it can receive connections on localhost
 func TestAllocatePortLocalhost(t *testing.T) {
 	runtime, err := newTestRuntime()
 	if err != nil {
 		t.Fatal(err)
 	}
-	container, err := NewBuilder(runtime).Create(&Config{
-		Image:     GetTestImage(runtime).Id,
-		Cmd:       []string{"sh", "-c", "echo well hello there | nc -l -p 5555"},
-		PortSpecs: []string{"5555"},
-	},
-	)
-	if err != nil {
-		t.Fatal(err)
+	port := 5554
+
+	var container *Container
+	for {
+		port += 1
+		log.Println("Trying port", port)
+		t.Log("Trying port", port)
+		container, err = findAvailalblePort(runtime, port)
+		if container != nil {
+			break
+		}
+		if err != nil {
+			t.Fatal(err)
+		}
+		log.Println("Port", port, "already in use")
+		t.Log("Port", port, "already in use")
 	}
-	if err := container.Start(); err != nil {
-		t.Fatal(err)
-	}
+
 	defer container.Kill()
 
 	setTimeout(t, "Waiting for the container to be started timed out", 2*time.Second, func() {
@@ -308,7 +337,7 @@
 
 	conn, err := net.Dial("tcp",
 		fmt.Sprintf(
-			"localhost:%s", container.NetworkSettings.PortMapping["5555"],
+			"localhost:%s", container.NetworkSettings.PortMapping[strconv.Itoa(port)],
 		),
 	)
 	if err != nil {