This repository has been archived by the owner on Nov 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.go
executable file
·117 lines (104 loc) · 3.6 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package main
// nolint[gocyclo]
import (
"flag"
"fmt"
"os"
"os/signal"
"strings"
"sync"
"syscall"
"time"
"github.com/fatih/color"
docker "github.com/fsouza/go-dockerclient"
)
type options struct {
dockerHost string
sweepInterval int
removeImages bool
removeHealthyContainersExited bool
}
var opts options
func init() {
flag.StringVar(&opts.dockerHost, "docker-host", "unix:///var/run/docker.sock", "-docker-host=unix:///var/run/docker.sock")
flag.IntVar(&opts.sweepInterval, "sweep-interval", 60, "-sweep-interval=60")
flag.BoolVar(&opts.removeImages, "remove-images", true, "-remove-images=true")
flag.BoolVar(&opts.removeHealthyContainersExited, "remove-healthy-containers-exited", true, "-remove-healthy-containers-exited=true")
}
func main() {
flag.Parse()
dc, err := docker.NewClient(opts.dockerHost)
if err != nil {
panic(err)
}
s := make(chan os.Signal, 1)
signal.Notify(s, syscall.SIGTERM, syscall.SIGINT)
fmt.Fprintf(os.Stdout, "gcd: [info]: (Time: %v)\n", time.Now().String())
fmt.Fprintf(os.Stdout, "gcd: [info]: (Docker Host: %v)\n", opts.dockerHost)
fmt.Fprintf(os.Stdout, "gcd: [info]: (Sweep Interval: %vs)\n", opts.sweepInterval)
fmt.Fprintf(os.Stdout, "gcd: [info]: (Remove Images: %v)\n", opts.removeImages)
fmt.Fprintf(os.Stdout, "gcd: [info]: (Remove Healthy Containers Exited: %v)\n", opts.removeHealthyContainersExited)
for {
select {
case <-s:
os.Exit(0)
case <-time.Tick(time.Duration(opts.sweepInterval) * time.Second):
run(dc, opts)
}
}
}
func run(dc *docker.Client, opts options) {
fmt.Fprintf(os.Stdout, "\ngcd: [info]: (Time: %v)\n", time.Now().String())
containers, err := dc.ListContainers(docker.ListContainersOptions{
All: true,
})
if err != nil {
fmt.Fprint(os.Stderr, color.HiRedString(err.Error()))
}
var wgContainers sync.WaitGroup
for _, container := range containers {
wgContainers.Add(1)
go func(container docker.APIContainers) {
defer wgContainers.Done()
exitCodeFromContainer := "(-)"
if splitedStatus := strings.Split(container.Status, " "); len(splitedStatus) > 1 {
exitCodeFromContainer = splitedStatus[1]
}
if container.State != "running" {
if (opts.removeHealthyContainersExited && exitCodeFromContainer == "(0)") || exitCodeFromContainer != "(0)" {
fmt.Fprintf(os.Stdout, "gcd: [trying remove container]: (Id: %v, Labels: %v)\n", container.ID, container.Labels)
if err := dc.RemoveContainer(docker.RemoveContainerOptions{
ID: container.ID,
RemoveVolumes: true,
Force: true,
}); err != nil {
fmt.Fprintf(os.Stderr, "gcd: [error]: (when try remove container, reason: %v)\n", color.HiRedString(err.Error()))
} else {
fmt.Fprintf(os.Stdout, "gcd: [removed container]: (Id: %v, Labels: %v)\n", container.ID, container.Labels)
}
}
}
}(container)
}
wgContainers.Wait()
if opts.removeImages {
var wgImages sync.WaitGroup
images, err := dc.ListImages(docker.ListImagesOptions{})
if err != nil {
fmt.Fprint(os.Stderr, color.HiRedString(err.Error()))
}
for _, image := range images {
wgImages.Add(1)
go func(image docker.APIImages) {
defer wgImages.Done()
fmt.Fprintf(os.Stdout, "gcd: [trying remove image]: (Id: %v, Tags: %v)\n", image.ID, image.RepoTags)
if err := dc.RemoveImage(image.ID); err != nil {
fmt.Fprintf(os.Stderr, "gcd: [error]: (when try remove image, reason: %v)\n", color.HiRedString(err.Error()))
} else {
fmt.Fprintf(os.Stdout, "gcd: [removed image]: (Id: %v, Tags: %v)\n", image.ID, image.RepoTags)
}
}(image)
}
wgImages.Wait()
}
}