2019-05-31 00:26:34 +01:00
|
|
|
// Package docker builds docker images
|
|
|
|
package docker
|
|
|
|
|
|
|
|
import (
|
|
|
|
"archive/tar"
|
|
|
|
"bytes"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
|
2019-11-19 16:09:43 +00:00
|
|
|
docker "github.com/fsouza/go-dockerclient"
|
2020-02-23 16:45:20 +03:00
|
|
|
log "github.com/micro/go-micro/v2/logger"
|
2020-01-30 14:39:00 +03:00
|
|
|
"github.com/micro/go-micro/v2/runtime/local/build"
|
2019-05-31 00:26:34 +01:00
|
|
|
)
|
|
|
|
|
2019-11-19 16:09:43 +00:00
|
|
|
type Builder struct {
|
|
|
|
Options build.Options
|
2019-05-31 00:26:34 +01:00
|
|
|
Client *docker.Client
|
|
|
|
}
|
|
|
|
|
2019-11-19 16:09:43 +00:00
|
|
|
func (d *Builder) Build(s *build.Source) (*build.Package, error) {
|
2019-05-31 00:26:34 +01:00
|
|
|
image := filepath.Join(s.Repository.Path, s.Repository.Name)
|
|
|
|
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
tw := tar.NewWriter(buf)
|
|
|
|
defer tw.Close()
|
|
|
|
|
|
|
|
dockerFile := "Dockerfile"
|
|
|
|
|
|
|
|
// open docker file
|
|
|
|
f, err := os.Open(filepath.Join(s.Repository.Path, s.Repository.Name, dockerFile))
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// read docker file
|
|
|
|
by, err := ioutil.ReadAll(f)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
tarHeader := &tar.Header{
|
|
|
|
Name: dockerFile,
|
|
|
|
Size: int64(len(by)),
|
|
|
|
}
|
|
|
|
err = tw.WriteHeader(tarHeader)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
_, err = tw.Write(by)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
tr := bytes.NewReader(buf.Bytes())
|
|
|
|
|
|
|
|
err = d.Client.BuildImage(docker.BuildImageOptions{
|
|
|
|
Name: image,
|
|
|
|
Dockerfile: dockerFile,
|
|
|
|
InputStream: tr,
|
|
|
|
OutputStream: ioutil.Discard,
|
|
|
|
RmTmpContainer: true,
|
|
|
|
SuppressOutput: true,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2019-11-19 16:09:43 +00:00
|
|
|
return &build.Package{
|
2019-05-31 00:26:34 +01:00
|
|
|
Name: image,
|
|
|
|
Path: image,
|
|
|
|
Type: "docker",
|
|
|
|
Source: s,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2019-11-19 16:09:43 +00:00
|
|
|
func (d *Builder) Clean(b *build.Package) error {
|
2019-05-31 00:26:34 +01:00
|
|
|
image := filepath.Join(b.Path, b.Name)
|
|
|
|
return d.Client.RemoveImage(image)
|
|
|
|
}
|
|
|
|
|
2019-11-19 16:09:43 +00:00
|
|
|
func NewBuilder(opts ...build.Option) build.Builder {
|
|
|
|
options := build.Options{}
|
2019-05-31 00:26:34 +01:00
|
|
|
for _, o := range opts {
|
|
|
|
o(&options)
|
|
|
|
}
|
|
|
|
endpoint := "unix:///var/run/docker.sock"
|
|
|
|
client, err := docker.NewClient(endpoint)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
2019-11-19 16:09:43 +00:00
|
|
|
return &Builder{
|
2019-05-31 00:26:34 +01:00
|
|
|
Options: options,
|
|
|
|
Client: client,
|
|
|
|
}
|
|
|
|
}
|