Skip to content

Commit 11cd64f

Browse files
authored
Merge pull request moby#27525 from AkihiroSuda/prune-network-cluster
add `docker network prune`
2 parents 95b459d + 7e24c16 commit 11cd64f

29 files changed

Lines changed: 399 additions & 3 deletions

api/server/router/network/backend.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,5 @@ type Backend interface {
1717
ConnectContainerToNetwork(containerName, networkName string, endpointConfig *network.EndpointSettings) error
1818
DisconnectContainerFromNetwork(containerName string, networkName string, force bool) error
1919
DeleteNetwork(name string) error
20+
NetworksPrune(config *types.NetworksPruneConfig) (*types.NetworksPruneReport, error)
2021
}

api/server/router/network/network.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ func (r *networkRouter) initRoutes() {
3737
router.NewPostRoute("/networks/create", r.postNetworkCreate),
3838
router.NewPostRoute("/networks/{id:.*}/connect", r.postNetworkConnect),
3939
router.NewPostRoute("/networks/{id:.*}/disconnect", r.postNetworkDisconnect),
40+
router.NewPostRoute("/networks/prune", r.postNetworksPrune),
4041
// DELETE
4142
router.NewDeleteRoute("/networks/{id:.*}", r.deleteNetwork),
4243
}

api/server/router/network/network_routes.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,24 @@ func buildEndpointResource(id string, name string, info libnetwork.EndpointInfo)
274274
}
275275
return er
276276
}
277+
278+
func (n *networkRouter) postNetworksPrune(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error {
279+
if err := httputils.ParseForm(r); err != nil {
280+
return err
281+
}
282+
283+
if err := httputils.CheckForJSON(r); err != nil {
284+
return err
285+
}
286+
287+
var cfg types.NetworksPruneConfig
288+
if err := json.NewDecoder(r.Body).Decode(&cfg); err != nil {
289+
return err
290+
}
291+
292+
pruneReport, err := n.backend.NetworksPrune(&cfg)
293+
if err != nil {
294+
return err
295+
}
296+
return httputils.WriteJSON(w, http.StatusOK, pruneReport)
297+
}

api/types/types.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,11 @@ type ContainersPruneConfig struct {
522522
type VolumesPruneConfig struct {
523523
}
524524

525+
// NetworksPruneConfig contains the configuration for Remote API:
526+
// POST "/networks/prune"
527+
type NetworksPruneConfig struct {
528+
}
529+
525530
// ContainersPruneReport contains the response for Remote API:
526531
// POST "/containers/prune"
527532
type ContainersPruneReport struct {
@@ -542,3 +547,9 @@ type ImagesPruneReport struct {
542547
ImagesDeleted []ImageDelete
543548
SpaceReclaimed uint64
544549
}
550+
551+
// NetworksPruneReport contains the response for Remote API:
552+
// POST "/networks/prune"
553+
type NetworksPruneReport struct {
554+
NetworksDeleted []string
555+
}

cli/command/network/cmd.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func NewNetworkCommand(dockerCli *command.DockerCli) *cobra.Command {
2626
newInspectCommand(dockerCli),
2727
newListCommand(dockerCli),
2828
newRemoveCommand(dockerCli),
29+
NewPruneCommand(dockerCli),
2930
)
3031
return cmd
3132
}

cli/command/network/prune.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package network
2+
3+
import (
4+
"fmt"
5+
6+
"golang.org/x/net/context"
7+
8+
"github.com/docker/docker/api/types"
9+
"github.com/docker/docker/cli"
10+
"github.com/docker/docker/cli/command"
11+
"github.com/spf13/cobra"
12+
)
13+
14+
type pruneOptions struct {
15+
force bool
16+
}
17+
18+
// NewPruneCommand returns a new cobra prune command for networks
19+
func NewPruneCommand(dockerCli *command.DockerCli) *cobra.Command {
20+
var opts pruneOptions
21+
22+
cmd := &cobra.Command{
23+
Use: "prune [OPTIONS]",
24+
Short: "Remove all unused networks",
25+
Args: cli.NoArgs,
26+
RunE: func(cmd *cobra.Command, args []string) error {
27+
output, err := runPrune(dockerCli, opts)
28+
if err != nil {
29+
return err
30+
}
31+
if output != "" {
32+
fmt.Fprintln(dockerCli.Out(), output)
33+
}
34+
return nil
35+
},
36+
}
37+
38+
flags := cmd.Flags()
39+
flags.BoolVarP(&opts.force, "force", "f", false, "Do not prompt for confirmation")
40+
41+
return cmd
42+
}
43+
44+
const warning = `WARNING! This will remove all networks not used by at least one container.
45+
Are you sure you want to continue?`
46+
47+
func runPrune(dockerCli *command.DockerCli, opts pruneOptions) (output string, err error) {
48+
if !opts.force && !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), warning) {
49+
return
50+
}
51+
52+
report, err := dockerCli.Client().NetworksPrune(context.Background(), types.NetworksPruneConfig{})
53+
if err != nil {
54+
return
55+
}
56+
57+
if len(report.NetworksDeleted) > 0 {
58+
output = "Deleted Networks:\n"
59+
for _, id := range report.NetworksDeleted {
60+
output += id + "\n"
61+
}
62+
}
63+
64+
return
65+
}
66+
67+
// RunPrune calls the Network Prune API
68+
// This returns the amount of space reclaimed and a detailed output string
69+
func RunPrune(dockerCli *command.DockerCli) (uint64, string, error) {
70+
output, err := runPrune(dockerCli, pruneOptions{force: true})
71+
return 0, output, err
72+
}

