prune.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package system
  2. import (
  3. "fmt"
  4. "github.com/docker/docker/cli"
  5. "github.com/docker/docker/cli/command"
  6. "github.com/docker/docker/cli/command/prune"
  7. "github.com/docker/docker/opts"
  8. units "github.com/docker/go-units"
  9. "github.com/spf13/cobra"
  10. )
  11. type pruneOptions struct {
  12. force bool
  13. all bool
  14. filter opts.FilterOpt
  15. }
  16. // NewPruneCommand creates a new cobra.Command for `docker prune`
  17. func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command {
  18. opts := pruneOptions{filter: opts.NewFilterOpt()}
  19. cmd := &cobra.Command{
  20. Use: "prune [OPTIONS]",
  21. Short: "Remove unused data",
  22. Args: cli.NoArgs,
  23. RunE: func(cmd *cobra.Command, args []string) error {
  24. return runPrune(dockerCli, opts)
  25. },
  26. Tags: map[string]string{"version": "1.25"},
  27. }
  28. flags := cmd.Flags()
  29. flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation")
  30. flags.BoolVarP(&opts.all, "all", "a", false, "Remove all unused images not just dangling ones")
  31. flags.Var(&opts.filter, "filter", "Provide filter values (e.g. 'until=<timestamp>')")
  32. return cmd
  33. }
  34. const (
  35. warning = `WARNING! This will remove:
  36. - all stopped containers
  37. - all volumes not used by at least one container
  38. - all networks not used by at least one container
  39. %s
  40. Are you sure you want to continue?`
  41. danglingImageDesc = "- all dangling images"
  42. allImageDesc = `- all images without at least one container associated to them`
  43. )
  44. func runPrune(dockerCli *command.DockerCli, options pruneOptions) error {
  45. var message string
  46. if options.all {
  47. message = fmt.Sprintf(warning, allImageDesc)
  48. } else {
  49. message = fmt.Sprintf(warning, danglingImageDesc)
  50. }
  51. if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), message) {
  52. return nil
  53. }
  54. var spaceReclaimed uint64
  55. for _, pruneFn := range []func(dockerCli *command.DockerCli, filter opts.FilterOpt) (uint64, string, error){
  56. prune.RunContainerPrune,
  57. prune.RunVolumePrune,
  58. prune.RunNetworkPrune,
  59. } {
  60. spc, output, err := pruneFn(dockerCli, options.filter)
  61. if err != nil {
  62. return err
  63. }
  64. spaceReclaimed += spc
  65. if output != "" {
  66. fmt.Fprintln(dockerCli.Out(), output)
  67. }
  68. }
  69. spc, output, err := prune.RunImagePrune(dockerCli, options.all, options.filter)
  70. if err != nil {
  71. return err
  72. }
  73. if spc > 0 {
  74. spaceReclaimed += spc
  75. fmt.Fprintln(dockerCli.Out(), output)
  76. }
  77. fmt.Fprintln(dockerCli.Out(), "Total reclaimed space:", units.HumanSize(float64(spaceReclaimed)))
  78. return nil
  79. }