title: How to connect container stdin & stdout with websocket?
body: <p>At present I want to connect container stdin and stdout with websocket.  But I can not read stdout if there are no output. e.g. "cd /"</p>
  
  <p>Here is my code:</p>
  
  <pre><code>package main
  
  import (
      dcl "github.com/docker/docker/client"
      "context"
      "html/template"
      "github.com/docker/docker/api/types"
      "log"
      "net/http"
      "flag"
      "github.com/gorilla/websocket"
      "fmt"
      "io"
      "bufio"
  )
  
  var inout chan []byte
  var output chan []byte
  
  var addr = flag.String("addr", "localhost:8080", "http service address")
  
  var upgrader = websocket.Upgrader{}
  
  func echo(w http.ResponseWriter, r *http.Request) {
      conn, err := upgrader.Upgrade(w, r, nil)
      if err != nil {
          log.Print(err)
          return
      }
      defer conn.Close()
  
      cli, err := dcl.NewEnvClient()
      if err != nil {
          log.Print(err)
          conn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
          return
      }
  
      ctx := context.Background()
      execConfig := types.ExecConfig{
          AttachStderr: true,
          AttachStdin:  true,
          AttachStdout: true,
          Cmd:          []string{"/bin/sh"},
          Tty:          false,
          Detach:       false,
      }
  
      //set target container
      exec, err := cli.ContainerExecCreate(ctx, "ubuntu", execConfig)
      if err != nil {
          log.Print(err)
          conn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
          return
      }
      execAttachConfig := types.ExecStartCheck{
          Detach: false,
          Tty:    false,
      }
      containerConn, err := cli.ContainerExecAttach(ctx, exec.ID, execAttachConfig)
      if err != nil {
          log.Print(err)
          conn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
          return
      }
      defer containerConn.Close()
  
      bufin := bufio.NewReader(containerConn.Reader)
  
      go func(w io.WriteCloser) {
          for {
              data, ok := &lt;-inout
              if !ok {
                  fmt.Println("!ok")
                  w.Close()
                  return
              }
  
              fmt.Println(string(data))
              w.Write(append(data, '\n'))
          }
      }(containerConn.Conn)
  
      go func() {
          for {
              buffer := make([]byte, 4096, 4096)
              c, err := bufin.Read(buffer)
              if err != nil{
                  fmt.Println(err)
              }
              //c, err := containerConn.Reader.Read(buffer)
              if c &gt; 0 {
                  output &lt;- buffer[:c]
              }
              if c == 0{
                  output &lt;- []byte{' '}
              }
              if err != nil {
                  break
              }
          }
      }()
  
      for {
  
          mt, message, err := conn.ReadMessage()
          if err != nil {
              log.Println("read:", err)
              break
          }
  
          log.Printf("recv: %s", message)
          inout &lt;- message
          data := &lt;-output
          err = conn.WriteMessage(mt, data)
          if err != nil {
              log.Println("write:", err)
              break
          }
      }
  }
  
  func home(w http.ResponseWriter, r *http.Request) {
      homeTemplate.Execute(w, "ws://"+r.Host+"/echo")
  }
  
  func main() {
  
      inout = make(chan []byte)
      output = make(chan []byte)
  
      http.HandleFunc("/echo", echo)
      http.HandleFunc("/", home)
      log.Fatal(http.ListenAndServe(*addr, nil))
  }
  
  var homeTemplate = template.Must(template.New("").Parse(`
  &lt;!DOCTYPE html&gt;
  &lt;html&gt;
  &lt;head&gt;
  &lt;meta charset="utf-8"&gt;
  &lt;script&gt;
  window.addEventListener("load", function(evt) {
      var output = document.getElementById("output");
      var input = document.getElementById("input");
      var ws;
      var print = function(message) {
          var d = document.createElement("div");
          d.innerHTML = message;
          output.appendChild(d);
      };
      document.getElementById("open").onclick = function(evt) {
          if (ws) {
              return false;
          }
          ws = new WebSocket("{{.}}");
          ws.onopen = function(evt) {
              print("OPEN");
          }
          ws.onclose = function(evt) {
              print("CLOSE");
              ws = null;
          }
          ws.onmessage = function(evt) {
              print("RESPONSE: " + evt.data);
          }
          ws.onerror = function(evt) {
              print("ERROR: " + evt.data);
          }
          return false;
      };
      document.getElementById("send").onclick = function(evt) {
          if (!ws) {
              return false;
          }
          print("SEND: " + input.value);
          ws.send(input.value);
          return false;
      };
      document.getElementById("close").onclick = function(evt) {
          if (!ws) {
              return false;
          }
          ws.close();
          return false;
      };
  });
  &lt;/script&gt;
  &lt;/head&gt;
  &lt;body&gt;
  &lt;table&gt;
  &lt;tr&gt;&lt;td valign="top" width="50%"&gt;
  &lt;p&gt;Click "Open" to create a connection to the server,
  "Send" to send a message to the server and "Close" to close the connection.
  You can change the message and send multiple times.
  &lt;p&gt;
  &lt;form&gt;
  &lt;button id="open"&gt;Open&lt;/button&gt;
  &lt;button id="close"&gt;Close&lt;/button&gt;
  &lt;p&gt;&lt;input id="input" type="text" value="ls"&gt;
  &lt;button id="send"&gt;Send&lt;/button&gt;
  &lt;/form&gt;
  &lt;/td&gt;&lt;td valign="top" width="50%"&gt;
  &lt;div id="output"&gt;&lt;/div&gt;
  &lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
  &lt;/body&gt;
  &lt;/html&gt;
  `))
  </code></pre>
  
  <p>I try many ways, but no way can work :(</p>