add docker network prune

`docker network prune` prunes unused networks, including overlay ones.
`docker system prune` also prunes unused networks.

Signed-off-by: Akihiro Suda <suda.akihiro@lab.ntt.co.jp>
Upstream-commit: 7e24c16086a9a4f38e241e51837f2be4877c04a6
Component: engine
This commit is contained in:
Akihiro Suda
2016-10-18 04:36:52 +00:00
parent db3c1eebdd
commit 4fb550ce0f
29 changed files with 399 additions and 3 deletions

View File

@ -0,0 +1,12 @@
package daemon
import (
apitypes "github.com/docker/docker/api/types"
)
// Cluster is the interface for github.com/docker/docker/daemon/cluster.(*Cluster).
type Cluster interface {
GetNetwork(input string) (apitypes.NetworkResource, error)
GetNetworks() ([]apitypes.NetworkResource, error)
RemoveNetwork(input string) error
}

View File

@ -102,6 +102,7 @@ type Daemon struct {
containerdRemote libcontainerd.Remote
defaultIsolation containertypes.Isolation // Default isolation mode on Windows
clusterProvider cluster.Provider
cluster Cluster
}
// HasExperimental returns whether the experimental features of the daemon are enabled or not
@ -1234,3 +1235,13 @@ func copyBlkioEntry(entries []*containerd.BlkioStatsEntry) []types.BlkioStatEntr
}
return out
}
// GetCluster returns the cluster
func (daemon *Daemon) GetCluster() Cluster {
return daemon.cluster
}
// SetCluster sets the cluster
func (daemon *Daemon) SetCluster(cluster Cluster) {
daemon.cluster = cluster
}

View File

@ -1,6 +1,8 @@
package daemon
import (
"regexp"
"github.com/Sirupsen/logrus"
"github.com/docker/distribution/digest"
"github.com/docker/docker/api/types"
@ -8,7 +10,9 @@ import (
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/directory"
"github.com/docker/docker/reference"
"github.com/docker/docker/runconfig"
"github.com/docker/docker/volume"
"github.com/docker/libnetwork"
)
// ContainersPrune removes unused containers
@ -150,3 +154,72 @@ func (daemon *Daemon) ImagesPrune(config *types.ImagesPruneConfig) (*types.Image
return rep, nil
}
// localNetworksPrune removes unused local networks
func (daemon *Daemon) localNetworksPrune(config *types.NetworksPruneConfig) (*types.NetworksPruneReport, error) {
rep := &types.NetworksPruneReport{}
var err error
// When the function returns true, the walk will stop.
l := func(nw libnetwork.Network) bool {
nwName := nw.Name()
predefined := runconfig.IsPreDefinedNetwork(nwName)
if !predefined && len(nw.Endpoints()) == 0 {
if err = daemon.DeleteNetwork(nw.ID()); err != nil {
logrus.Warnf("could not remove network %s: %v", nwName, err)
return false
}
rep.NetworksDeleted = append(rep.NetworksDeleted, nwName)
}
return false
}
daemon.netController.WalkNetworks(l)
return rep, err
}
// clusterNetworksPrune removes unused cluster networks
func (daemon *Daemon) clusterNetworksPrune(config *types.NetworksPruneConfig) (*types.NetworksPruneReport, error) {
rep := &types.NetworksPruneReport{}
cluster := daemon.GetCluster()
networks, err := cluster.GetNetworks()
if err != nil {
return rep, err
}
networkIsInUse := regexp.MustCompile(`network ([[:alnum:]]+) is in use`)
for _, nw := range networks {
if nw.Name == "ingress" {
continue
}
// https://github.com/docker/docker/issues/24186
// `docker network inspect` unfortunately displays ONLY those containers that are local to that node.
// So we try to remove it anyway and check the error
err = cluster.RemoveNetwork(nw.ID)
if err != nil {
// we can safely ignore the "network .. is in use" error
match := networkIsInUse.FindStringSubmatch(err.Error())
if len(match) != 2 || match[1] != nw.ID {
logrus.Warnf("could not remove network %s: %v", nw.Name, err)
}
continue
}
rep.NetworksDeleted = append(rep.NetworksDeleted, nw.Name)
}
return rep, nil
}
// NetworksPrune removes unused networks
func (daemon *Daemon) NetworksPrune(config *types.NetworksPruneConfig) (*types.NetworksPruneReport, error) {
rep := &types.NetworksPruneReport{}
clusterRep, err := daemon.clusterNetworksPrune(config)
if err != nil {
logrus.Warnf("could not remove cluster networks: %v", err)
} else {
rep.NetworksDeleted = append(rep.NetworksDeleted, clusterRep.NetworksDeleted...)
}
localRep, err := daemon.localNetworksPrune(config)
if err != nil {
logrus.Warnf("could not remove local networks: %v", err)
} else {
rep.NetworksDeleted = append(rep.NetworksDeleted, localRep.NetworksDeleted...)
}
return rep, err
}