Skip to content

Commit ea4dd0c

Browse files
committed
Add nginx virtual hosting example
1 parent 94ffc1c commit ea4dd0c

File tree

2 files changed

+95
-18
lines changed

2 files changed

+95
-18
lines changed

docker-gen.go

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,16 @@ import (
1313
"os/exec"
1414
"os/signal"
1515
"path/filepath"
16+
"reflect"
1617
"strings"
1718
"syscall"
1819
"text/template"
1920
)
2021

2122
var (
22-
watch bool
23-
notifyCmd string
23+
watch bool
24+
notifyCmd string
25+
onlyExposed bool
2426
)
2527

2628
type Event struct {
@@ -37,19 +39,70 @@ type RuntimeContainer struct {
3739
ID string
3840
Addresses []Address
3941
Image string
42+
Env map[string]string
43+
}
44+
45+
func deepGet(item interface{}, path string) interface{} {
46+
if path == "" {
47+
return item
48+
}
49+
50+
parts := strings.Split(path, ".")
51+
itemValue := reflect.ValueOf(item)
52+
53+
if len(parts) > 0 {
54+
switch itemValue.Kind() {
55+
case reflect.Struct:
56+
fieldValue := itemValue.FieldByName(parts[0])
57+
if fieldValue.IsValid() {
58+
return deepGet(fieldValue.Interface(), strings.Join(parts[1:], "."))
59+
}
60+
case reflect.Map:
61+
mapValue := itemValue.MapIndex(reflect.ValueOf(parts[0]))
62+
if mapValue.IsValid() {
63+
return deepGet(mapValue.Interface(), strings.Join(parts[1:], "."))
64+
}
65+
default:
66+
fmt.Printf("can't group by %s", path)
67+
}
68+
return nil
69+
}
70+
71+
return itemValue.Interface()
72+
}
73+
74+
func groupBy(entries []*RuntimeContainer, key string) map[string][]*RuntimeContainer {
75+
groups := make(map[string][]*RuntimeContainer)
76+
for _, v := range entries {
77+
value := deepGet(*v, key)
78+
if value != nil {
79+
groups[value.(string)] = append(groups[value.(string)], v)
80+
}
81+
}
82+
return groups
83+
}
84+
85+
func contains(a map[string]string, b string) bool {
86+
if _, ok := a[b]; ok {
87+
return true
88+
}
89+
return false
4090
}
4191

4292
func usage() {
4393
println("Usage: docker-gen [-watch=false] [-notify=\"restart xyz\"] <template> [<dest>]")
4494
}
4595

4696
func generateFile(templatePath string, containers []*RuntimeContainer) {
47-
48-
tmpl, err := template.ParseFiles(templatePath)
97+
tmpl, err := template.New(filepath.Base(templatePath)).Funcs(template.FuncMap{
98+
"contains": contains,
99+
"groupBy": groupBy,
100+
}).ParseFiles(templatePath)
49101
if err != nil {
50102
panic(err)
51103
}
52104

105+
tmpl = tmpl
53106
dest := os.Stdout
54107
if flag.NArg() == 2 {
55108
dest, err = os.Create(flag.Arg(1))
@@ -149,6 +202,7 @@ func generateFromContainers(client *docker.Client) {
149202
ID: container.ID,
150203
Image: container.Config.Image,
151204
Addresses: []Address{},
205+
Env: make(map[string]string),
152206
}
153207
for k, _ := range container.NetworkSettings.Ports {
154208
runtimeContainer.Addresses = append(runtimeContainer.Addresses,
@@ -157,7 +211,21 @@ func generateFromContainers(client *docker.Client) {
157211
Port: k.Port(),
158212
})
159213
}
160-
containers = append(containers, runtimeContainer)
214+
215+
for _, entry := range container.Config.Env {
216+
parts := strings.Split(entry, "=")
217+
runtimeContainer.Env[parts[0]] = parts[1]
218+
}
219+
220+
if !onlyExposed {
221+
containers = append(containers, runtimeContainer)
222+
continue
223+
}
224+
225+
if onlyExposed && len(runtimeContainer.Addresses) > 0 {
226+
containers = append(containers, runtimeContainer)
227+
}
228+
161229
}
162230

163231
generateFile(flag.Arg(0), containers)
@@ -179,8 +247,8 @@ func runNotifyCmd() {
179247
}
180248

181249
func main() {
182-
183250
flag.BoolVar(&watch, "watch", false, "watch for container changes")
251+
flag.BoolVar(&onlyExposed, "only-exposed", false, "only include containers with exposed ports")
184252
flag.StringVar(&notifyCmd, "notify", "", "run command after template is regenerated")
185253
flag.Parse()
186254

@@ -205,9 +273,11 @@ func main() {
205273
eventChan := getEvents()
206274
for {
207275
event := <-eventChan
208-
if event.Status == "start" || event.Status == "stop" {
276+
if event.Status == "start" || event.Status == "stop" || event.Status == "die" {
209277
generateFromContainers(client)
210278
runNotifyCmd()
279+
} else {
280+
println(event.Status)
211281
}
212282
}
213283

templates/nginx.tmpl

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,28 @@
1-
upstream docker {
2-
{{range $key, $value := .}}
3-
{}
4-
{{with $address := index $value.Addresses 0 }}
5-
server {{ $address.IP}}:{{ $address.Port}};
6-
{{end}}
7-
{{end}}
1+
{{ range $host, $containers := groupBy $ "Env.VIRTUAL_HOST" }}
2+
upstream {{ $host }} {
3+
4+
{{ range $index, $value := $containers }}
5+
{{ if (gt (len $value.Addresses) 0) }}
6+
{{ with $address := index $value.Addresses 0 }}
7+
server {{ $address.IP }}:{{ $address.Port }};
8+
{{ end }}
9+
{{ end }}
10+
{{ end }}
11+
812
}
913

1014
server {
11-
root /usr/share/nginx/www;
12-
index index.html index.htm;
15+
#ssl_certificate /etc/nginx/certs/demo.pem;
16+
#ssl_certificate_key /etc/nginx/certs/demo.key;
17+
18+
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
1319

14-
server_name localhost;
20+
server_name {{ $host }};
1521

1622
location / {
17-
proxy_pass http://docker;
23+
proxy_pass http://{{ $host }};
1824
include /etc/nginx/proxy_params;
1925
}
2026
}
2127

28+
{{ end }}

0 commit comments

Comments
 (0)