From a23615aecf3d898d487dffed04e1303cae87833a Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Mon, 19 Jul 2021 13:49:02 +0200 Subject: [PATCH] refine dangling filter By proxy by vendoring containers/common. Previously, a "dangling" image was an untagged image; just a described in the Docker docs. The definition of dangling has now been refined to an untagged image without children to be compatible with Docker. Signed-off-by: Valentin Rothberg --- go.mod | 2 +- go.sum | 7 +- tests/rmi.bats | 15 ++++ .../containers/common/libimage/filters.go | 10 ++- .../containers/common/libimage/image.go | 68 +++++++------- .../containers/common/libimage/image_tree.go | 4 + .../containers/common/libimage/layer_tree.go | 90 ++++++++++++++----- .../containers/common/libimage/pull.go | 19 +++- .../containers/common/libimage/runtime.go | 38 ++++---- .../containers/common/pkg/config/config.go | 11 +++ .../common/pkg/config/containers.conf | 7 ++ .../containers/common/pkg/config/default.go | 2 + .../containers/common/version/version.go | 2 +- vendor/modules.txt | 2 +- 14 files changed, 198 insertions(+), 79 deletions(-) diff --git a/go.mod b/go.mod index 9d9a542d467..68721b73cf6 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.12 require ( github.com/containernetworking/cni v0.8.1 - github.com/containers/common v0.40.2-0.20210707094508-0a4a1906d4b2 + github.com/containers/common v0.41.1-0.20210721112610-c95d2f794edf github.com/containers/image/v5 v5.13.2 github.com/containers/ocicrypt v1.1.2 github.com/containers/storage v1.32.6 diff --git a/go.sum b/go.sum index 155e6d5da38..ce7eb6c7477 100644 --- a/go.sum +++ b/go.sum @@ -225,8 +225,8 @@ github.com/containernetworking/cni v0.8.1 h1:7zpDnQ3T3s4ucOuJ/ZCLrYBxzkg0AELFfII github.com/containernetworking/cni v0.8.1/go.mod h1:LGwApLUm2FpoOfxTDEeq8T9ipbpZ61X79hmU3w8FmsY= github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHVlzhJpcY6TQxn/fUyDDM= github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= -github.com/containers/common v0.40.2-0.20210707094508-0a4a1906d4b2 h1:2ApmOS9jSnJXuSOkZNEAZ7j0/9i8zjoi67b/UpUjPxY= -github.com/containers/common v0.40.2-0.20210707094508-0a4a1906d4b2/go.mod h1:thow5Jn7O+rP01njI9COQ16L9g/KQ1LcMcYqP2NhYCU= +github.com/containers/common v0.41.1-0.20210721112610-c95d2f794edf h1:z0ciG0ByyJG3WCBpLYd2XLThCC7UBaH7GeSfXY4sAqc= +github.com/containers/common v0.41.1-0.20210721112610-c95d2f794edf/go.mod h1:Ba5YVNCnyX6xDtg1JqEHa2EMVMW5UbHmIyEqsEwpeGE= github.com/containers/image/v5 v5.13.2 h1:AgYunV/9d2fRkrmo23wH2MkqeHolFd6oQCkK+1PpuFA= github.com/containers/image/v5 v5.13.2/go.mod h1:GkWursKDlDcUIT7L7vZf70tADvZCk/Ga0wgS0MuF0ag= github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b h1:Q8ePgVfHDplZ7U33NwHZkrVELsZP5fYj9pM5WBZB2GE= @@ -237,7 +237,6 @@ github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B github.com/containers/ocicrypt v1.1.2 h1:Ez+GAMP/4GLix5Ywo/fL7O0nY771gsBIigiqUm1aXz0= github.com/containers/ocicrypt v1.1.2/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/containers/storage v1.32.2/go.mod h1:YIBxxjfXZTi04Ah49sh1uSGfmT1V89+I5i3deRobzQo= -github.com/containers/storage v1.32.5/go.mod h1:8/DVVDqniaUlUV0D0q7cEnXK6Bs2uU3FPqNZVPumwEs= github.com/containers/storage v1.32.6 h1:NqdFRewXO/PYPjgCAScoigZc5QUA21yapSEj6kqD8cw= github.com/containers/storage v1.32.6/go.mod h1:mdB+b89p+jU8zpzLTVXA0gWMmIo0WrkfGMh1R8O2IQw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -612,7 +611,6 @@ github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= @@ -621,7 +619,6 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/onsi/gomega v1.14.0 h1:ep6kpPVwmr/nTbklSx2nrLNSIO62DoYAhnPNIMhK8gI= github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= diff --git a/tests/rmi.bats b/tests/rmi.bats index 8570e7f0ecb..061d29ec0bf 100644 --- a/tests/rmi.bats +++ b/tests/rmi.bats @@ -155,6 +155,21 @@ load helpers expect_output "" } +@test "attempt to prune non-dangling empty images" { + # Regression test for containers/podman/issues/10832 + ctxdir=${TESTDIR}/bud + mkdir -p $ctxdir + cat >$ctxdir/Dockerfile < 0 { + return false, nil + } + children, err := i.getChildren(ctx, false) + if err != nil { + return false, err + } + return len(children) == 0, nil } // IsIntermediate returns true if the image is an intermediate image, that is -// a dangling image without children. +// an untagged image with children. func (i *Image) IsIntermediate(ctx context.Context) (bool, error) { - // If the image has tags, it's not an intermediate one. - if !i.IsDangling() { + if len(i.Names()) > 0 { return false, nil } children, err := i.getChildren(ctx, false) if err != nil { return false, err } - // No tags, no children -> intermediate! return len(children) != 0, nil } @@ -271,7 +276,7 @@ type RemoveImageReport struct { // remove removes the image along with all dangling parent images that no other // image depends on. The image must not be set read-only and not be used by -// containers. +// containers. Returns IDs of removed/untagged images in order. // // If the image is used by containers return storage.ErrImageUsedByContainer. // Use force to remove these containers. @@ -282,7 +287,12 @@ type RemoveImageReport struct { // // This function is internal. Users of libimage should always use // `(*Runtime).RemoveImages()`. -func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, referencedBy string, options *RemoveImagesOptions) error { +func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, referencedBy string, options *RemoveImagesOptions) ([]string, error) { + processedIDs := []string{} + return i.removeRecursive(ctx, rmMap, processedIDs, referencedBy, options) +} + +func (i *Image) removeRecursive(ctx context.Context, rmMap map[string]*RemoveImageReport, processedIDs []string, referencedBy string, options *RemoveImagesOptions) ([]string, error) { // If referencedBy is empty, the image is considered to be removed via // `image remove --all` which alters the logic below. @@ -294,7 +304,7 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, logrus.Debugf("Removing image %s", i.ID()) if i.IsReadOnly() { - return errors.Errorf("cannot remove read-only image %q", i.ID()) + return processedIDs, errors.Errorf("cannot remove read-only image %q", i.ID()) } if i.runtime.eventChannel != nil { @@ -306,7 +316,7 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, if exists { // If the image has already been removed, we're done. if report.Removed { - return nil + return processedIDs, nil } } else { report = &RemoveImageReport{ID: i.ID()} @@ -333,7 +343,7 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, if options.WithSize { size, err := i.Size() if handleError(err) != nil { - return err + return processedIDs, err } report.Size = size } @@ -354,18 +364,18 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, byDigest := strings.HasPrefix(referencedBy, "sha256:") if !options.Force { if byID && numNames > 1 { - return errors.Errorf("unable to delete image %q by ID with more than one tag (%s): please force removal", i.ID(), i.Names()) + return processedIDs, errors.Errorf("unable to delete image %q by ID with more than one tag (%s): please force removal", i.ID(), i.Names()) } else if byDigest && numNames > 1 { // FIXME - Docker will remove the digest but containers storage // does not support that yet, so our hands are tied. - return errors.Errorf("unable to delete image %q by digest with more than one tag (%s): please force removal", i.ID(), i.Names()) + return processedIDs, errors.Errorf("unable to delete image %q by digest with more than one tag (%s): please force removal", i.ID(), i.Names()) } } // Only try to untag if we know it's not an ID or digest. if !byID && !byDigest { if err := i.Untag(referencedBy); handleError(err) != nil { - return err + return processedIDs, err } report.Untagged = append(report.Untagged, referencedBy) @@ -374,14 +384,15 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, } } + processedIDs = append(processedIDs, i.ID()) if skipRemove { - return nil + return processedIDs, nil } // Perform the actual removal. First, remove containers if needed. if options.Force { if err := i.removeContainers(options.RemoveContainerFunc); err != nil { - return err + return processedIDs, err } } @@ -407,7 +418,7 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, } if _, err := i.runtime.store.DeleteImage(i.ID(), true); handleError(err) != nil { - return err + return processedIDs, err } report.Untagged = append(report.Untagged, i.Names()...) @@ -417,27 +428,24 @@ func (i *Image) remove(ctx context.Context, rmMap map[string]*RemoveImageReport, // Check if can remove the parent image. if parent == nil { - return nil + return processedIDs, nil } - if !parent.IsDangling() { - return nil - } - - // If the image has siblings, we don't remove the parent. - hasSiblings, err := parent.HasChildren(ctx) + // Only remove the parent if it's dangling, that is being untagged and + // without children. + danglingParent, err := parent.IsDangling(ctx) if err != nil { // See Podman commit fd9dd7065d44: we need to // be tolerant toward corrupted images. logrus.Warnf("error determining if an image is a parent: %v, ignoring the error", err) - hasSiblings = false + danglingParent = false } - if hasSiblings { - return nil + if !danglingParent { + return processedIDs, nil } // Recurse into removing the parent. - return parent.remove(ctx, rmMap, "", options) + return parent.removeRecursive(ctx, rmMap, processedIDs, "", options) } // Tag the image with the specified name and store it in the local containers diff --git a/vendor/github.com/containers/common/libimage/image_tree.go b/vendor/github.com/containers/common/libimage/image_tree.go index b8b9cb21605..d48aeeada34 100644 --- a/vendor/github.com/containers/common/libimage/image_tree.go +++ b/vendor/github.com/containers/common/libimage/image_tree.go @@ -80,6 +80,10 @@ func (i *Image) Tree(traverseChildren bool) (string, error) { } func imageTreeTraverseChildren(node *layerNode, parent gotree.Tree) error { + if node.layer == nil { + return nil + } + var tags string repoTags, err := node.repoTags() if err != nil { diff --git a/vendor/github.com/containers/common/libimage/layer_tree.go b/vendor/github.com/containers/common/libimage/layer_tree.go index 4195b43c0e7..05f21531b0a 100644 --- a/vendor/github.com/containers/common/libimage/layer_tree.go +++ b/vendor/github.com/containers/common/libimage/layer_tree.go @@ -15,6 +15,9 @@ type layerTree struct { // ociCache is a cache for Image.ID -> OCI Image. Translations are done // on-demand. ociCache map[string]*ociv1.Image + // emptyImages do not have any top-layer so we cannot create a + // *layerNode for them. + emptyImages []*Image } // node returns a layerNode for the specified layerID. @@ -105,6 +108,7 @@ func (r *Runtime) layerTree() (*layerTree, error) { img := images[i] // do not leak loop variable outside the scope topLayer := img.TopLayer() if topLayer == "" { + tree.emptyImages = append(tree.emptyImages, img) continue } node, exists := tree.nodes[topLayer] @@ -126,22 +130,13 @@ func (r *Runtime) layerTree() (*layerTree, error) { // either the same top layer as parent or parent being the true parent layer. // Furthermore, the history of the parent and child images must match with the // parent having one history item less. If all is true, all images are -// returned. Otherwise, the first image is returned. +// returned. Otherwise, the first image is returned. Note that manifest lists +// do not have children. func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]*Image, error) { if parent.TopLayer() == "" { - return nil, nil - } - - var children []*Image - - parentNode, exists := t.nodes[parent.TopLayer()] - if !exists { - // Note: erroring out in this case has turned out having been a - // mistake. Users may not be able to recover, so we're now - // throwing a warning to guide them to resolve the issue and - // turn the errors non-fatal. - logrus.Warnf("Layer %s not found in layer tree. The storage may be corrupted, consider running `podman system reset`.", parent.TopLayer()) - return children, nil + if isManifestList, _ := parent.IsManifestList(ctx); isManifestList { + return nil, nil + } } parentID := parent.ID() @@ -163,6 +158,38 @@ func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]*I return areParentAndChild(parentOCI, childOCI), nil } + var children []*Image + + // Empty images are special in that they do not have any physical layer + // but yet can have a parent-child relation. Hence, compare the + // "parent" image to all other known empty images. + if parent.TopLayer() == "" { + for i := range t.emptyImages { + empty := t.emptyImages[i] + isParent, err := checkParent(empty) + if err != nil { + return nil, err + } + if isParent { + children = append(children, empty) + if !all { + break + } + } + } + return children, nil + } + + parentNode, exists := t.nodes[parent.TopLayer()] + if !exists { + // Note: erroring out in this case has turned out having been a + // mistake. Users may not be able to recover, so we're now + // throwing a warning to guide them to resolve the issue and + // turn the errors non-fatal. + logrus.Warnf("Layer %s not found in layer tree. The storage may be corrupted, consider running `podman system reset`.", parent.TopLayer()) + return children, nil + } + // addChildrenFrom adds child images of parent to children. Returns // true if any image is a child of parent. addChildrenFromNode := func(node *layerNode) (bool, error) { @@ -204,8 +231,37 @@ func (t *layerTree) children(ctx context.Context, parent *Image, all bool) ([]*I } // parent returns the parent image or nil if no parent image could be found. +// Note that manifest lists do not have parents. func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) { if child.TopLayer() == "" { + if isManifestList, _ := child.IsManifestList(ctx); isManifestList { + return nil, nil + } + } + + childID := child.ID() + childOCI, err := t.toOCI(ctx, child) + if err != nil { + return nil, err + } + + // Empty images are special in that they do not have any physical layer + // but yet can have a parent-child relation. Hence, compare the + // "child" image to all other known empty images. + if child.TopLayer() == "" { + for _, empty := range t.emptyImages { + if childID == empty.ID() { + continue + } + emptyOCI, err := t.toOCI(ctx, empty) + if err != nil { + return nil, err + } + // History check. + if areParentAndChild(emptyOCI, childOCI) { + return empty, nil + } + } return nil, nil } @@ -219,14 +275,8 @@ func (t *layerTree) parent(ctx context.Context, child *Image) (*Image, error) { return nil, nil } - childOCI, err := t.toOCI(ctx, child) - if err != nil { - return nil, err - } - // Check images from the parent node (i.e., parent layer) and images // with the same layer (i.e., same top layer). - childID := child.ID() images := node.images if node.parent != nil { images = append(images, node.parent.images...) diff --git a/vendor/github.com/containers/common/libimage/pull.go b/vendor/github.com/containers/common/libimage/pull.go index fbe3b466df4..71cec021bc9 100644 --- a/vendor/github.com/containers/common/libimage/pull.go +++ b/vendor/github.com/containers/common/libimage/pull.go @@ -394,8 +394,23 @@ func (r *Runtime) copySingleImageFromRegistry(ctx context.Context, imageName str // very likely a bug but a consistent one in Podman/Buildah and should // be addressed at a later point. if pullPolicy != config.PullPolicyAlways { - logrus.Debugf("Enforcing pull policy to %q to support custom platform (arch: %q, os: %q, variant: %q)", "always", options.Architecture, options.OS, options.Variant) - pullPolicy = config.PullPolicyAlways + switch { + // User input clearly refer to a local image. + case strings.HasPrefix(imageName, "localhost/"): + logrus.Debugf("Enforcing pull policy to %q to support custom platform (arch: %q, os: %q, variant: %q)", "never", options.Architecture, options.OS, options.Variant) + pullPolicy = config.PullPolicyNever + + // Image resolved to a local one, so let's still have a + // look at the registries or aliases but use it + // otherwise. + case strings.HasPrefix(resolvedImageName, "localhost/"): + logrus.Debugf("Enforcing pull policy to %q to support custom platform (arch: %q, os: %q, variant: %q)", "newer", options.Architecture, options.OS, options.Variant) + pullPolicy = config.PullPolicyNewer + + default: + logrus.Debugf("Enforcing pull policy to %q to support custom platform (arch: %q, os: %q, variant: %q)", "always", options.Architecture, options.OS, options.Variant) + pullPolicy = config.PullPolicyAlways + } } } diff --git a/vendor/github.com/containers/common/libimage/runtime.go b/vendor/github.com/containers/common/libimage/runtime.go index 1fd2973cbc2..26a04dad58e 100644 --- a/vendor/github.com/containers/common/libimage/runtime.go +++ b/vendor/github.com/containers/common/libimage/runtime.go @@ -3,7 +3,6 @@ package libimage import ( "context" "os" - "path/filepath" "strings" "github.com/containers/image/v5/docker/reference" @@ -94,10 +93,6 @@ func RuntimeFromStore(store storage.Store, options *RuntimeOptions) (*Runtime, e setRegistriesConfPath(&systemContext) - if systemContext.BlobInfoCacheDir == "" { - systemContext.BlobInfoCacheDir = filepath.Join(store.GraphRoot(), "cache") - } - return &Runtime{ store: store, systemContext: systemContext, @@ -592,11 +587,10 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem rmErrors = append(rmErrors, err) } - orderedIDs := []string{} // determinism and relative order deleteMap := make(map[string]*deleteMe) // ID -> deleteMe - + toDelete := []string{} // Look up images in the local containers storage and fill out - // orderedIDs and the deleteMap. + // toDelete and the deleteMap. switch { case len(names) > 0: // Look up the images one-by-one. That allows for removing @@ -610,15 +604,12 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem } dm, exists := deleteMap[img.ID()] if !exists { - orderedIDs = append(orderedIDs, img.ID()) + toDelete = append(toDelete, img.ID()) dm = &deleteMe{image: img} deleteMap[img.ID()] = dm } dm.referencedBy = append(dm.referencedBy, resolvedName) } - if len(orderedIDs) == 0 { - return nil, rmErrors - } default: filteredImages, err := r.ListImages(ctx, nil, &ListImagesOptions{Filters: options.Filters}) @@ -627,14 +618,21 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem return nil, rmErrors } for _, img := range filteredImages { - orderedIDs = append(orderedIDs, img.ID()) + toDelete = append(toDelete, img.ID()) deleteMap[img.ID()] = &deleteMe{image: img} } } + // Return early if there's no image to delete. + if len(deleteMap) == 0 { + return nil, rmErrors + } + // Now remove the images in the given order. rmMap := make(map[string]*RemoveImageReport) - for _, id := range orderedIDs { + orderedIDs := []string{} + visitedIDs := make(map[string]bool) + for _, id := range toDelete { del, exists := deleteMap[id] if !exists { appendError(errors.Errorf("internal error: ID %s not in found in image-deletion map", id)) @@ -644,9 +642,17 @@ func (r *Runtime) RemoveImages(ctx context.Context, names []string, options *Rem del.referencedBy = []string{""} } for _, ref := range del.referencedBy { - if err := del.image.remove(ctx, rmMap, ref, options); err != nil { + processedIDs, err := del.image.remove(ctx, rmMap, ref, options) + if err != nil { appendError(err) - continue + } + // NOTE: make sure to add given ID only once to orderedIDs. + for _, id := range processedIDs { + if visited := visitedIDs[id]; visited { + continue + } + orderedIDs = append(orderedIDs, id) + visitedIDs[id] = true } } } diff --git a/vendor/github.com/containers/common/pkg/config/config.go b/vendor/github.com/containers/common/pkg/config/config.go index 68076b1170d..84876026da2 100644 --- a/vendor/github.com/containers/common/pkg/config/config.go +++ b/vendor/github.com/containers/common/pkg/config/config.go @@ -158,6 +158,13 @@ type ContainersConfig struct { // PidNS indicates how to create a pid namespace for the container PidNS string `toml:"pidns,omitempty"` + // Copy the content from the underlying image into the newly created + // volume when the container is created instead of when it is started. + // If false, the container engine will not copy the content until + // the container is started. Setting it to true may have negative + // performance implications. + PrepareVolumeOnCreate bool `toml:"prepare_volume_on_create,omitempty"` + // RootlessNetworking depicts the "kind" of networking for rootless // containers. Valid options are `slirp4netns` and `cni`. Default is // `slirp4netns` @@ -384,6 +391,10 @@ type EngineConfig struct { // will refer to the plugin as) mapped to a path, which must point to a // Unix socket that conforms to the Volume Plugin specification. VolumePlugins map[string]string `toml:"volume_plugins,omitempty"` + + // ChownCopiedFiles tells the container engine whether to chown files copied + // into a container to the container's primary uid/gid. + ChownCopiedFiles bool `toml:"chown_copied_files"` } // SetOptions contains a subset of options in a Config. It's used to indicate if diff --git a/vendor/github.com/containers/common/pkg/config/containers.conf b/vendor/github.com/containers/common/pkg/config/containers.conf index 41f3c784a73..f429b96edb6 100644 --- a/vendor/github.com/containers/common/pkg/config/containers.conf +++ b/vendor/github.com/containers/common/pkg/config/containers.conf @@ -189,6 +189,13 @@ default_sysctls = [ # # pids_limit = 2048 +# Copy the content from the underlying image into the newly created volume +# when the container is created instead of when it is started. If false, +# the container engine will not copy the content until the container is started. +# Setting it to true may have negative performance implications. +# +# prepare_volume_on_create = false + # Indicates the networking to be used for rootless containers # rootless_networking = "slirp4netns" diff --git a/vendor/github.com/containers/common/pkg/config/default.go b/vendor/github.com/containers/common/pkg/config/default.go index 5abb6326f49..a16dd0e023c 100644 --- a/vendor/github.com/containers/common/pkg/config/default.go +++ b/vendor/github.com/containers/common/pkg/config/default.go @@ -340,6 +340,8 @@ func defaultConfigFromMemory() (*EngineConfig, error) { c.LockType = "shm" c.MachineEnabled = false + c.ChownCopiedFiles = true + return c, nil } diff --git a/vendor/github.com/containers/common/version/version.go b/vendor/github.com/containers/common/version/version.go index 8907e21ab92..47dca527c2f 100644 --- a/vendor/github.com/containers/common/version/version.go +++ b/vendor/github.com/containers/common/version/version.go @@ -1,4 +1,4 @@ package version // Version is the version of the build. -const Version = "0.40.2-dev" +const Version = "0.41.1-dev" diff --git a/vendor/modules.txt b/vendor/modules.txt index fb39c14706d..a5cde14d80e 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -60,7 +60,7 @@ github.com/containernetworking/cni/pkg/types/020 github.com/containernetworking/cni/pkg/types/current github.com/containernetworking/cni/pkg/utils github.com/containernetworking/cni/pkg/version -# github.com/containers/common v0.40.2-0.20210707094508-0a4a1906d4b2 +# github.com/containers/common v0.41.1-0.20210721112610-c95d2f794edf github.com/containers/common/libimage github.com/containers/common/libimage/manifests github.com/containers/common/pkg/apparmor