func()

in executors/docker/executor_docker.go [872:931]


func (s *executor) watchContainer(ctx context.Context, id string, input io.Reader) (err error) {
	options := types.ContainerAttachOptions{
		Stream: true,
		Stdin:  true,
		Stdout: true,
		Stderr: true,
	}

	s.Debugln("Attaching to container", id, "...")
	hijacked, err := s.client.ContainerAttach(ctx, id, options)
	if err != nil {
		return
	}
	defer hijacked.Close()

	s.Debugln("Starting container", id, "...")
	err = s.client.ContainerStart(ctx, id, types.ContainerStartOptions{})
	if err != nil {
		return
	}

	s.Debugln("Waiting for attach to finish", id, "...")
	attachCh := make(chan error, 2)

	// Copy any output to the build trace
	go func() {
		_, err := stdcopy.StdCopy(s.Trace, s.Trace, hijacked.Reader)
		if err != nil {
			attachCh <- err
		}
	}()

	// Write the input to the container and close its STDIN to get it to finish
	go func() {
		_, err := io.Copy(hijacked.Conn, input)
		hijacked.CloseWrite()
		if err != nil {
			attachCh <- err
		}
	}()

	waitCh := make(chan error, 1)
	go func() {
		waitCh <- s.waitForContainer(id)
	}()

	select {
	case <-ctx.Done():
		s.killContainer(id, waitCh)
		err = errors.New("Aborted")

	case err = <-attachCh:
		s.killContainer(id, waitCh)
		s.Debugln("Container", id, "finished with", err)

	case err = <-waitCh:
		s.Debugln("Container", id, "finished with", err)
	}
	return
}