docker override port, host, backend
reuse loadbalancer
This commit is contained in:
parent
0af872e661
commit
730fbfe9c5
5 changed files with 76 additions and 45 deletions
46
docker.go
46
docker.go
|
@ -5,8 +5,31 @@ import (
|
|||
"bytes"
|
||||
"github.com/BurntSushi/toml"
|
||||
"log"
|
||||
"text/template"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var DockerFuncMap = template.FuncMap{
|
||||
"getBackend": func(container docker.Container) string {
|
||||
for key, value := range container.Config.Labels {
|
||||
if (key == "træfik.backend") {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return container.Config.Hostname
|
||||
},
|
||||
"getPort": func(container docker.Container) string {
|
||||
for key, value := range container.Config.Labels {
|
||||
if (key == "træfik.port") {
|
||||
return value
|
||||
}
|
||||
}
|
||||
for key, _ := range container.NetworkSettings.Ports {
|
||||
return key.Port()
|
||||
}
|
||||
return ""
|
||||
},
|
||||
"getHost": getHost,
|
||||
}
|
||||
type DockerProvider struct {
|
||||
Watch bool
|
||||
Endpoint string
|
||||
|
@ -38,16 +61,22 @@ func (provider *DockerProvider) loadDockerConfig() *Configuration {
|
|||
configuration := new(Configuration)
|
||||
containerList, _ := provider.dockerClient.ListContainers(docker.ListContainersOptions{})
|
||||
containersInspected := []docker.Container{}
|
||||
hosts := map[string][]docker.Container{}
|
||||
for _, container := range containerList {
|
||||
containerInspected, _ := provider.dockerClient.InspectContainer(container.ID)
|
||||
containersInspected = append(containersInspected, *containerInspected)
|
||||
hosts[getHost(*containerInspected)] = append(hosts[getHost(*containerInspected)], *containerInspected)
|
||||
}
|
||||
containers := struct {
|
||||
|
||||
templateObjects := struct {
|
||||
Containers []docker.Container
|
||||
Hosts map[string][]docker.Container
|
||||
}{
|
||||
containersInspected,
|
||||
hosts,
|
||||
}
|
||||
tmpl, err := gtf.New("docker.tmpl").ParseFiles("docker.tmpl")
|
||||
gtf.Inject(DockerFuncMap)
|
||||
tmpl, err := template.New("docker.tmpl").Funcs(DockerFuncMap).ParseFiles("docker.tmpl")
|
||||
if err != nil {
|
||||
log.Println("Error reading file:", err)
|
||||
return nil
|
||||
|
@ -55,7 +84,7 @@ func (provider *DockerProvider) loadDockerConfig() *Configuration {
|
|||
|
||||
var buffer bytes.Buffer
|
||||
|
||||
err = tmpl.Execute(&buffer, containers)
|
||||
err = tmpl.Execute(&buffer, templateObjects)
|
||||
if err != nil {
|
||||
log.Println("Error with docker template:", err)
|
||||
return nil
|
||||
|
@ -66,4 +95,13 @@ func (provider *DockerProvider) loadDockerConfig() *Configuration {
|
|||
return nil
|
||||
}
|
||||
return configuration
|
||||
}
|
||||
|
||||
func getHost(container docker.Container) string {
|
||||
for key, value := range container.Config.Labels {
|
||||
if (key == "træfik.host") {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return strings.TrimPrefix(container.Name, "/")
|
||||
}
|
29
docker.tmpl
29
docker.tmpl
|
@ -1,25 +1,12 @@
|
|||
[backends]{{range .Containers}}
|
||||
[backends.backend-{{.Config.Hostname}}]
|
||||
[backends.backend-{{.Config.Hostname}}.servers.server-{{.Config.Hostname}}]
|
||||
|
||||
{{/* Only one exposed port! */}}
|
||||
{{if eq (len .Config.ExposedPorts) 1}}
|
||||
{{$ip := .NetworkSettings.IPAddress}}
|
||||
{{range $keyPort, $valuePort := .Config.ExposedPorts}}
|
||||
url = "http://{{$ip}}:{{$keyPort.Port}}"
|
||||
{{end}}
|
||||
{{else}}
|
||||
|
||||
{{end}}
|
||||
[backends.backend-{{getBackend .}}.servers.server-{{.Name | replace "/"}}]
|
||||
url = "http://{{.NetworkSettings.IPAddress}}:{{getPort .}}"
|
||||
{{end}}
|
||||
|
||||
[routes]{{range .Containers}}
|
||||
[routes.route-{{.Config.Hostname}}]
|
||||
backends = ["backend-{{.Config.Hostname}}"]
|
||||
[routes.route-{{.Config.Hostname}}.rules.rule-{{.Config.Hostname}}-hostname]
|
||||
[routes]{{range $host, $containers := .Hosts}}
|
||||
[routes.route-{{$host}}]
|
||||
backends = [{{range $container := $containers}}"backend-{{getBackend $container}}",{{end}}]
|
||||
[routes.route-{{$host}}.rules.rule-host-{{$host}}]
|
||||
category = "Host"
|
||||
value = "{{.Config.Hostname}}.zenika.fr"
|
||||
[routes.route-{{.Config.Hostname}}.rules.rule-{{.Config.Hostname}}-name]
|
||||
category = "Host"
|
||||
value = "{{.Name | replace "/"}}.zenika.fr"
|
||||
{{end}}
|
||||
value = "{{$host}}.zenika.fr"
|
||||
{{end}}
|
|
@ -1,7 +1,7 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Ramify</title>
|
||||
<title>træfik</title>
|
||||
|
||||
<!-- Bootstrap -->
|
||||
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
|
||||
|
@ -18,7 +18,7 @@
|
|||
<body>
|
||||
<nav class="navbar navbar-default" role="navigation">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand" href="/html/">Ramify</a>
|
||||
<a class="navbar-brand" href="/html/">træfik</a>
|
||||
</div>
|
||||
<div class="collapse navbar-collapse navbar-ex1-collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
|
|
|
@ -20,8 +20,8 @@ import (
|
|||
|
||||
type FileConfiguration struct {
|
||||
Docker *DockerProvider
|
||||
File *FileProvider
|
||||
Web *WebProvider
|
||||
File *FileProvider
|
||||
Web *WebProvider
|
||||
}
|
||||
|
||||
var srv *graceful.Server
|
||||
|
@ -40,9 +40,9 @@ func main() {
|
|||
log.Println("Configuration receveived", configuration)
|
||||
if configuration == nil {
|
||||
log.Println("Skipping empty configuration")
|
||||
} else if(reflect.DeepEqual(currentConfiguration, configuration)){
|
||||
} else if (reflect.DeepEqual(currentConfiguration, configuration)) {
|
||||
log.Println("Skipping same configuration")
|
||||
} else{
|
||||
} else {
|
||||
currentConfiguration = configuration
|
||||
configurationRouter = LoadConfig(configuration)
|
||||
srv.Stop(10 * time.Second)
|
||||
|
@ -52,15 +52,15 @@ func main() {
|
|||
}()
|
||||
|
||||
configuration := LoadFileConfig()
|
||||
if(configuration.Docker != nil){
|
||||
if (configuration.Docker != nil) {
|
||||
providers = append(providers, configuration.Docker)
|
||||
}
|
||||
|
||||
if(configuration.File != nil){
|
||||
if (configuration.File != nil) {
|
||||
providers = append(providers, configuration.File)
|
||||
}
|
||||
|
||||
if(configuration.Web != nil){
|
||||
if (configuration.Web != nil) {
|
||||
providers = append(providers, configuration.Web)
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,7 @@ func main() {
|
|||
|
||||
func LoadConfig(configuration *Configuration) *mux.Router {
|
||||
router := mux.NewRouter()
|
||||
backends := map[string]http.Handler{}
|
||||
for routeName, route := range configuration.Routes {
|
||||
log.Println("Creating route", routeName)
|
||||
fwd, _ := forward.New()
|
||||
|
@ -118,16 +119,21 @@ func LoadConfig(configuration *Configuration) *mux.Router {
|
|||
newRoutes = append(newRoutes, newRoute)
|
||||
}
|
||||
for _, backendName := range route.Backends {
|
||||
log.Println("Creating backend", backendName)
|
||||
lb, _ := roundrobin.New(fwd)
|
||||
rb, _ := roundrobin.NewRebalancer(lb)
|
||||
for serverName, server := range configuration.Backends[backendName].Servers {
|
||||
log.Println("Creating server", serverName)
|
||||
url, _ := url.Parse(server.Url)
|
||||
rb.UpsertServer(url)
|
||||
if (backends[backendName] ==nil) {
|
||||
log.Println("Creating backend", backendName)
|
||||
lb, _ := roundrobin.New(fwd)
|
||||
rb, _ := roundrobin.NewRebalancer(lb)
|
||||
for serverName, server := range configuration.Backends[backendName].Servers {
|
||||
log.Println("Creating server", serverName)
|
||||
url, _ := url.Parse(server.Url)
|
||||
rb.UpsertServer(url)
|
||||
}
|
||||
backends[backendName]=lb
|
||||
}else {
|
||||
log.Println("Reusing backend", backendName)
|
||||
}
|
||||
for _, route := range newRoutes {
|
||||
route.Handler(handlers.CombinedLoggingHandler(os.Stdout, lb))
|
||||
route.Handler(handlers.CombinedLoggingHandler(os.Stdout, backends[backendName]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,9 +148,9 @@ func Invoke(any interface{}, name string, args ...interface{}) []reflect.Value {
|
|||
return reflect.ValueOf(any).MethodByName(name).Call(inputs)
|
||||
}
|
||||
|
||||
func LoadFileConfig() *FileConfiguration {
|
||||
func LoadFileConfig() *FileConfiguration {
|
||||
configuration := new(FileConfiguration)
|
||||
if _, err := toml.DecodeFile("ramify.toml", configuration); err != nil {
|
||||
if _, err := toml.DecodeFile("træfik.toml", configuration); err != nil {
|
||||
log.Fatal("Error reading file:", err)
|
||||
}
|
||||
return configuration
|
|
@ -6,7 +6,7 @@ watch = true
|
|||
address = ":8010"
|
||||
|
||||
#[file]
|
||||
#filename = "ramify.toml"
|
||||
#filename = "træfik.toml"
|
||||
#watch = true
|
||||
|
||||
[backends]
|
Loading…
Reference in a new issue