cli/command/prune/prune.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"github.com/docker/docker/cli/command"
55
"github.com/docker/docker/cli/command/container"
66
"github.com/docker/docker/cli/command/image"
7+
"github.com/docker/docker/cli/command/network"
78
"github.com/docker/docker/cli/command/volume"
89
"github.com/spf13/cobra"
910
)
@@ -23,6 +24,11 @@ func NewImagePruneCommand(dockerCli *command.DockerCli) *cobra.Command {
2324
return image.NewPruneCommand(dockerCli)
2425
}
2526

27+
// NewNetworkPruneCommand returns a cobra prune command for Networks
28+
func NewNetworkPruneCommand(dockerCli *command.DockerCli) *cobra.Command {
29+
return network.NewPruneCommand(dockerCli)
30+
}
31+
2632
// RunContainerPrune executes a prune command for containers
2733
func RunContainerPrune(dockerCli *command.DockerCli) (uint64, string, error) {
2834
return container.RunPrune(dockerCli)
@@ -37,3 +43,8 @@ func RunVolumePrune(dockerCli *command.DockerCli) (uint64, string, error) {
3743
func RunImagePrune(dockerCli *command.DockerCli, all bool) (uint64, string, error) {
3844
return image.RunPrune(dockerCli, all)
3945
}
46+
47+
// RunNetworkPrune executes a prune command for networks
48+
func RunNetworkPrune(dockerCli *command.DockerCli) (uint64, string, error) {
49+
return network.RunPrune(dockerCli)
50+
}

cli/command/system/prune.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const (
3939
warning = `WARNING! This will remove:
4040
- all stopped containers
4141
- all volumes not used by at least one container
42+
- all networks not used by at least one container
4243
%s
4344
Are you sure you want to continue?`
4445

@@ -64,13 +65,14 @@ func runPrune(dockerCli *command.DockerCli, opts pruneOptions) error {
6465
for _, pruneFn := range []func(dockerCli *command.DockerCli) (uint64, string, error){
6566
prune.RunContainerPrune,
6667
prune.RunVolumePrune,
68+
prune.RunNetworkPrune,
6769
} {
6870
spc, output, err := pruneFn(dockerCli)
6971
if err != nil {
7072
return err
7173
}
72-
if spc > 0 {
73-
spaceReclaimed += spc
74+
spaceReclaimed += spc
75+
if output != "" {
7476
fmt.Fprintln(dockerCli.Out(), output)
7577
}
7678
}

client/interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ type NetworkAPIClient interface {
9191
NetworkInspectWithRaw(ctx context.Context, networkID string) (types.NetworkResource, []byte, error)
9292
NetworkList(ctx context.Context, options types.NetworkListOptions) ([]types.NetworkResource, error)
9393
NetworkRemove(ctx context.Context, networkID string) error
94+
NetworksPrune(ctx context.Context, cfg types.NetworksPruneConfig) (types.NetworksPruneReport, error)
9495
}
9596

9697
// NodeAPIClient defines API client methods for the nodes

client/network_prune.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package client
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
7+
"github.com/docker/docker/api/types"
8+
"golang.org/x/net/context"
9+
)
10+
11+
// NetworksPrune requests the daemon to delete unused networks
12+
func (cli *Client) NetworksPrune(ctx context.Context, cfg types.NetworksPruneConfig) (types.NetworksPruneReport, error) {
13+
var report types.NetworksPruneReport
14+
15+
serverResp, err := cli.post(ctx, "/networks/prune", nil, cfg, nil)
16+
if err != nil {
17+
return report, err
18+
}
19+
defer ensureReaderClosed(serverResp)
20+
21+
if err := json.NewDecoder(serverResp.body).Decode(&report); err != nil {
22+
return report, fmt.Errorf("Error retrieving network prune report: %v", err)
23+
}
24+
25+
return report, nil
26+
}

0 commit comments

Comments
 (0)