forked from dahernan/godockerize
-
Notifications
You must be signed in to change notification settings - Fork 0
/
godockerize.go
144 lines (115 loc) · 2.86 KB
/
godockerize.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package main
import (
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"text/template"
)
const (
buildTemplate = `
FROM google/golang:stable
# Godep for vendoring
RUN go get github.com/tools/godep
# Recompile the standard library without CGO
RUN CGO_ENABLED=0 go install -a std
MAINTAINER [email protected]
ENV APP_DIR $GOPATH{{.Appdir}}
# Set the entrypoint
ENTRYPOINT ["/opt/app/{{.Entrypoint}}"]
ADD . $APP_DIR
# Compile the binary and statically link
RUN mkdir /opt/app
RUN cd $APP_DIR && godep restore
RUN cd $APP_DIR && CGO_ENABLED=0 go build -o /opt/app/{{.Entrypoint}} -ldflags '-d -w -s'
EXPOSE {{.Expose}}
`
buildScratchTemplate = `
FROM scratch
ENTRYPOINT ["/{{.Entrypoint}}"]
# Add the binary
ADD {{.Entrypoint}} /
EXPOSE {{.Expose}}
`
)
type DockerInfo struct {
Appdir string
Entrypoint string
Expose string
}
func main() {
expose := flag.String("expose", "3000", "Port to expose in docker")
fromTheScratch := flag.Bool("scratch", false, "Build the from the base image scratch")
flag.Parse()
goPath := os.Getenv("GOPATH")
dir, err := filepath.Abs(".")
if err != nil {
log.Fatal(err)
}
appdir := strings.Replace(dir, goPath, "", 1)
_, entrypoint := path.Split(appdir)
dockerInfo := DockerInfo{
Appdir: appdir,
Entrypoint: entrypoint,
Expose: *expose,
}
if *fromTheScratch {
buildForLinux(dockerInfo)
generateDockerfileFromScratch(dockerInfo)
} else {
generateDockerfile(dockerInfo)
}
}
func generateDockerfile(dockerInfo DockerInfo) {
t := template.Must(template.New("buildTemplate").Parse(buildTemplate))
f, err := os.Create("Dockerfile")
if err != nil {
log.Fatal("Error wrinting Dockerfile %v", err.Error())
return
}
defer f.Close()
t.Execute(f, dockerInfo)
fmt.Printf("Dockerfile generated, you can build the image with: \n")
fmt.Printf("$ docker build -t %s .\n", dockerInfo.Entrypoint)
}
func generateDockerfileFromScratch(dockerInfo DockerInfo) {
t := template.Must(template.New("buildScratchTemplate").Parse(buildScratchTemplate))
f, err := os.Create("Dockerfile")
if err != nil {
log.Fatal("Error writing Dockerfile %v", err.Error())
return
}
defer f.Close()
t.Execute(f, dockerInfo)
fmt.Printf("Dockerfile from the scratch generated, you can build the image with: \n")
fmt.Printf("$ docker build -t %s .\n", dockerInfo.Entrypoint)
}
func buildForLinux(dockerInfo DockerInfo) {
os.Setenv("GOOS", "linux")
os.Setenv("CGO_ENABLED", "0")
cmd := exec.Command("go", "build", "-o", dockerInfo.Entrypoint)
stderr, err := cmd.StderrPipe()
if err != nil {
log.Fatalf("%s", err)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatalf("%s", err)
}
err = cmd.Start()
if err != nil {
log.Fatalf("%s", err)
}
io.Copy(os.Stdout, stdout)
errBuf, _ := ioutil.ReadAll(stderr)
err = cmd.Wait()
if err != nil {
log.Fatalf("%s", errBuf)
}
}