Add ctr image prune
Signed-off-by: Jin Dong <jindon@amazon.com>
This commit is contained in:
parent
24020812bb
commit
8e0a3c51a5
@ -47,6 +47,7 @@ var Command = cli.Command{
|
||||
unmountCommand,
|
||||
pullCommand,
|
||||
pushCommand,
|
||||
pruneCommand,
|
||||
removeCommand,
|
||||
tagCommand,
|
||||
setLabelsCommand,
|
||||
@ -355,3 +356,73 @@ var removeCommand = cli.Command{
|
||||
return exitErr
|
||||
},
|
||||
}
|
||||
|
||||
var pruneCommand = cli.Command{
|
||||
Name: "prune",
|
||||
Usage: "remove unused images",
|
||||
Flags: []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "all", // TODO: add more filters
|
||||
Usage: "remove all unused images, not just dangling ones (if all is not specified no images will be pruned)",
|
||||
},
|
||||
},
|
||||
// adapted from `nerdctl`:
|
||||
// https://github.com/containerd/nerdctl/blob/272dc9c29fc1434839d3ec63194d7efa24d7c0ef/cmd/nerdctl/image_prune.go#L86
|
||||
Action: func(context *cli.Context) error {
|
||||
client, ctx, cancel, err := commands.NewClient(context)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer cancel()
|
||||
|
||||
all := context.Bool("all")
|
||||
if !all {
|
||||
log.G(ctx).Warn("No images pruned. `image prune` requires --all to be specified.")
|
||||
// NOP
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
imageStore = client.ImageService()
|
||||
containerStore = client.ContainerService()
|
||||
)
|
||||
imageList, err := imageStore.List(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containerList, err := containerStore.List(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
usedImages := make(map[string]struct{})
|
||||
for _, container := range containerList {
|
||||
usedImages[container.Image] = struct{}{}
|
||||
}
|
||||
|
||||
var removedImages []string
|
||||
for _, image := range imageList {
|
||||
if _, ok := usedImages[image.Name]; ok {
|
||||
continue
|
||||
}
|
||||
removedImages = append(removedImages, image.Name)
|
||||
}
|
||||
|
||||
var delOpts []images.DeleteOpt
|
||||
for i, imageName := range removedImages {
|
||||
// Delete the last image reference synchronously to trigger garbage collection.
|
||||
// This is best effort. It is possible that the image reference is deleted by
|
||||
// someone else before this point.
|
||||
if i == len(removedImages)-1 {
|
||||
delOpts = []images.DeleteOpt{images.SynchronousDelete()}
|
||||
}
|
||||
if err := imageStore.Delete(ctx, imageName, delOpts...); err != nil {
|
||||
if !errdefs.IsNotFound(err) {
|
||||
log.G(ctx).WithError(err).Warnf("failed to delete image %s", imageName)
|
||||
}
|
||||
continue
|
||||
}
|
||||
log.G(ctx).Infof("deleted image: %s\n", imageName)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user