- 
                Notifications
    
You must be signed in to change notification settings  - Fork 561
 
Open
Labels
Description
Hi,
It seem like StartExecOptions.Context is not respected by client?
Here is simple script which adds context with timeout for long execution command.
package main
import (
	"context"
	"os"
	"time"
	log "github.com/Sirupsen/logrus"
	docker "github.com/fsouza/go-dockerclient"
)
func execInContainer(command string) {
	endpoint := os.Getenv("DOCKER_HOST")
	if endpoint == "" {
		endpoint = "unix:///var/run/docker.sock"
	}
	client, err := docker.NewClient(endpoint)
	if err != nil {
		log.Debug(err.Error())
		return
	}
	log.Debug("Created client")
	//Pull image from Registry, if not present
	imageName := "golang:1.15"
	//Try to create a container from the imageID
	config := docker.Config{
		Image:        imageName,
		OpenStdin:    true,
		StdinOnce:    true,
		AttachStdin:  true,
		AttachStdout: true,
		AttachStderr: true,
		Tty:          true,
	}
	opts2 := docker.CreateContainerOptions{Config: &config}
	container, err := client.CreateContainer(opts2)
	if err != nil {
		log.Debug(err.Error())
		return
	} else {
		defer func() {
			err = client.RemoveContainer(docker.RemoveContainerOptions{ID: container.ID})
			if err != nil {
				log.Debug(err.Error())
				return
			}
			log.Debug("Removed container with ID", container.ID)
		}()
	}
	log.Debug("Created container with ID", container.ID)
	//Try to start the container
	err = client.StartContainer(container.ID, &docker.HostConfig{})
	if err != nil {
		log.Debug(err.Error())
		return
	} else {
		// And once it is done with all the commands, remove the container.
		defer func() {
			err = client.StopContainer(container.ID, 0)
			if err != nil {
				log.Debug(err.Error())
				return
			}
			log.Debug("Stopped container with ID", container.ID)
		}()
	}
	log.Debug("Started container with ID", container.ID)
	var (
		dExec *docker.Exec
	)
	cmd := []string{"bash", "-c", command}
	de := docker.CreateExecOptions{
		AttachStderr: true,
		AttachStdin:  true,
		AttachStdout: true,
		Tty:          true,
		Cmd:          cmd,
		Container:    container.ID,
	}
	log.Debug("CreateExec")
	if dExec, err = client.CreateExec(de); err != nil {
		log.Debug("CreateExec Error: %s", err)
		return
	}
	log.Debug("Created Exec")
	execId := dExec.ID
	// Context with timeout!!!
	ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
	defer cancel()
	opts := docker.StartExecOptions{
		OutputStream: os.Stdout,
		ErrorStream:  os.Stderr,
		InputStream:  os.Stdin,
		RawTerminal:  true,
		Context:      ctx,
	}
	log.Debug("StartExec")
	if err = client.StartExec(execId, opts); err != nil {
		log.Debug("StartExec Error: %s", err)
		return
	}
}
func main() {
	formatter := log.TextFormatter{
		TimestampFormat: "2006-01-02 15:04:05",
		FullTimestamp:   true,
	}
	log.SetFormatter(&formatter)
	log.SetLevel(log.DebugLevel)
	execInContainer("sleep 60")
}You can see that start exec option has context with timeout about 5 seconds.
But logs shows that command runs all 60 seconds.
DEBU[2021-04-27 12:00:37] Created client
DEBU[2021-04-27 12:00:37] Created container with IDd2a6490ce508a51f54fa5d8cda640e69a558ca65871e36133a7b2dd6c5c5ab44 
DEBU[2021-04-27 12:00:38] Started container with IDd2a6490ce508a51f54fa5d8cda640e69a558ca65871e36133a7b2dd6c5c5ab44 
DEBU[2021-04-27 12:00:38] CreateExec
DEBU[2021-04-27 12:00:38] Created Exec
DEBU[2021-04-27 12:00:38] StartExec
DEBU[2021-04-27 12:01:38] Stopped container with IDd2a6490ce508a51f54fa5d8cda640e69a558ca65871e36133a7b2dd6c5c5ab44 
DEBU[2021-04-27 12:01:38] Removed container with IDd2a6490ce508a51f54fa5d8cda640e69a558ca65871e36133a7b2dd6c5c5ab44