github.com/sergiusens/goreleaser@v0.34.3-0.20171009111917-ae6f7c157c5c/pipeline/docker/docker.go (about) 1 // Package docker provides a Pipe that creates and pushes a Docker image 2 package docker 3 4 import ( 5 "fmt" 6 "os" 7 "os/exec" 8 "path/filepath" 9 10 "github.com/goreleaser/goreleaser/config" 11 "github.com/goreleaser/goreleaser/context" 12 "github.com/goreleaser/goreleaser/pipeline" 13 14 "github.com/apex/log" 15 16 "github.com/pkg/errors" 17 ) 18 19 // ErrNoDocker is shown when docker cannot be found in $PATH 20 var ErrNoDocker = errors.New("docker not present in $PATH") 21 22 // Pipe for docker 23 type Pipe struct{} 24 25 // Description of the pipe 26 func (Pipe) Description() string { 27 return "Creating Docker images" 28 } 29 30 // Run the pipe 31 func (Pipe) Run(ctx *context.Context) error { 32 if len(ctx.Config.Dockers) == 0 || ctx.Config.Dockers[0].Image == "" { 33 return pipeline.Skip("docker section is not configured") 34 } 35 _, err := exec.LookPath("docker") 36 if err != nil { 37 return ErrNoDocker 38 } 39 return doRun(ctx) 40 } 41 42 func doRun(ctx *context.Context) error { 43 for _, docker := range ctx.Config.Dockers { 44 var imagePlatform = docker.Goos + docker.Goarch + docker.Goarm 45 for platform, groups := range ctx.Binaries { 46 if platform != imagePlatform { 47 continue 48 } 49 for folder, binaries := range groups { 50 for _, binary := range binaries { 51 if binary.Name != docker.Binary { 52 continue 53 } 54 var err = process(ctx, folder, docker, binary) 55 if err != nil && !pipeline.IsSkip(err) { 56 return err 57 } 58 } 59 } 60 } 61 } 62 return nil 63 } 64 65 func process(ctx *context.Context, folder string, docker config.Docker, binary context.Binary) error { 66 var root = filepath.Join(ctx.Config.Dist, folder) 67 var dockerfile = filepath.Join(root, filepath.Base(docker.Dockerfile)) 68 var image = fmt.Sprintf("%s:%s", docker.Image, ctx.Version) 69 var latest = fmt.Sprintf("%s:latest", docker.Image) 70 71 if err := os.Link(docker.Dockerfile, dockerfile); err != nil { 72 return errors.Wrap(err, "failed to link dockerfile") 73 } 74 for _, file := range docker.Files { 75 if err := os.Link(file, filepath.Join(root, filepath.Base(file))); err != nil { 76 return errors.Wrapf(err, "failed to link extra file '%s'", file) 77 } 78 } 79 if err := dockerBuild(root, dockerfile, image); err != nil { 80 return err 81 } 82 if docker.Latest { 83 if err := dockerTag(image, latest); err != nil { 84 return err 85 } 86 } 87 88 return publish(ctx, docker, image, latest) 89 } 90 91 func publish(ctx *context.Context, docker config.Docker, image, latest string) error { 92 // TODO: improve this so it can log it to stdout 93 if !ctx.Publish { 94 return pipeline.Skip("--skip-publish is set") 95 } 96 if ctx.Config.Release.Draft { 97 return pipeline.Skip("release is marked as draft") 98 } 99 if err := dockerPush(image); err != nil { 100 return err 101 } 102 ctx.AddDocker(image) 103 if !docker.Latest { 104 return nil 105 } 106 if err := dockerTag(image, latest); err != nil { 107 return err 108 } 109 return dockerPush(latest) 110 } 111 112 func dockerBuild(root, dockerfile, image string) error { 113 log.WithField("image", image).Info("building docker image") 114 var cmd = exec.Command("docker", "build", "-f", dockerfile, "-t", image, root) 115 log.WithField("cmd", cmd).Debug("executing") 116 out, err := cmd.CombinedOutput() 117 if err != nil { 118 return errors.Wrapf(err, "failed to build docker image: \n%s", string(out)) 119 } 120 log.Debugf("docker build output: \n%s", string(out)) 121 return nil 122 } 123 124 func dockerTag(image, tag string) error { 125 log.WithField("image", image).WithField("tag", tag).Info("tagging docker image") 126 var cmd = exec.Command("docker", "tag", image, tag) 127 log.WithField("cmd", cmd).Debug("executing") 128 out, err := cmd.CombinedOutput() 129 if err != nil { 130 return errors.Wrapf(err, "failed to tag docker image: \n%s", string(out)) 131 } 132 log.Debugf("docker tag output: \n%s", string(out)) 133 return nil 134 } 135 136 func dockerPush(image string) error { 137 log.WithField("image", image).Info("pushing docker image") 138 var cmd = exec.Command("docker", "push", image) 139 log.WithField("cmd", cmd).Debug("executing") 140 out, err := cmd.CombinedOutput() 141 if err != nil { 142 return errors.Wrapf(err, "failed to push docker image: \n%s", string(out)) 143 } 144 log.Debugf("docker push output: \n%s", string(out)) 145 return nil 146 }