github.1git.de/docker/cli@v26.1.3+incompatible/cli/command/image/prune.go (about)

     1  package image
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  
     9  	"github.com/docker/cli/cli"
    10  	"github.com/docker/cli/cli/command"
    11  	"github.com/docker/cli/cli/command/completion"
    12  	"github.com/docker/cli/opts"
    13  	"github.com/docker/docker/errdefs"
    14  	units "github.com/docker/go-units"
    15  	"github.com/pkg/errors"
    16  	"github.com/spf13/cobra"
    17  )
    18  
    19  type pruneOptions struct {
    20  	force  bool
    21  	all    bool
    22  	filter opts.FilterOpt
    23  }
    24  
    25  // NewPruneCommand returns a new cobra prune command for images
    26  func NewPruneCommand(dockerCli command.Cli) *cobra.Command {
    27  	options := pruneOptions{filter: opts.NewFilterOpt()}
    28  
    29  	cmd := &cobra.Command{
    30  		Use:   "prune [OPTIONS]",
    31  		Short: "Remove unused images",
    32  		Args:  cli.NoArgs,
    33  		RunE: func(cmd *cobra.Command, args []string) error {
    34  			spaceReclaimed, output, err := runPrune(cmd.Context(), dockerCli, options)
    35  			if err != nil {
    36  				return err
    37  			}
    38  			if output != "" {
    39  				fmt.Fprintln(dockerCli.Out(), output)
    40  			}
    41  			fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed)))
    42  			return nil
    43  		},
    44  		Annotations:       map[string]string{"version": "1.25"},
    45  		ValidArgsFunction: completion.NoComplete,
    46  	}
    47  
    48  	flags := cmd.Flags()
    49  	flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation")
    50  	flags.BoolVarP(&options.all, "all", "a", false, "Remove all unused images, not just dangling ones")
    51  	flags.Var(&options.filter, "filter", `Provide filter values (e.g. "until=<timestamp>")`)
    52  
    53  	return cmd
    54  }
    55  
    56  const (
    57  	allImageWarning = `WARNING! This will remove all images without at least one container associated to them.
    58  Are you sure you want to continue?`
    59  	danglingWarning = `WARNING! This will remove all dangling images.
    60  Are you sure you want to continue?`
    61  )
    62  
    63  func runPrune(ctx context.Context, dockerCli command.Cli, options pruneOptions) (spaceReclaimed uint64, output string, err error) {
    64  	pruneFilters := options.filter.Value().Clone()
    65  	pruneFilters.Add("dangling", strconv.FormatBool(!options.all))
    66  	pruneFilters = command.PruneFilters(dockerCli, pruneFilters)
    67  
    68  	warning := danglingWarning
    69  	if options.all {
    70  		warning = allImageWarning
    71  	}
    72  	if !options.force {
    73  		r, err := command.PromptForConfirmation(ctx, dockerCli.In(), dockerCli.Out(), warning)
    74  		if err != nil {
    75  			return 0, "", err
    76  		}
    77  		if !r {
    78  			return 0, "", errdefs.Cancelled(errors.New("image prune has been cancelled"))
    79  		}
    80  	}
    81  
    82  	report, err := dockerCli.Client().ImagesPrune(ctx, pruneFilters)
    83  	if err != nil {
    84  		return 0, "", err
    85  	}
    86  
    87  	if len(report.ImagesDeleted) > 0 {
    88  		var sb strings.Builder
    89  		sb.WriteString("Deleted Images:\n")
    90  		for _, st := range report.ImagesDeleted {
    91  			if st.Untagged != "" {
    92  				sb.WriteString("untagged: ")
    93  				sb.WriteString(st.Untagged)
    94  				sb.WriteByte('\n')
    95  			} else {
    96  				sb.WriteString("deleted: ")
    97  				sb.WriteString(st.Deleted)
    98  				sb.WriteByte('\n')
    99  			}
   100  		}
   101  		output = sb.String()
   102  		spaceReclaimed = report.SpaceReclaimed
   103  	}
   104  
   105  	return spaceReclaimed, output, nil
   106  }
   107  
   108  // RunPrune calls the Image Prune API
   109  // This returns the amount of space reclaimed and a detailed output string
   110  func RunPrune(ctx context.Context, dockerCli command.Cli, all bool, filter opts.FilterOpt) (uint64, string, error) {
   111  	return runPrune(ctx, dockerCli, pruneOptions{force: true, all: all, filter: filter})
   112  }