(Sorry if it looks like I’ve cross-posted, I originally posted this in “Getting Help”, then found out about this sub-forum, so I deleted the original post, althought the Topic title still remains, for some reason)
I am writing a docker client using the official SDK; so far it works fine, but I have issues here with my own docker exec
clone.
Let us say that I run the equivalent of docker exec -tiuroot $CONTAINERNAME bash
, and then proceed to send some commands to the allocated tty (ls, ps, etc), I get double output (see second extract). Another problem is the escape sequence: if I were to run tail -f $SOME_FILE
within the container, and then pressed CTRL+C it wouldn’t stop the tail command, but would kick me out of the container.
I do not see how to change both behavior.
First code extract is my actual method, attached image is an example where you see the “double output” when running dtools exec.
Both issues (double-output and escape character) kind of drive me nuts and I’d appreciate comments here.
Oh, and another issue I’ve just found out while uploading the image, below (not shown in image) : TAB COMPLETION wouldn’t work in this implementation; using the “real” docker exec
in the same container does work, so it’s an stdin/stdout issue in my implementation.
About the DockerExecConfig variable : it’s of types.ExecConfig and is prepopulated somewhere else.
func ContainerExec (uri string, args []string) string {
cli, err := client.NewClientWithOpts(client.WithHost(uri), client.WithAPIVersionNegotiation())
if err != nil {
fmt.Printf("Unable to create docker client: %s\n", err)
os.Exit(-1)
}
DockerExecConfig.AttachStderr = DockerExecConfig.AttachStdout
DockerExecConfig.AttachStdin = DockerExecConfig.AttachStdout
DockerExecConfig.Cmd = args[1:]
execResponse, err := cli.ContainerExecCreate(ctx, args[0], DockerExecConfig)
if err != nil {
return err.Error()
}
execAttachConfig := types.ExecStartCheck{
Tty: !DockerExecConfig.Tty,
}
resp, err := cli.ContainerExecAttach(ctx, execResponse.ID, execAttachConfig)
if err != nil {
return err.Error()
}
defer resp.Close()
errChan := make(chan error, 1)
go func() {
_, errorInContainer := stdcopy.StdCopy(os.Stdout, os.Stderr, resp.Reader)
errChan <- errorInContainer
}()
go func() {
_, err := io.Copy(resp.Conn, os.Stdin)
errChan <- err
}()
select {
case errorInContainer := <-errChan:
if errorInContainer != nil {
fmt.Printf("dtools exec error: %s\n", errorInContainer.Error())
os.Exit(-1)
}
return ""
}
}
You see in this image that every command input at the CLI prompts gets sent to stdout as well, also, notice the $PS1 prompt which shows that the dtools command was sent from host “bergen” to container “nginx”, and CTRL+C sent back control to bergen instead of killing tail -1 -f. Subsequent docker exec
has shown that tail -1 -f
was still running.