luet/vendor/github.com/mudler/docker-companion/api/squash.go
Ettore Di Giacinto 420186b7db
Switch to go mod
2019-11-10 18:05:28 +01:00

93 lines
2.0 KiB
Go

package api
import (
"fmt"
"io"
"os"
"os/signal"
"strings"
"syscall"
"github.com/fsouza/go-dockerclient"
jww "github.com/spf13/jwalterweatherman"
)
// Squash Squashes a docker image into another one
func Squash(client *docker.Client, image string, toImage string) error {
var err error
var Tag = "latest"
r, w := io.Pipe()
Imageparts := strings.Split(toImage, ":")
if len(Imageparts) == 2 {
Tag = Imageparts[1]
toImage = Imageparts[0]
}
jww.INFO.Println("Creating container")
container, err := client.CreateContainer(docker.CreateContainerOptions{
Config: &docker.Config{
Image: image,
Cmd: []string{"true"},
},
})
if err != nil {
jww.FATAL.Fatalln("Couldn't create container, sorry", err)
}
defer func(*docker.Container) {
client.RemoveContainer(docker.RemoveContainerOptions{
ID: container.ID,
Force: true,
})
}(container)
signalchan := make(chan os.Signal, 1)
signal.Notify(signalchan,
syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGQUIT)
go func() {
for {
s := <-signalchan
switch s {
case syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT:
jww.WARN.Println("SIGTERM/SIGINT/SIGQUIT detected, removing pending containers/image")
client.RemoveContainer(docker.RemoveContainerOptions{
ID: container.ID,
Force: true,
})
client.RemoveImage(toImage)
}
}
}()
// writing without a reader will deadlock so write in a goroutine
go func() {
// it is important to close the writer or reading from the other end of the
// pipe will never finish
defer w.Close()
err = client.ExportContainer(docker.ExportContainerOptions{ID: container.ID, OutputStream: w})
if err != nil {
jww.FATAL.Fatalln("Couldn't export container, sorry", err)
}
}()
jww.INFO.Println("Importing to", toImage)
err = client.ImportImage(docker.ImportImageOptions{Repository: toImage,
Source: "-",
InputStream: r,
Tag: Tag,
})
if err != nil {
return fmt.Errorf("Could not import docker image")
}
return nil
}