github.com/git-ogawa/go-dbyml@v1.2.1/dbyml/image.go (about) 1 package dbyml 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "os" 8 "reflect" 9 10 "github.com/docker/docker/api/types" 11 "github.com/docker/docker/client" 12 "github.com/docker/docker/pkg/jsonmessage" 13 "github.com/moby/term" 14 ) 15 16 // ImageInfo defines docker image information. 17 type ImageInfo struct { 18 Basename string `yaml:"name"` // Image name 19 Tag string `yaml:"tag"` // Image tag 20 ImageName string `yaml:"image_name"` // Image name such as `go-dbyml:latest` 21 Context string `yaml:"path"` // Path to the directory where Dockerfile exists, is equivalent to build context 22 Dockerfile string `yaml:"dockerfile"` // Dockerfile filename 23 BuildArgs map[string]*string `yaml:"build_args"` // Build-args to be passed to image on build 24 Labels map[string]string `yaml:"label"` // Labels to be passed to image on build 25 DockerHost string `yaml:"docker_host"` // Docker host such as "unix:///var/run/docker.sock" 26 27 DockerfilePath string 28 Registry RegistryInfo 29 BuildInfo BuildInfo 30 FullName string 31 DockerClient *client.Client 32 } 33 34 // NewImageInfo creates a new ImageInfo struct with default values. 35 func NewImageInfo() *ImageInfo { 36 image := new(ImageInfo) 37 image.Tag = "latest" 38 image.Context = "." 39 image.Dockerfile = "Dockerfile" 40 image.DockerHost = "unix:///var/run/docker.sock" 41 image.DockerfilePath = image.Context + "/" + image.Dockerfile 42 image.Registry = *NewRegistryInfo() 43 image.BuildInfo = *NewBuildInfo() 44 return image 45 } 46 47 // SetProperties sets some properties when build an image. 48 func (image *ImageInfo) SetProperties() { 49 image.ImageName = image.Basename + ":" + image.Tag 50 image.DockerfilePath = image.Context + "/" + image.Dockerfile 51 image.SetDockerClient() 52 } 53 54 // SetDockerClient initializes docker api client for the specified host. 55 func (image *ImageInfo) SetDockerClient() { 56 image.DockerClient, _ = client.NewClientWithOpts( 57 client.WithHost(image.DockerHost), 58 client.WithAPIVersionNegotiation(), 59 ) 60 } 61 62 // ShowProperties shows the current settings related to image build. 63 func (image ImageInfo) ShowProperties() { 64 rv := reflect.ValueOf(image) 65 rt := rv.Type() 66 for i := 0; i < rt.NumField(); i++ { 67 field := rt.Field(i) 68 kind := field.Type.Kind() 69 value := rv.FieldByName(field.Name) 70 if kind == reflect.Map || kind == reflect.Slice { 71 showMapElement(field.Name, value.MapRange()) 72 } else if kind == reflect.String && value.Interface() != "" { 73 fmt.Printf("%-30v: %v\n", field.Name, value) 74 } 75 } 76 } 77 78 // Build runs image build. 79 func (image *ImageInfo) Build() error { 80 buf := GetBuildContext(image.Context) 81 tar := bytes.NewReader(buf.Bytes()) 82 ctx := context.Background() 83 84 options := types.ImageBuildOptions{ 85 NoCache: image.BuildInfo.NoCache, 86 Dockerfile: image.DockerfilePath, 87 Remove: true, 88 BuildArgs: image.BuildArgs, 89 Labels: image.Labels, 90 Target: image.BuildInfo.Target, 91 Tags: []string{image.ImageName}, 92 } 93 94 res, err := image.DockerClient.ImageBuild(ctx, tar, options) 95 if err != nil { 96 return err 97 } 98 defer res.Body.Close() 99 100 termFd, isTerm := term.GetFdInfo(os.Stderr) 101 err = jsonmessage.DisplayJSONMessagesStream(res.Body, os.Stderr, termFd, isTerm, nil) 102 return err 103 } 104 105 // SetFullImageName sets image name for pushing to a registry. 106 func (image *ImageInfo) SetFullImageName() { 107 if image.Registry.Project != "" { 108 image.FullName = image.Registry.Host + "/" + image.Registry.Project + "/" + image.ImageName 109 } else { 110 image.FullName = image.Registry.Host + "/" + image.ImageName 111 } 112 } 113 114 // Push runs image push to a registry. 115 func (image *ImageInfo) Push() error { 116 ctx := context.Background() 117 image.AddTag() 118 119 opts := types.ImagePushOptions{All: false, RegistryAuth: image.Registry.BasicAuth()} 120 121 res, err := image.DockerClient.ImagePush(ctx, image.FullName, opts) 122 if err != nil { 123 return err 124 } 125 defer res.Close() 126 127 termFd, isTerm := term.GetFdInfo(os.Stderr) 128 err = jsonmessage.DisplayJSONMessagesStream(res, os.Stderr, termFd, isTerm, nil) 129 return err 130 } 131 132 // AddTag adds a tag containing the registry name to a built image. 133 func (image *ImageInfo) AddTag() { 134 ctx := context.Background() 135 image.SetFullImageName() 136 137 err := image.DockerClient.ImageTag(ctx, image.ImageName, image.FullName) 138 if err != nil { 139 panic(err) 140 } 141 }