mirror of
https://github.com/containers/podman.git
synced 2026-04-03 22:43:15 -04:00
Podman is not the only user of containers/storage, and as such we cannot rely on our database as the sole source of truth when pruning images. If images do not show as in use from Podman's perspective, but subsequently fail to remove because they are being used by a container, they're probably being used by Buildah or another c/storage client. Since the images in question are in use, we shouldn't error on failure to prune them - we weren't supposed to prune them in the first place. Fixes: #3983 Signed-off-by: Matthew Heon <matthew.heon@pm.me>
60 lines
1.4 KiB
Go
60 lines
1.4 KiB
Go
package image
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/containers/libpod/libpod/events"
|
|
"github.com/containers/storage"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// GetPruneImages returns a slice of images that have no names/unused
|
|
func (ir *Runtime) GetPruneImages(all bool) ([]*Image, error) {
|
|
var (
|
|
pruneImages []*Image
|
|
)
|
|
allImages, err := ir.GetRWImages()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, i := range allImages {
|
|
if len(i.Names()) == 0 {
|
|
pruneImages = append(pruneImages, i)
|
|
continue
|
|
}
|
|
if all {
|
|
containers, err := i.Containers()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(containers) < 1 {
|
|
pruneImages = append(pruneImages, i)
|
|
}
|
|
}
|
|
}
|
|
return pruneImages, nil
|
|
}
|
|
|
|
// PruneImages prunes dangling and optionally all unused images from the local
|
|
// image store
|
|
func (ir *Runtime) PruneImages(ctx context.Context, all bool) ([]string, error) {
|
|
var prunedCids []string
|
|
pruneImages, err := ir.GetPruneImages(all)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "unable to get images to prune")
|
|
}
|
|
for _, p := range pruneImages {
|
|
if err := p.Remove(ctx, true); err != nil {
|
|
if errors.Cause(err) == storage.ErrImageUsedByContainer {
|
|
logrus.Warnf("Failed to prune image %s as it is in use: %v", p.ID(), err)
|
|
continue
|
|
}
|
|
return nil, errors.Wrap(err, "failed to prune image")
|
|
}
|
|
defer p.newImageEvent(events.Prune)
|
|
prunedCids = append(prunedCids, p.ID())
|
|
}
|
|
return prunedCids, nil
|
|
}
|