Beispiel #1
0
func (l *LocalCluster) runDockerSpy() {
	l.panicOnStop()

	create := func() (*Container, error) {
		return createContainer(l,
			container.Config{
				Image: dockerspyImage + ":" + dockerspyTag,
				Cmd:   strslice.New("--dns-domain=" + domain),
			}, container.HostConfig{
				Binds:           []string{"/var/run/docker.sock:/var/run/docker.sock"},
				PublishAllPorts: true,
			},
			"docker-spy",
		)
	}
	c, err := create()
	if dockerclient.IsErrImageNotFound(err) {
		if err := pullImage(l, types.ImagePullOptions{ImageID: dockerspyImage, Tag: dockerspyTag}); err != nil {
			log.Fatal(err)
		}

		c, err = create()
	}
	maybePanic(err)
	maybePanic(c.Start())
	l.dns = c
	if ci, err := c.Inspect(); err != nil {
		log.Error(err)
	} else {
		log.Infof("started %s: %s", c.Name(), ci.NetworkSettings.IPAddress)
	}
}
Beispiel #2
0
// CreateContainer aka schedule a brand new container into the cluster.
func (c *Cluster) CreateContainer(config *cluster.ContainerConfig, name string, authConfig *types.AuthConfig) (*cluster.Container, error) {
	poolUUID := os.Getenv("CX_POOL")
	log.Debug("CX: Adding label pool=" + poolUUID)
	config.Labels["pool"] = poolUUID

	container, err := c.createContainer(config, name, false, authConfig)

	if err != nil {
		var retries int64
		//  fails with image not found, then try to reschedule with image affinity
		// ENGINEAPIFIXME: The first error can be removed once dockerclient is removed
		bImageNotFoundError, _ := regexp.MatchString(`image \S* not found`, err.Error())
		if (bImageNotFoundError || client.IsErrImageNotFound(err)) && !config.HaveNodeConstraint() {
			// Check if the image exists in the cluster
			// If exists, retry with an image affinity
			if c.Image(config.Image) != nil {
				container, err = c.createContainer(config, name, true, authConfig)
				retries++
			}
		}

		for ; retries < c.createRetry && err != nil; retries++ {
			log.WithFields(log.Fields{"Name": "Swarm"}).Warnf("Failed to create container: %s, retrying", err)
			container, err = c.createContainer(config, name, false, authConfig)
		}
	}
	return container, err
}
Beispiel #3
0
// OutOfSync checks if the container is out of sync with the service definition.
// It looks if the the service hash container label is the same as the computed one.
func (c *Container) OutOfSync(imageName string) (bool, error) {
	info, err := c.findInfo()
	if err != nil {
		return false, err
	}

	if info.Config.Image != imageName {
		logrus.Debugf("Images for %s do not match %s!=%s", c.name, info.Config.Image, imageName)
		return true, nil
	}

	if info.Config.Labels[HASH.Str()] != c.getHash() {
		logrus.Debugf("Hashes for %s do not match %s!=%s", c.name, info.Config.Labels[HASH.Str()], c.getHash())
		return true, nil
	}

	image, _, err := c.client.ImageInspectWithRaw(context.Background(), info.Config.Image, false)
	if err != nil {
		if client.IsErrImageNotFound(err) {
			logrus.Debugf("Image %s do not exist, do not know if it's out of sync", info.Config.Image)
			return false, nil
		}
		return false, err
	}

	logrus.Debugf("Checking existing image name vs id: %s == %s", image.ID, info.Image)
	return image.ID != info.Image, err
}
Beispiel #4
0
func (cli *DockerCli) inspectAll(ctx context.Context, getSize bool) inspect.GetRefFunc {
	return func(ref string) (interface{}, []byte, error) {
		c, rawContainer, err := cli.client.ContainerInspectWithRaw(ctx, ref, getSize)
		if err != nil {
			// Search for image with that id if a container doesn't exist.
			if client.IsErrContainerNotFound(err) {
				i, rawImage, err := cli.client.ImageInspectWithRaw(ctx, ref, getSize)
				if err != nil {
					if client.IsErrImageNotFound(err) {
						// Search for task with that id if an image doesn't exists.
						t, rawTask, err := cli.client.TaskInspectWithRaw(ctx, ref)
						if err != nil {
							return nil, nil, fmt.Errorf("Error: No such image, container or task: %s", ref)
						}
						if getSize {
							fmt.Fprintln(cli.err, "WARNING: --size ignored for tasks")
						}
						return t, rawTask, nil
					}
					return nil, nil, err
				}
				return i, rawImage, err
			}
			return nil, nil, err
		}
		return c, rawContainer, err
	}
}
Beispiel #5
0
func (c *Container) createContainer(imageName, oldContainer string, configOverride *config.ServiceConfig) (*types.Container, error) {
	serviceConfig := c.service.serviceConfig
	if configOverride != nil {
		serviceConfig.Command = configOverride.Command
		serviceConfig.Tty = configOverride.Tty
		serviceConfig.StdinOpen = configOverride.StdinOpen
	}
	configWrapper, err := ConvertToAPI(c.service)
	if err != nil {
		return nil, err
	}

	configWrapper.Config.Image = imageName

	if configWrapper.Config.Labels == nil {
		configWrapper.Config.Labels = map[string]string{}
	}

	configWrapper.Config.Labels[SERVICE.Str()] = c.service.name
	configWrapper.Config.Labels[PROJECT.Str()] = c.service.context.Project.Name
	configWrapper.Config.Labels[HASH.Str()] = c.getHash()
	// libcompose run command not yet supported, so always "False"
	configWrapper.Config.Labels[ONEOFF.Str()] = "False"
	configWrapper.Config.Labels[NUMBER.Str()] = getContainerNumber(c)
	configWrapper.Config.Labels[VERSION.Str()] = ComposeVersion

	err = c.populateAdditionalHostConfig(configWrapper.HostConfig)
	if err != nil {
		return nil, err
	}

	if oldContainer != "" {
		info, err := c.client.ContainerInspect(context.Background(), oldContainer)
		if err != nil {
			return nil, err
		}
		configWrapper.HostConfig.Binds = util.Merge(configWrapper.HostConfig.Binds, volumeBinds(configWrapper.Config.Volumes, &info))
	}

	logrus.Debugf("Creating container %s %#v", c.name, configWrapper)

	container, err := c.client.ContainerCreate(context.Background(), configWrapper.Config, configWrapper.HostConfig, configWrapper.NetworkingConfig, c.name)
	if err != nil {
		if client.IsErrImageNotFound(err) {
			logrus.Debugf("Not Found, pulling image %s", configWrapper.Config.Image)
			if err = c.pull(configWrapper.Config.Image); err != nil {
				return nil, err
			}
			if container, err = c.client.ContainerCreate(context.Background(), configWrapper.Config, configWrapper.HostConfig, configWrapper.NetworkingConfig, c.name); err != nil {
				return nil, err
			}
		} else {
			logrus.Debugf("Failed to create container %s: %v", c.name, err)
			return nil, err
		}
	}

	return GetContainerByID(c.client, container.ID)
}
Beispiel #6
0
func ensureImage(cli DockerClient, image string) (string, error) {
	ctx := context.Background()
	info, _, err := cli.ImageInspectWithRaw(ctx, image, false)
	if err == nil {
		logrus.Debugf("Image found locally %s", image)
		return info.ID, nil
	}

	if !client.IsErrImageNotFound(err) {
		logrus.Errorf("Error inspecting image %q: %v", image, err)
		return "", err
	}

	// Image must be tagged reference if it does not exist
	ref, err := reference.Parse(image)
	if err != nil {
		logrus.Errorf("Image is not valid reference %q: %v", image, err)
		return "", err
	}
	tagged, ok := ref.(reference.NamedTagged)
	if !ok {
		logrus.Errorf("Tagged reference required %q", image)
		return "", errors.New("invalid reference, tag needed")
	}

	pullStart := time.Now()
	pullOptions := types.ImagePullOptions{
		PrivilegeFunc: registryAuthNotSupported,
	}
	resp, err := cli.ImagePull(ctx, tagged.String(), pullOptions)
	if err != nil {
		logrus.Errorf("Error pulling image %q: %v", tagged.String(), err)
		return "", err
	}
	defer resp.Close()

	outFd, isTerminalOut := term.GetFdInfo(os.Stdout)

	if err = jsonmessage.DisplayJSONMessagesStream(resp, os.Stdout, outFd, isTerminalOut, nil); err != nil {
		logrus.Errorf("Error copying pull output: %v", err)
		return "", err
	}
	// TODO: Get pulled digest

	logFields := logrus.Fields{
		timerKey: time.Since(pullStart),
		"image":  tagged.String(),
	}
	logrus.WithFields(logFields).Info("image pulled")

	info, _, err = cli.ImageInspectWithRaw(ctx, tagged.String(), false)
	if err != nil {
		return "", nil
	}

	return info.ID, nil
}
func (d *kubeDockerClient) InspectImage(image string) (*dockertypes.ImageInspect, error) {
	resp, _, err := d.client.ImageInspectWithRaw(getDefaultContext(), image, true)
	if err != nil {
		if dockerapi.IsErrImageNotFound(err) {
			err = imageNotFoundError{ID: image}
		}
		return nil, err
	}
	return &resp, nil
}
Beispiel #8
0
// IsImageInLocalRegistry determines whether the supplied image is in the local registry.
func (d *stiDocker) IsImageInLocalRegistry(name string) (bool, error) {
	name = getImageName(name)
	resp, err := d.InspectImage(name)
	if resp != nil {
		return true, nil
	}
	if err != nil && !dockerapi.IsErrImageNotFound(err) {
		return false, errors.NewInspectImageError(name, err)
	}
	return false, nil
}
Beispiel #9
0
func (s stiDocker) InspectImage(name string) (*dockertypes.ImageInspect, error) {
	ctx, _ := context.WithTimeout(context.Background(), 2*time.Minute)
	resp, _, err := s.client.ImageInspectWithRaw(ctx, name, true)
	if err != nil {
		if dockerapi.IsErrImageNotFound(err) {
			return nil, fmt.Errorf("no such image :%q", name)
		}
		return nil, err
	}
	return &resp, nil
}
func (i integrationTest) InspectImage(name string) (*dockertypes.ImageInspect, error) {
	ctx, cancel := getDefaultContext()
	defer cancel()
	resp, _, err := i.engineClient.ImageInspectWithRaw(ctx, name)
	if err != nil {
		if dockerapi.IsErrImageNotFound(err) {
			return nil, fmt.Errorf("no such image :%q", name)
		}
		return nil, err
	}
	return &resp, nil
}
Beispiel #11
0
func (cli *DockerCli) createContainer(config *container.Config, hostConfig *container.HostConfig, networkingConfig *networktypes.NetworkingConfig, cidfile, name string) (*types.ContainerCreateResponse, error) {
	var containerIDFile *cidFile
	if cidfile != "" {
		var err error
		if containerIDFile, err = newCIDFile(cidfile); err != nil {
			return nil, err
		}
		defer containerIDFile.Close()
	}

	_, ref, err := reference.ParseIDOrReference(config.Image)
	if err != nil {
		return nil, err
	}
	if ref != nil {
		ref = reference.WithDefaultTag(ref)
	}

	//create the container
	response, err := cli.client.ContainerCreate(context.Background(), config, hostConfig, networkingConfig, name)

	//if image not found try to pull it
	if err != nil {
		if client.IsErrImageNotFound(err) && ref != nil {
			fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", ref.String())

			// we don't want to write to stdout anything apart from container.ID
			if err = cli.pullImageCustomOut(config.Image, cli.err); err != nil {
				return nil, err
			}
			// Retry
			var retryErr error
			response, retryErr = cli.client.ContainerCreate(context.Background(), config, hostConfig, networkingConfig, name)
			if retryErr != nil {
				return nil, retryErr
			}
		} else {
			return nil, err
		}
	}

	for _, warning := range response.Warnings {
		fmt.Fprintf(cli.err, "WARNING: %s\n", warning)
	}
	if containerIDFile != nil {
		if err = containerIDFile.Write(response.ID); err != nil {
			return nil, err
		}
	}
	return &response, nil
}
Beispiel #12
0
func (c *Container) createContainer(imageName, oldContainer string) (*types.Container, error) {
	configWrapper, err := ConvertToAPI(c.service)
	if err != nil {
		return nil, err
	}

	configWrapper.Config.Image = imageName

	if configWrapper.Config.Labels == nil {
		configWrapper.Config.Labels = map[string]string{}
	}

	configWrapper.Config.Labels[NAME.Str()] = c.name
	configWrapper.Config.Labels[SERVICE.Str()] = c.service.name
	configWrapper.Config.Labels[PROJECT.Str()] = c.service.context.Project.Name
	configWrapper.Config.Labels[HASH.Str()] = c.getHash()

	err = c.populateAdditionalHostConfig(configWrapper.HostConfig)
	if err != nil {
		return nil, err
	}

	if oldContainer != "" {
		info, err := c.client.ContainerInspect(context.Background(), oldContainer)
		if err != nil {
			return nil, err
		}
		configWrapper.HostConfig.Binds = util.Merge(configWrapper.HostConfig.Binds, volumeBinds(configWrapper.Config.Volumes, &info))
	}

	logrus.Debugf("Creating container %s %#v", c.name, configWrapper)

	container, err := c.client.ContainerCreate(context.Background(), configWrapper.Config, configWrapper.HostConfig, configWrapper.NetworkingConfig, c.name)
	if err != nil {
		if client.IsErrImageNotFound(err) {
			logrus.Debugf("Not Found, pulling image %s", configWrapper.Config.Image)
			if err = c.pull(configWrapper.Config.Image); err != nil {
				return nil, err
			}
			if container, err = c.client.ContainerCreate(context.Background(), configWrapper.Config, configWrapper.HostConfig, configWrapper.NetworkingConfig, c.name); err != nil {
				return nil, err
			}
		} else {
			logrus.Debugf("Failed to create container %s: %v", c.name, err)
			return nil, err
		}
	}

	return GetContainerByID(c.client, container.ID)
}
Beispiel #13
0
// Create a new container
func (e *Engine) Create(config *ContainerConfig, name string, pullImage bool, authConfig *types.AuthConfig) (*Container, error) {
	var (
		err        error
		createResp types.ContainerCreateResponse
	)

	// Convert our internal ContainerConfig into something Docker will
	// understand.  Start by making a copy of the internal ContainerConfig as
	// we don't want to mess with the original.
	dockerConfig := *config

	// nb of CPUs -> real CpuShares

	// FIXME remove "duplicate" lines and move this to cluster/config.go
	dockerConfig.HostConfig.CPUShares = int64(math.Ceil(float64(config.HostConfig.CPUShares*1024) / float64(e.Cpus)))

	createResp, err = e.apiClient.ContainerCreate(context.Background(), &dockerConfig.Config, &dockerConfig.HostConfig, &dockerConfig.NetworkingConfig, name)
	e.CheckConnectionErr(err)
	if err != nil {
		// If the error is other than not found, abort immediately.
		if (err != dockerclient.ErrImageNotFound && !engineapi.IsErrImageNotFound(err)) || !pullImage {
			return nil, err
		}
		// Otherwise, try to pull the image...
		if err = e.Pull(config.Image, authConfig); err != nil {
			return nil, err
		}
		// ...And try again.
		createResp, err = e.apiClient.ContainerCreate(context.Background(), &dockerConfig.Config, &dockerConfig.HostConfig, &dockerConfig.NetworkingConfig, name)
		e.CheckConnectionErr(err)
		if err != nil {
			return nil, err
		}
	}

	// Register the container immediately while waiting for a state refresh.
	// Force a state refresh to pick up the newly created container.
	e.refreshContainer(createResp.ID, true)
	e.RefreshVolumes()
	e.RefreshNetworks()

	e.Lock()
	container := e.containers[createResp.ID]
	e.Unlock()

	if container == nil {
		err = errors.New("Container created but refresh didn't report it back")
	}
	return container, err
}
func (d *kubeDockerClient) InspectImage(image string) (*dockertypes.ImageInspect, error) {
	ctx, cancel := d.getTimeoutContext()
	defer cancel()
	resp, _, err := d.client.ImageInspectWithRaw(ctx, image, true)
	if ctxErr := contextError(ctx); ctxErr != nil {
		return nil, ctxErr
	}
	if err != nil {
		if dockerapi.IsErrImageNotFound(err) {
			err = imageNotFoundError{ID: image}
		}
		return nil, err
	}
	return &resp, nil
}
func (d *kubeDockerClient) InspectImage(image string) (*docker.Image, error) {
	resp, _, err := d.client.ImageInspectWithRaw(getDefaultContext(), image, true)
	if err != nil {
		// TODO(random-liu): Use IsErrImageNotFound instead of ErrNoSuchImage
		if dockerapi.IsErrImageNotFound(err) {
			err = docker.ErrNoSuchImage
		}
		return nil, err
	}
	imageInfo := &docker.Image{}
	if err := convertType(&resp, imageInfo); err != nil {
		return nil, err
	}
	return imageInfo, nil
}
Beispiel #16
0
func (s *Service) ensureImageExists() (string, error) {
	err := s.imageExists()

	if err == nil {
		return s.imageName(), nil
	}

	if err != nil && !client.IsErrImageNotFound(err) {
		return "", err
	}

	if s.Config().Build != "" {
		if s.context.NoBuild {
			return "", fmt.Errorf("Service %q needs to be built, but no-build was specified", s.name)
		}
		return s.imageName(), s.build()
	}

	return s.imageName(), s.Pull()
}
Beispiel #17
0
func (cli *DockerCli) inspectAll(getSize bool) inspectSearcher {
	return func(ref string) (interface{}, []byte, error) {
		c, rawContainer, err := cli.client.ContainerInspectWithRaw(ref, getSize)
		if err != nil {
			// Search for image with that id if a container doesn't exist.
			if client.IsErrContainerNotFound(err) {
				i, rawImage, err := cli.client.ImageInspectWithRaw(ref, getSize)
				if err != nil {
					if client.IsErrImageNotFound(err) {
						return nil, nil, fmt.Errorf("Error: No such image or container: %s", ref)
					}
					return nil, nil, err
				}
				return i, rawImage, err
			}
			return nil, nil, err
		}
		return c, rawContainer, err
	}
}
Beispiel #18
0
func (p *Project) ensureImageExists(ref string, force bool) error {
	if !force {
		// Check if ref is already there
		_, _, err := p.Client.ImageInspectWithRaw(context.Background(), ref, false)
		if err != nil && !client.IsErrImageNotFound(err) {
			return err
		}
		if err == nil {
			return nil
		}
	}

	// And pull it
	responseBody, err := p.Client.ImagePull(context.Background(), ref, types.ImagePullOptions{})
	if err != nil {
		fmt.Printf("%v", err)
		return err
	}
	defer responseBody.Close()

	_, err = ioutil.ReadAll(responseBody)
	return err
}
Beispiel #19
0
func createContainer(ctx context.Context, dockerCli *client.DockerCli, config *container.Config, hostConfig *container.HostConfig, networkingConfig *networktypes.NetworkingConfig, cidfile, name string) (*types.ContainerCreateResponse, error) {
	stderr := dockerCli.Err()

	var containerIDFile *cidFile
	if cidfile != "" {
		var err error
		if containerIDFile, err = newCIDFile(cidfile); err != nil {
			return nil, err
		}
		defer containerIDFile.Close()
	}

	var trustedRef reference.Canonical
	_, ref, err := reference.ParseIDOrReference(config.Image)
	if err != nil {
		return nil, err
	}
	if ref != nil {
		ref = reference.WithDefaultTag(ref)

		if ref, ok := ref.(reference.NamedTagged); ok && client.IsTrusted() {
			var err error
			trustedRef, err = dockerCli.TrustedReference(ctx, ref)
			if err != nil {
				return nil, err
			}
			config.Image = trustedRef.String()
		}
	}

	//create the container
	response, err := dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, name)

	//if image not found try to pull it
	if err != nil {
		if apiclient.IsErrImageNotFound(err) && ref != nil {
			fmt.Fprintf(stderr, "Unable to find image '%s' locally\n", ref.String())

			// we don't want to write to stdout anything apart from container.ID
			if err = pullImage(ctx, dockerCli, config.Image, stderr); err != nil {
				return nil, err
			}
			if ref, ok := ref.(reference.NamedTagged); ok && trustedRef != nil {
				if err := dockerCli.TagTrusted(ctx, trustedRef, ref); err != nil {
					return nil, err
				}
			}
			// Retry
			var retryErr error
			response, retryErr = dockerCli.Client().ContainerCreate(ctx, config, hostConfig, networkingConfig, name)
			if retryErr != nil {
				return nil, retryErr
			}
		} else {
			return nil, err
		}
	}

	for _, warning := range response.Warnings {
		fmt.Fprintf(stderr, "WARNING: %s\n", warning)
	}
	if containerIDFile != nil {
		if err = containerIDFile.Write(response.ID); err != nil {
			return nil, err
		}
	}
	return &response, nil
}
Beispiel #20
0
// create the volumes container that keeps all of the volumes used by
// the cluster.
func (l *LocalCluster) initCluster() {
	log.Infof("initializing cluster")
	l.panicOnStop()

	// Create the temporary certs directory in the current working
	// directory. Boot2docker's handling of binding local directories
	// into the container is very confusing. If the directory being
	// bound has a parent directory that exists in the boot2docker VM
	// then that directory is bound into the container. In particular,
	// that means that binds of /tmp and /var will be problematic.
	var err error
	l.CertsDir, err = ioutil.TempDir(pwd, ".localcluster.certs.")
	maybePanic(err)

	binds := []string{
		l.CertsDir + ":/certs",
		filepath.Join(pwd, "..") + ":/go/src/github.com/cockroachdb/cockroach",
	}

	if l.logDir != "" {
		l.keepLogs = true
		if !filepath.IsAbs(l.logDir) {
			l.logDir = filepath.Join(pwd, l.logDir)
		}
		binds = append(binds, l.logDir+":/logs")
		// If we don't make sure the directory exists, Docker will and then we
		// may run into ownership issues (think Docker running as root, but us
		// running as a regular Joe as it happens on CircleCI).
		maybePanic(os.MkdirAll(l.logDir, 0777))
	}
	if *cockroachImage == builderImage {
		path, err := filepath.Abs(*cockroachBinary)
		maybePanic(err)
		binds = append(binds, path+":/"+filepath.Base(*cockroachBinary))
	}

	vols := map[string]struct{}{}
	for i := 0; i < l.numLocal; i++ {
		for j := 0; j < l.numStores; j++ {
			vols[dataStr(i, j)] = struct{}{}
		}
	}
	create := func() (*Container, error) {
		return createContainer(
			l,
			container.Config{
				Image:      *cockroachImage,
				Volumes:    vols,
				Entrypoint: strslice.New("/bin/true"),
			}, container.HostConfig{
				Binds:           binds,
				PublishAllPorts: true,
			},
			"volumes",
		)
	}
	c, err := create()
	if dockerclient.IsErrImageNotFound(err) && *cockroachImage == builderImage {
		if err := pullImage(l, types.ImagePullOptions{ImageID: *cockroachImage}); err != nil {
			log.Fatal(err)
		}
		c, err = create()
	}
	maybePanic(err)

	maybePanic(c.Start())
	maybePanic(c.Wait())
	l.vols = c
}