func (c App) Attach(user string, ws *websocket.Conn) revel.Result { config := docker.Config{} config.Cmd = []string{"/bin/bash"} config.Image = "workshops:" + c.Params.Values.Get("image") config.Tty = true config.AttachStdin = true config.AttachStdout = true config.OpenStdin = true config.StdinOnce = true container, err := c.DockerClient.CreateContainer(&config) if err != nil { fmt.Println(err.Error()) c.Response.Status = 500 return c.RenderText(err.Error()) } id := container.ShortID() err = c.DockerClient.StartContainer(id) if err != nil { fmt.Println(err.Error()) c.Response.Status = 500 return c.RenderText(err.Error()) } endpoint := "ws://127.0.0.1:4243/v1.5/containers/" + id + "/attach/ws?logs=1&stderr=1&stdout=1&stream=1&stdin=1" containerWs, err := websocket.Dial(endpoint, "", "http://localhost") if err != nil { fmt.Println(err.Error()) c.Response.Status = 500 return c.RenderText(err.Error()) } finished := make(chan bool) go func() { defer containerWs.Close() buf := make([]byte, 40*1024) for { n, err := containerWs.Read(buf) if err != nil { break } if n != 0 { ws.Write(buf[0:n]) } } finished <- true }() go func() { defer ws.Close() defer containerWs.Close() buf := make([]byte, 40*1024) for { n, err := ws.Read(buf) if err != nil { break } if n != 0 { containerWs.Write(buf[0:n]) } } finished <- true }() <-finished <-finished return c.RenderText("OK") }