fix: clean up local build images immediately after an image is released
In some cases, we might hold onto intermediate images until the next deploy. While these images are generally part of newer images - and are therefore cleaned up when the child images are no longer in use - they cruft up the 'docker image ls' output, causing some folks to believe Dokku is not cleaning up images. Refs #6272
This commit is contained in:
@@ -3,7 +3,6 @@ package builder
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path"
|
||||
@@ -12,30 +11,6 @@ import (
|
||||
"github.com/dokku/dokku/plugins/common"
|
||||
)
|
||||
|
||||
func listImagesByAppLabel(appName string) ([]string, error) {
|
||||
command := []string{
|
||||
common.DockerBin(),
|
||||
"image",
|
||||
"ls",
|
||||
"--quiet",
|
||||
"--filter",
|
||||
fmt.Sprintf("label=com.dokku.app-name=%v", appName),
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
listCmd := common.NewShellCmd(strings.Join(command, " "))
|
||||
listCmd.ShowOutput = false
|
||||
listCmd.Command.Stderr = &stderr
|
||||
b, err := listCmd.Output()
|
||||
|
||||
if err != nil {
|
||||
return []string{}, errors.New(strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
output := strings.Split(strings.TrimSpace(string(b[:])), "\n")
|
||||
return output, nil
|
||||
}
|
||||
|
||||
func listImagesByImageRepo(imageRepo string) ([]string, error) {
|
||||
command := []string{
|
||||
common.DockerBin(),
|
||||
|
||||
@@ -50,6 +50,10 @@ func main() {
|
||||
case "post-delete":
|
||||
appName := flag.Arg(0)
|
||||
err = builder.TriggerPostDelete(appName)
|
||||
case "post-release-builder":
|
||||
builderType := flag.Arg(0)
|
||||
appName := flag.Arg(1)
|
||||
err = builder.TriggerPostReleaseBuilder(builderType, appName)
|
||||
case "report":
|
||||
appName := flag.Arg(0)
|
||||
err = builder.ReportSingleApp(appName, "", "")
|
||||
|
||||
@@ -133,7 +133,9 @@ func TriggerPostDelete(appName string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
imagesByAppLabel, err := listImagesByAppLabel(appName)
|
||||
imagesByAppLabel, err := common.DockerFilterImages([]string{
|
||||
fmt.Sprintf("label=com.dokku.app-name=%s", appName),
|
||||
})
|
||||
if err != nil {
|
||||
common.LogWarn(err.Error())
|
||||
}
|
||||
@@ -149,3 +151,17 @@ func TriggerPostDelete(appName string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// TriggerPostReleaseBuilder deletes unused build images
|
||||
func TriggerPostReleaseBuilder(builderType string, appName string) error {
|
||||
images, _ := common.DockerFilterImages([]string{
|
||||
"label=com.dokku.image-stage=build",
|
||||
fmt.Sprintf("label=com.dokku.app-name=%s", appName),
|
||||
})
|
||||
|
||||
if err := common.RemoveImages(images); err != nil {
|
||||
common.LogWarn(err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -300,17 +300,58 @@ func IsImageHerokuishBased(image string, appName string) bool {
|
||||
|
||||
// ListDanglingImages lists all dangling image ids for a given app
|
||||
func ListDanglingImages(appName string) ([]string, error) {
|
||||
filters := []string{"dangling=true"}
|
||||
if appName != "" {
|
||||
filters = append(filters, []string{fmt.Sprintf("label=com.dokku.app-name=%v", appName)}...)
|
||||
}
|
||||
return DockerFilterImages(filters)
|
||||
}
|
||||
|
||||
// RemoveImages removes images by ID
|
||||
func RemoveImages(imageIDs []string) error {
|
||||
if len(imageIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
command := []string{
|
||||
DockerBin(),
|
||||
"image",
|
||||
"ls",
|
||||
"--quiet",
|
||||
"--filter",
|
||||
"dangling=true",
|
||||
"rm",
|
||||
}
|
||||
|
||||
if appName != "" {
|
||||
command = append(command, []string{"--filter", fmt.Sprintf("label=com.dokku.app-name=%v", appName)}...)
|
||||
command = append(command, imageIDs...)
|
||||
|
||||
var stderr bytes.Buffer
|
||||
rmCmd := NewShellCmd(strings.Join(command, " "))
|
||||
rmCmd.ShowOutput = false
|
||||
rmCmd.Command.Stderr = &stderr
|
||||
rmCmd.Execute()
|
||||
if _, err := rmCmd.Output(); err != nil {
|
||||
return errors.New(strings.TrimSpace(stderr.String()))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// VerifyImage returns true if docker image exists in local repo
|
||||
func VerifyImage(image string) bool {
|
||||
imageCmd := NewShellCmd(strings.Join([]string{DockerBin(), "image", "inspect", image}, " "))
|
||||
imageCmd.ShowOutput = false
|
||||
return imageCmd.Execute()
|
||||
}
|
||||
|
||||
// DockerFilterContainers returns a slice of container IDs based on the passed in filters
|
||||
func DockerFilterContainers(filters []string) ([]string, error) {
|
||||
command := []string{
|
||||
DockerBin(),
|
||||
"container",
|
||||
"ls",
|
||||
"--quiet",
|
||||
"--all",
|
||||
}
|
||||
|
||||
for _, filter := range filters {
|
||||
command = append(command, "--filter", filter)
|
||||
}
|
||||
|
||||
var stderr bytes.Buffer
|
||||
@@ -327,39 +368,11 @@ func ListDanglingImages(appName string) ([]string, error) {
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// RemoveImages removes images by ID
|
||||
func RemoveImages(imageIDs []string) {
|
||||
if len(imageIDs) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// DockerFilterImages returns a slice of image IDs based on the passed in filters
|
||||
func DockerFilterImages(filters []string) ([]string, error) {
|
||||
command := []string{
|
||||
DockerBin(),
|
||||
"image",
|
||||
"rm",
|
||||
}
|
||||
|
||||
command = append(command, imageIDs...)
|
||||
|
||||
var stderr bytes.Buffer
|
||||
rmCmd := NewShellCmd(strings.Join(command, " "))
|
||||
rmCmd.ShowOutput = false
|
||||
rmCmd.Command.Stderr = &stderr
|
||||
rmCmd.Execute()
|
||||
}
|
||||
|
||||
// VerifyImage returns true if docker image exists in local repo
|
||||
func VerifyImage(image string) bool {
|
||||
imageCmd := NewShellCmd(strings.Join([]string{DockerBin(), "image", "inspect", image}, " "))
|
||||
imageCmd.ShowOutput = false
|
||||
return imageCmd.Execute()
|
||||
}
|
||||
|
||||
// DockerFilterContainers returns a slice of container IDs based on the passed in filters
|
||||
func DockerFilterContainers(filters []string) ([]string, error) {
|
||||
command := []string{
|
||||
DockerBin(),
|
||||
"container",
|
||||
"ls",
|
||||
"--quiet",
|
||||
"--all",
|
||||
|
||||
Reference in New Issue
Block a user