func (job *Job) Exec(docker *dockerclient.DockerClient, w io.Writer) error { containerConfig := &dockerclient.ContainerConfig{ Image: job.Image, Cmd: []string{"/bin/bash", "-c", job.Cmd}, AttachStdout: true, AttachStderr: true, } cid, err := docker.CreateContainer(containerConfig, fmt.Sprintf("spot-trader-job-%d", job.ID)) if err != nil { return fmt.Errorf("creating container: %v", err) } defer func() { if err = docker.RemoveContainer(cid, false, false); err != nil { log.Printf("error removing container: %v", err) } }() options := &dockerclient.AttachOptions{Stdout: true, Stderr: true, Stream: true} stdout, err := docker.AttachContainer(cid, options) if err != nil { return fmt.Errorf("attaching: %v", err) } err = docker.StartContainer(cid, nil) if err != nil { return fmt.Errorf("starting container: %v", err) } done := make(chan struct{}) go func() { err := copyDockerOut(w, w, stdout) if err != nil { log.Println(err) } stdout.Close() close(done) }() <-done err = docker.StopContainer(cid, 5) if err != nil { log.Printf("error stopping container: %v", err) } return nil }