Skip to content

StartExecOptions.Context is not respected during exection #871

@krasoffski

Description

@krasoffski

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 

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions