github.com/sneal/packer@v0.5.2/builder/docker/driver_docker.go (about) 1 package docker 2 3 import ( 4 "bytes" 5 "fmt" 6 "github.com/mitchellh/packer/packer" 7 "io" 8 "log" 9 "os" 10 "os/exec" 11 "strings" 12 ) 13 14 type DockerDriver struct { 15 Ui packer.Ui 16 Tpl *packer.ConfigTemplate 17 } 18 19 func (d *DockerDriver) DeleteImage(id string) error { 20 var stderr bytes.Buffer 21 cmd := exec.Command("docker", "rmi", id) 22 cmd.Stderr = &stderr 23 24 log.Printf("Deleting image: %s", id) 25 if err := cmd.Start(); err != nil { 26 return err 27 } 28 29 if err := cmd.Wait(); err != nil { 30 err = fmt.Errorf("Error deleting image: %s\nStderr: %s", 31 err, stderr.String()) 32 return err 33 } 34 35 return nil 36 } 37 38 func (d *DockerDriver) Export(id string, dst io.Writer) error { 39 var stderr bytes.Buffer 40 cmd := exec.Command("docker", "export", id) 41 cmd.Stdout = dst 42 cmd.Stderr = &stderr 43 44 log.Printf("Exporting container: %s", id) 45 if err := cmd.Start(); err != nil { 46 return err 47 } 48 49 if err := cmd.Wait(); err != nil { 50 err = fmt.Errorf("Error exporting: %s\nStderr: %s", 51 err, stderr.String()) 52 return err 53 } 54 55 return nil 56 } 57 58 func (d *DockerDriver) Import(path string, repo string) (string, error) { 59 var stdout bytes.Buffer 60 cmd := exec.Command("docker", "import", "-", repo) 61 cmd.Stdout = &stdout 62 stdin, err := cmd.StdinPipe() 63 if err != nil { 64 return "", err 65 } 66 67 // There should be only one artifact of the Docker builder 68 file, err := os.Open(path) 69 if err != nil { 70 return "", err 71 } 72 defer file.Close() 73 74 if err := cmd.Start(); err != nil { 75 return "", err 76 } 77 78 go func() { 79 defer stdin.Close() 80 io.Copy(stdin, file) 81 }() 82 83 if err := cmd.Wait(); err != nil { 84 err = fmt.Errorf("Error importing container: %s", err) 85 return "", err 86 } 87 88 return strings.TrimSpace(stdout.String()), nil 89 } 90 91 func (d *DockerDriver) Pull(image string) error { 92 cmd := exec.Command("docker", "pull", image) 93 return runAndStream(cmd, d.Ui) 94 } 95 96 func (d *DockerDriver) Push(name string) error { 97 cmd := exec.Command("docker", "push", name) 98 return runAndStream(cmd, d.Ui) 99 } 100 101 func (d *DockerDriver) StartContainer(config *ContainerConfig) (string, error) { 102 // Build up the template data 103 var tplData startContainerTemplate 104 tplData.Image = config.Image 105 if len(config.Volumes) > 0 { 106 volumes := make([]string, 0, len(config.Volumes)) 107 for host, guest := range config.Volumes { 108 volumes = append(volumes, fmt.Sprintf("%s:%s", host, guest)) 109 } 110 111 tplData.Volumes = strings.Join(volumes, ",") 112 } 113 114 // Args that we're going to pass to Docker 115 args := config.RunCommand 116 for i, v := range args { 117 var err error 118 args[i], err = d.Tpl.Process(v, &tplData) 119 if err != nil { 120 return "", err 121 } 122 } 123 d.Ui.Message(fmt.Sprintf( 124 "Run command: docker %s", strings.Join(args, " "))) 125 126 // Start the container 127 var stdout, stderr bytes.Buffer 128 cmd := exec.Command("docker", args...) 129 cmd.Stdout = &stdout 130 cmd.Stderr = &stderr 131 132 log.Printf("Starting container with args: %v", args) 133 if err := cmd.Start(); err != nil { 134 return "", err 135 } 136 137 log.Println("Waiting for container to finish starting") 138 if err := cmd.Wait(); err != nil { 139 if _, ok := err.(*exec.ExitError); ok { 140 err = fmt.Errorf("Docker exited with a non-zero exit status.\nStderr: %s", 141 stderr.String()) 142 } 143 144 return "", err 145 } 146 147 // Capture the container ID, which is alone on stdout 148 return strings.TrimSpace(stdout.String()), nil 149 } 150 151 func (d *DockerDriver) StopContainer(id string) error { 152 return exec.Command("docker", "kill", id).Run() 153 } 154 155 func (d *DockerDriver) Verify() error { 156 if _, err := exec.LookPath("docker"); err != nil { 157 return err 158 } 159 160 return nil 161 }