Files
linuxkit/cmd/moby/docker.go
Justin Cormack 0ade84e151 Fix docker pull
Signed-off-by: Justin Cormack <justin.cormack@docker.com>
2017-05-12 13:04:19 +01:00

224 lines
5.2 KiB
Go

package main
// We want to replace much of this with use of containerd tools
// and also using the Docker API not shelling out
import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"strings"
log "github.com/Sirupsen/logrus"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"golang.org/x/net/context"
)
func dockerRun(args ...string) ([]byte, error) {
log.Debugf("docker run: %s", strings.Join(args, " "))
docker, err := exec.LookPath("docker")
if err != nil {
return []byte{}, errors.New("Docker does not seem to be installed")
}
args = append([]string{"run", "--rm", "--log-driver=none"}, args...)
cmd := exec.Command(docker, args...)
stderrPipe, err := cmd.StderrPipe()
if err != nil {
return []byte{}, err
}
stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
return []byte{}, err
}
err = cmd.Start()
if err != nil {
return []byte{}, err
}
stdout, err := ioutil.ReadAll(stdoutPipe)
if err != nil {
return []byte{}, err
}
stderr, err := ioutil.ReadAll(stderrPipe)
if err != nil {
return []byte{}, err
}
err = cmd.Wait()
if err != nil {
return []byte{}, fmt.Errorf("%v: %s", err, stderr)
}
log.Debugf("docker run: %s...Done", strings.Join(args, " "))
return stdout, nil
}
func dockerRunInput(input io.Reader, args ...string) ([]byte, error) {
log.Debugf("docker run (input): %s", strings.Join(args, " "))
docker, err := exec.LookPath("docker")
if err != nil {
return []byte{}, errors.New("Docker does not seem to be installed")
}
args = append([]string{"run", "--rm", "-i"}, args...)
cmd := exec.Command(docker, args...)
cmd.Stdin = input
stderrPipe, err := cmd.StderrPipe()
if err != nil {
return []byte{}, err
}
stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
return []byte{}, err
}
err = cmd.Start()
if err != nil {
return []byte{}, err
}
stdout, err := ioutil.ReadAll(stdoutPipe)
if err != nil {
return []byte{}, err
}
stderr, err := ioutil.ReadAll(stderrPipe)
if err != nil {
return []byte{}, err
}
err = cmd.Wait()
if err != nil {
return []byte{}, fmt.Errorf("%v: %s", err, stderr)
}
log.Debugf("docker run (input): %s...Done", strings.Join(args, " "))
return stdout, nil
}
func dockerCreate(image string) (string, error) {
log.Debugf("docker create: %s", image)
cli, err := dockerClient()
if err != nil {
return "", errors.New("could not initialize Docker API client")
}
// we do not ever run the container, so /dev/null is used as command
config := &container.Config{
Cmd: []string{"/dev/null"},
Image: image,
}
respBody, err := cli.ContainerCreate(context.Background(), config, nil, nil, "")
if err != nil {
return "", err
}
log.Debugf("docker create: %s...Done", image)
return respBody.ID, nil
}
func dockerExport(container string) ([]byte, error) {
log.Debugf("docker export: %s", container)
cli, err := dockerClient()
if err != nil {
return []byte{}, errors.New("could not initialize Docker API client")
}
responseBody, err := cli.ContainerExport(context.Background(), container)
if err != nil {
return []byte{}, err
}
defer responseBody.Close()
output := bytes.NewBuffer(nil)
_, err = io.Copy(output, responseBody)
if err != nil {
return []byte{}, err
}
return output.Bytes(), nil
}
func dockerRm(container string) error {
log.Debugf("docker rm: %s", container)
cli, err := dockerClient()
if err != nil {
return errors.New("could not initialize Docker API client")
}
if err = cli.ContainerRemove(context.Background(), container, types.ContainerRemoveOptions{}); err != nil {
return err
}
log.Debugf("docker rm: %s...Done", container)
return nil
}
func dockerPull(image string, trustedPull bool) error {
log.Debugf("docker pull: %s", image)
if trustedPull {
log.Debugf("pulling %s with content trust", image)
trustedImg, err := TrustedReference(image)
if err != nil {
return fmt.Errorf("Trusted pull for %s failed: %v", image, err)
}
image = trustedImg.String()
}
cli, err := dockerClient()
if err != nil {
return errors.New("could not initialize Docker API client")
}
r, err := cli.ImagePull(context.Background(), image, types.ImagePullOptions{})
if err != nil {
return err
}
defer r.Close()
_, err = io.Copy(ioutil.Discard, r)
if err != nil {
return err
}
log.Debugf("docker pull: %s...Done", image)
return nil
}
func dockerClient() (*client.Client, error) {
// for maximum compatibility as we use nothing new
err := os.Setenv("DOCKER_API_VERSION", "1.23")
if err != nil {
return nil, err
}
return client.NewEnvClient()
}
func dockerInspectImage(cli *client.Client, image string) (types.ImageInspect, error) {
log.Debugf("docker inspect image: %s", image)
inspect, _, err := cli.ImageInspectWithRaw(context.Background(), image)
if err != nil {
if client.IsErrImageNotFound(err) {
pullErr := dockerPull(image, false)
if pullErr != nil {
return types.ImageInspect{}, pullErr
}
inspect, _, err = cli.ImageInspectWithRaw(context.Background(), image)
if err != nil {
return types.ImageInspect{}, err
}
} else {
return types.ImageInspect{}, err
}
}
log.Debugf("docker inspect image: %s...Done", image)
return inspect, nil
}