// TagImageWithReference adds the given reference to the image ID provided. func (daemon *Daemon) TagImageWithReference(imageID image.ID, newTag reference.Named) error { if err := daemon.referenceStore.AddTag(newTag, imageID.Digest(), true); err != nil { return err } daemon.LogImageEvent(imageID.String(), newTag.String(), "tag") return nil }
func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]distribution.Descriptor, error) { img, err := s.is.Get(id) if err != nil { return nil, err } if len(img.RootFS.DiffIDs) == 0 { return nil, fmt.Errorf("empty export - not implemented") } var parent digest.Digest var layers []string var foreignSrcs map[layer.DiffID]distribution.Descriptor for i := range img.RootFS.DiffIDs { v1Img := image.V1Image{ Created: img.Created, } if i == len(img.RootFS.DiffIDs)-1 { v1Img = img.V1Image } rootFS := *img.RootFS rootFS.DiffIDs = rootFS.DiffIDs[:i+1] v1ID, err := v1.CreateID(v1Img, rootFS.ChainID(), parent) if err != nil { return nil, err } v1Img.ID = v1ID.Hex() if parent != "" { v1Img.Parent = parent.Hex() } src, err := s.saveLayer(rootFS.ChainID(), v1Img, img.Created) if err != nil { return nil, err } layers = append(layers, v1Img.ID) parent = v1ID if src.Digest != "" { if foreignSrcs == nil { foreignSrcs = make(map[layer.DiffID]distribution.Descriptor) } foreignSrcs[img.RootFS.DiffIDs[i]] = src } } configFile := filepath.Join(s.outDir, id.Digest().Hex()+".json") if err := ioutil.WriteFile(configFile, img.RawJSON(), 0644); err != nil { return nil, err } if err := system.Chtimes(configFile, img.Created, img.Created); err != nil { return nil, err } s.images[id].layers = layers return foreignSrcs, nil }
// checkImageDeleteConflict determines whether there are any conflicts // preventing deletion of the given image from this daemon. A hard conflict is // any image which has the given image as a parent or any running container // using the image. A soft conflict is any tags/digest referencing the given // image or any stopped container using the image. If ignoreSoftConflicts is // true, this function will not check for soft conflict conditions. func (daemon *Daemon) checkImageDeleteConflict(imgID image.ID, mask conflictType) *imageDeleteConflict { // Check if the image has any descendant images. if mask&conflictDependentChild != 0 && len(daemon.imageStore.Children(imgID)) > 0 { return &imageDeleteConflict{ hard: true, imgID: imgID, message: "image has dependent child images", } } if mask&conflictRunningContainer != 0 { // Check if any running container is using the image. running := func(c *container.Container) bool { return c.IsRunning() && c.ImageID == imgID } if container := daemon.containers.First(running); container != nil { return &imageDeleteConflict{ imgID: imgID, hard: true, used: true, message: fmt.Sprintf("image is being used by running container %s", stringid.TruncateID(container.ID)), } } } // Check if any repository tags/digest reference this image. if mask&conflictActiveReference != 0 && len(daemon.referenceStore.References(imgID.Digest())) > 0 { return &imageDeleteConflict{ imgID: imgID, message: "image is referenced in multiple repositories", } } if mask&conflictStoppedContainer != 0 { // Check if any stopped containers reference this image. stopped := func(c *container.Container) bool { return !c.IsRunning() && c.ImageID == imgID } if container := daemon.containers.First(stopped); container != nil { return &imageDeleteConflict{ imgID: imgID, used: true, message: fmt.Sprintf("image is being used by stopped container %s", stringid.TruncateID(container.ID)), } } } return nil }
// removeAllReferencesToImageID attempts to remove every reference to the given // imgID from this daemon's store of repository tag/digest references. Returns // on the first encountered error. Removed references are logged to this // daemon's event service. An "Untagged" types.ImageDelete is added to the // given list of records. func (daemon *Daemon) removeAllReferencesToImageID(imgID image.ID, records *[]types.ImageDelete) error { imageRefs := daemon.referenceStore.References(imgID.Digest()) for _, imageRef := range imageRefs { parsedRef, err := daemon.removeImageRef(imageRef) if err != nil { return err } untaggedRecord := types.ImageDelete{Untagged: parsedRef.String()} daemon.LogImageEvent(imgID.String(), imgID.String(), "untag") *records = append(*records, untaggedRecord) } return nil }
func newV1TopImage(imageID image.ID, img *image.Image, l layer.Layer, parent *v1DependencyImage) (*v1TopImage, error) { v1ID := imageID.Digest().Hex() parentV1ID := "" if parent != nil { parentV1ID = parent.V1ID() } config, err := v1.MakeV1ConfigFromConfig(img, v1ID, parentV1ID, false) if err != nil { return nil, err } return &v1TopImage{ v1ImageCommon: v1ImageCommon{ v1ID: v1ID, config: config, layer: l, }, imageID: imageID, }, nil }
// imageIsDangling returns whether the given image is "dangling" which means // that there are no repository references to the given image and it has no // child images. func (daemon *Daemon) imageIsDangling(imgID image.ID) bool { return !(len(daemon.referenceStore.References(imgID.Digest())) > 0 || len(daemon.imageStore.Children(imgID)) > 0) }