From 647b4aeccef8dc3ae035caf586f67c7773945f7e Mon Sep 17 00:00:00 2001 From: Brian Goff Date: Mon, 22 May 2017 13:41:16 -0400 Subject: [PATCH 1/2] Don't prune volumes on `docker system prune` Volumes tend to carry important data and pruning them on `docker system prune` can easily cause unwanted data loss. Let's play it safe and not prune volumes on `system prune` by default, and instead provide an option. Signed-off-by: Brian Goff (cherry picked from commit 37fd6128dc268b885f070b6d89a72e73d2eacec8) Signed-off-by: Andrew Hsu --- components/cli/cli/command/system/prune.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/components/cli/cli/command/system/prune.go b/components/cli/cli/command/system/prune.go index 11a45146a7b..fca9c98f2c5 100644 --- a/components/cli/cli/command/system/prune.go +++ b/components/cli/cli/command/system/prune.go @@ -12,9 +12,10 @@ import ( ) type pruneOptions struct { - force bool - all bool - filter opts.FilterOpt + force bool + all bool + pruneVolumes bool + filter opts.FilterOpt } // NewPruneCommand creates a new cobra.Command for `docker prune` @@ -34,6 +35,7 @@ func NewPruneCommand(dockerCli command.Cli) *cobra.Command { flags := cmd.Flags() flags.BoolVarP(&options.force, "force", "f", false, "Do not prompt for confirmation") flags.BoolVarP(&options.all, "all", "a", false, "Remove all unused images not just dangling ones") + flags.BoolVar(&options.pruneVolumes, "volumes", false, "Prune volumes") flags.Var(&options.filter, "filter", "Provide filter values (e.g. 'label==')") // "filter" flag is available in 1.28 (docker 17.04) and up flags.SetAnnotation("filter", "version", []string{"1.28"}) @@ -67,12 +69,15 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error { } var spaceReclaimed uint64 - - for _, pruneFn := range []func(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error){ + pruneFuncs := []func(dockerCli command.Cli, filter opts.FilterOpt) (uint64, string, error){ prune.RunContainerPrune, - prune.RunVolumePrune, prune.RunNetworkPrune, - } { + } + if options.pruneVolumes { + pruneFuncs = append(pruneFuncs, prune.RunVolumePrune) + } + + for _, pruneFn := range pruneFuncs { spc, output, err := pruneFn(dockerCli, options.filter) if err != nil { return err From f7a9f9fb67187e89564037c8dbd25eeb6580b242 Mon Sep 17 00:00:00 2001 From: Harald Albers Date: Thu, 29 Jun 2017 14:52:32 +0200 Subject: [PATCH 2/2] system prune: only warn about volumes if --volumes is given Signed-off-by: Harald Albers (cherry picked from commit 849b0e96a01e657f4be4c35e7fa4bce2736dc376) Conflicts: components/cli/cli/command/system/prune.go Signed-off-by: Andrew Hsu --- components/cli/cli/command/system/prune.go | 49 +++++++++++++--------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/components/cli/cli/command/system/prune.go b/components/cli/cli/command/system/prune.go index fca9c98f2c5..43569294166 100644 --- a/components/cli/cli/command/system/prune.go +++ b/components/cli/cli/command/system/prune.go @@ -1,7 +1,9 @@ package system import ( + "bytes" "fmt" + "text/template" "github.com/docker/cli/cli" "github.com/docker/cli/cli/command" @@ -43,28 +45,14 @@ func NewPruneCommand(dockerCli command.Cli) *cobra.Command { return cmd } -const ( - warning = `WARNING! This will remove: - - all stopped containers - - all volumes not used by at least one container - - all networks not used by at least one container - %s +const confirmationTemplate = `WARNING! This will remove: +{{- range $_, $warning := . }} + - {{ $warning }} +{{- end }} Are you sure you want to continue?` - danglingImageDesc = "- all dangling images" - allImageDesc = `- all images without at least one container associated to them` -) - func runPrune(dockerCli command.Cli, options pruneOptions) error { - var message string - - if options.all { - message = fmt.Sprintf(warning, allImageDesc) - } else { - message = fmt.Sprintf(warning, danglingImageDesc) - } - - if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), message) { + if !options.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), confirmationMessage(options)) { return nil } @@ -101,3 +89,26 @@ func runPrune(dockerCli command.Cli, options pruneOptions) error { return nil } + +// confirmationMessage constructs a confirmation message that depends on the cli options. +func confirmationMessage(options pruneOptions) string { + t := template.Must(template.New("confirmation message").Parse(confirmationTemplate)) + + warnings := []string{ + "all stopped containers", + "all networks not used by at least one container", + } + if options.pruneVolumes { + warnings = append(warnings, "all volumes not used by at least one container") + } + if options.all { + warnings = append(warnings, "all images without at least one container associated to them") + } else { + warnings = append(warnings, "all dangling images") + } + warnings = append(warnings, "all build cache") + + var buffer bytes.Buffer + t.Execute(&buffer, &warnings) + return buffer.String() +}