├── Dockerfile ├── README.md ├── root └── opt │ └── tools │ └── rancher-template │ ├── etc │ └── traefik.yml │ └── tmpl │ └── traefik.tmpl └── version /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rawmind/rancher-tools:3.6-7 2 | MAINTAINER Raul Sanchez 3 | 4 | #Set environment 5 | ENV SERVICE_NAME=traefik \ 6 | SERVICE_USER=traefik \ 7 | SERVICE_UID=10001 \ 8 | SERVICE_GROUP=traefik \ 9 | SERVICE_GID=10001 \ 10 | SERVICE_ARCHIVE=/opt/traefik-rancher-tools.tgz 11 | 12 | # Add files 13 | ADD root / 14 | RUN cd ${SERVICE_VOLUME} && \ 15 | tar czvf ${SERVICE_ARCHIVE} * ; rm -rf ${SERVICE_VOLUME}/* 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![](https://images.microbadger.com/badges/image/rawmind/rancher-traefik.svg)](https://microbadger.com/images/rawmind/rancher-traefik "Get your own image badge on microbadger.com") 2 | 3 | rancher-traefik 4 | ============== 5 | 6 | This image is the traefik dynamic conf for rancher. It comes from [rawmind/rancher-tools][rancher-tools]. 7 | 8 | ## Build 9 | 10 | ``` 11 | docker build -t rawmind/rancher-traefik: . 12 | ``` 13 | 14 | ## Versions 15 | 16 | - `1.5.0-0` [(Dockerfile)](https://github.com/rawmind0/rancher-traefik/blob/1.5.0-0/Dockerfile) 17 | - `1.4.4-6` [(Dockerfile)](https://github.com/rawmind0/rancher-traefik/blob/1.4.4-6/Dockerfile) 18 | - `1.3.6` [(Dockerfile)](https://github.com/rawmind0/rancher-traefik/blob/1.3.6/Dockerfile) 19 | - `1.3.3-2` [(Dockerfile)](https://github.com/rawmind0/rancher-traefik/blob/1.3.3-2/Dockerfile) 20 | - `0.3.4-19` [(Dockerfile)](https://github.com/rawmind0/rancher-traefik/blob/0.3.4-19/Dockerfile) 21 | 22 | 23 | ## Usage 24 | 25 | This image has to be run as a sidekick of [rawmind/alpine-traefik][alpine-traefik], and makes available `/opt/tools volume`. It scans from `rancher-metadata`, looking for `services` and `externalServices` that have traefik labels and generates traefik frontend and backends to expose the services. 26 | 27 | 28 | ## Configuration labels 29 | 30 | Traefik labels have to be created in your `service` or `externalService` in order to get included in traefik dynamic config. 31 | 32 | - traefik.enable = < true | stack | false > #Controls if you want to publish or not the service 33 | - true: the service will be published as *service_name.stack_name.traefik_domain* 34 | - stack: the service will be published as *stack_name.domain*. WARNING: You can have collisions inside services within your stack 35 | - false: the service will not be published 36 | - traefik.priority = # Override for frontend priority. Default `5` 37 | - traefik.protocol = < http | https > # Override the default protocol `http` 38 | - traefik.sticky = < true | false > # Enable/disable sticky sessions to the backend. Default `false` 39 | - traefik.backend.loadbalancer.method = < drr | wrr > # Override default lb algorithm `drr` 40 | - traefik.backend.circuitbreaker.expression = < expression > # Override default backend circuitbreaker expression `NetworkErrorRatio() > 0.5` 41 | - traefik.frontend.passHostHeader = < true | false > # Forward client Host header to the backend. Default `true` 42 | - traefik.weight = < weight > # Override default backend weight `5` 43 | - traefik.alias = < alias > # Alternate names to route rule. Multiple values separated by ",". traefik.domain is appended. WARNING: You could have collisions BE CAREFUL 44 | - traefik.alias.fqdn = < alias fqdn > # Alternate names to route rule. Multiple values separated by ",". `traefik.domain` must be defined but is not appended here 45 | - traefik.domain = < domain.name > # Domain names to route rules. Multiple domains separated by "," 46 | - traefik.domain.regexp = < domain.regexp > # Domain name regexp rule. Multiple domains separated by "," 47 | - traefik.port = # Port to expose through traefik. Default `80` 48 | - traefik.acme = < true | false > # Enable/disable ACME traefik feature. Default `false` 49 | - traefik.path = < path > # Path rule. Multiple values separated by "," 50 | - traefik.path.strip = < path > # Path strip rule. Multiple values separated by "," 51 | - traefik.path.prefix = < path > # Path prefix rule. Multiple values separated by "," 52 | - traefik.path.prefix.strip = < path > # Path prefix strip rule. Multiple values separated by "," 53 | - traefik.ratelimit.enable = < true | false > # Enable/disabe rate-limiting based on client ip. Default `false` 54 | - traefik.ratelimit.period = < n > # Replace n with desired amount of seconds in which traefik is checking the limits "average" and "burst". Default `10` 55 | - traefik.ratelimit.average = < n > # Change to desired average allowed requests by client ip. Default `100` 56 | - traefik.ratelimit.burst = < n > # State what limit the client ip is allowed to burst up to respectively. Default `200` 57 | 58 | WARNING: Only services with healthy state are added to traefik, so health checks are mandatory. 59 | 60 | Details for configuring the traefik rules can be found at: https://docs.traefik.io/basics/#frontends 61 | 62 | [alpine-traefik]: https://github.com/rawmind0/alpine-traefik 63 | [rancher-tools]: https://github.com/rawmind0/rancher-tools 64 | -------------------------------------------------------------------------------- /root/opt/tools/rancher-template/etc/traefik.yml: -------------------------------------------------------------------------------- 1 | destination: /opt/traefik/etc/rules.toml 2 | source: /opt/tools/rancher-template/tmpl/traefik.tmpl -------------------------------------------------------------------------------- /root/opt/tools/rancher-template/tmpl/traefik.tmpl: -------------------------------------------------------------------------------- 1 | [backends] 2 | {{- range $stack_index, $stack := . }} 3 | {{- range $service_index, $service := $stack.Services }} 4 | {{- $traefik_enable := (index $service.Labels "traefik.enable") -}} 5 | {{- if or (eq $traefik_enable "true") (eq $traefik_enable "stack")}} 6 | [backends.{{$service.Name}}__{{$stack.Name}}] 7 | [backends.{{$service.Name}}__{{$stack.Name}}.circuitbreaker] 8 | expression = {{$traefik_backend_circuitbreaker_expression := (index $service.Labels "traefik.backend.circuitbreaker.expression") -}} 9 | {{- if gt (len $traefik_backend_circuitbreaker_expression) 0 -}} 10 | "{{$traefik_backend_circuitbreaker_expression}}" 11 | {{- else -}} 12 | "NetworkErrorRatio() > 0.5" 13 | {{- end}} 14 | [backends.{{$service.Name}}__{{$stack.Name}}.LoadBalancer] 15 | method = {{$traefik_backend_loadbalancer_method := (index $service.Labels "traefik.backend.loadbalancer.method") -}} 16 | {{- if gt (len $traefik_backend_loadbalancer_method) 0 -}} 17 | "{{$traefik_backend_loadbalancer_method}}" 18 | {{- else -}} 19 | "drr" 20 | {{- end}} 21 | {{- $traefik_sticky := ( index $service.Labels "traefik.sticky") -}} 22 | {{- if eq $traefik_sticky "true"}} 23 | sticky = true 24 | {{- end -}} 25 | {{- if or (eq $service.Kind "service") (eq $service.Kind "externalService") -}} 26 | {{- $traefik_protocol := (index $service.Labels "traefik.protocol") -}} 27 | {{- $traefik_port := (index $service.Labels "traefik.port") -}} 28 | {{- range $container_index, $container := $service.Containers -}} 29 | {{- if and (ishealthy $container.HealthState) (isrunning $container.State) }} 30 | [backends.{{$service.Name}}__{{$stack.Name}}.servers.{{$container.Name}}] 31 | url = {{if eq $traefik_protocol "https" -}} 32 | "{{$traefik_protocol}}:// 33 | {{- else -}} 34 | "http:// 35 | {{- end -}} 36 | {{- if eq $service.Kind "service" -}} 37 | {{$container.PrimaryIp}}: 38 | {{- end -}} 39 | {{- if eq $service.Kind "externalService" -}} 40 | {{$container.Ips}}: 41 | {{- end -}} 42 | {{- if gt (len $traefik_port) 0 -}} 43 | {{$traefik_port}} 44 | {{- else -}} 45 | 80 46 | {{- end}}" 47 | weight = {{$traefik_weight := (index $service.Labels "traefik.weight") -}} 48 | {{- if gt (len $traefik_weight) 0 -}} 49 | {{$traefik_weight}} 50 | {{- else -}} 51 | 5 52 | {{- end}} 53 | {{- end -}} 54 | {{- end -}} 55 | {{- end -}} 56 | {{- end -}} 57 | {{- end -}} 58 | {{- end}} 59 | [frontends] 60 | {{- range $stack_index, $stack := . -}} 61 | {{- range $service_index, $service := $stack.Services -}} 62 | {{- $traefik_enable := (index $service.Labels "traefik.enable") -}} 63 | {{- if or (eq $traefik_enable "true") (eq $traefik_enable "stack") -}} 64 | {{- $traefik_priority := ( index $service.Labels "traefik.priority") -}} 65 | {{- $traefik_domain_regexp := ( index $service.Labels "traefik.domain.regexp") -}} 66 | {{- $traefik_domain := ( index $service.Labels "traefik.domain") -}} 67 | {{- $traefik_alias := ( index $service.Labels "traefik.alias") -}} 68 | {{- $traefik_alias_fqdn := ( index $service.Labels "traefik.alias.fqdn") -}} 69 | {{- $traefik_path := ( index $service.Labels "traefik.path") -}} 70 | {{- $traefik_path_strip := ( index $service.Labels "traefik.path.strip") -}} 71 | {{- $traefik_path_prefix := ( index $service.Labels "traefik.path.prefix") -}} 72 | {{- $traefik_path_prefix_strip := ( index $service.Labels "traefik.path.prefix.strip")}} 73 | [frontends.{{$service.Name}}__{{$stack.Name}}] 74 | backend = "{{$service.Name}}__{{$stack.Name}}" 75 | passHostHeader = {{$traefik_frontend_passHostHeader := (index $service.Labels "traefik.frontend.passHostHeader") -}} 76 | {{- if gt (len $traefik_frontend_passHostHeader) 0 -}} 77 | {{$traefik_frontend_passHostHeader}} 78 | {{- else -}} 79 | true 80 | {{- end}} 81 | priority = {{if gt (len $traefik_priority) 0 -}} 82 | {{$traefik_priority}} 83 | {{- else -}} 84 | 5 85 | {{- end}} 86 | [frontends.{{$service.Name}}__{{$stack.Name}}.routes.service] 87 | rule = " 88 | {{- if gt (len $traefik_domain_regexp) 0 -}} 89 | HostRegexp: 90 | {{- $regexpses := replace $traefik_domain_regexp " " "" -}} 91 | {{- $regexp := split $regexpses ","}} 92 | {{- range $i, $r := $regexp -}} 93 | {{- if $i -}},{{- end -}} 94 | {{- if not (eq $r "") -}}{{- tolower $r -}}{{- end -}} 95 | {{- end -}} 96 | , 97 | {{- end -}} 98 | {{- if gt (len $traefik_domain) 0 -}} 99 | Host: 100 | {{- $domains := replace $traefik_domain " " "" -}} 101 | {{- $domain := split $domains ","}} 102 | {{- range $i, $v := $domain -}} 103 | {{- if $i -}},{{- end -}} 104 | {{- if eq $traefik_enable "true"}} 105 | {{- tolower $service.Name -}}.{{- tolower $stack.Name -}}.{{- $v -}} 106 | {{- end -}} 107 | {{- if eq $traefik_enable "stack"}} 108 | {{- tolower $stack.Name -}}.{{- $v -}} 109 | {{- end -}} 110 | 111 | {{- if gt (len $traefik_alias) 0 -}} 112 | {{- $aliases := replace $traefik_alias " " "" -}} 113 | {{- $alias := split $aliases ","}} 114 | {{- range $i2, $a:= $alias -}} 115 | ,{{- if not (eq $a "") -}}{{- tolower $a -}}.{{- end -}}{{- $v -}} 116 | {{- end -}} 117 | {{- end -}} 118 | {{- end -}} 119 | {{- if gt (len $traefik_alias_fqdn) 0 -}} 120 | {{- $afqdns := replace $traefik_alias_fqdn " " "" -}} 121 | {{- $afqdn := split $afqdns ","}} 122 | {{- range $i2, $af := $afqdn -}} 123 | ,{{- if not (eq $af "") -}}{{- tolower $af -}}{{- end -}} 124 | {{- end -}} 125 | , 126 | {{- end -}} 127 | ; 128 | {{- else -}} 129 | Host: {{- tolower $service.Name -}}.{{- tolower $stack.Name -}}; 130 | {{- end -}} 131 | {{- if gt (len $traefik_path) 0 -}} 132 | Path: 133 | {{- $paths := replace $traefik_path " " "" -}} 134 | {{- $path := split $paths "," -}} 135 | {{- range $i, $p := $path -}} 136 | {{- if $i -}},{{- end -}} 137 | {{- if not (eq $p "") -}}{{- tolower $p -}}{{- end -}} 138 | {{- end -}} 139 | ; 140 | {{- end -}} 141 | {{- if gt (len $traefik_path_strip) 0 -}} 142 | PathStrip: 143 | {{- $paths := replace $traefik_path_strip " " "" -}} 144 | {{- $path := split $paths "," -}} 145 | {{- range $i, $p := $path -}} 146 | {{- if $i -}},{{- end -}} 147 | {{- if not (eq $p "") -}}{{- tolower $p -}}{{- end -}} 148 | {{- end -}} 149 | ; 150 | {{- end -}} 151 | {{- if gt (len $traefik_path_prefix) 0 -}} 152 | PathPrefix: 153 | {{- $paths := replace $traefik_path_prefix " " "" -}} 154 | {{- $path := split $paths "," -}} 155 | {{- range $i, $p := $path -}} 156 | {{- if $i -}},{{- end -}} 157 | {{- if not (eq $p "") -}}{{- tolower $p -}}{{- end -}} 158 | {{- end -}} 159 | ; 160 | {{- end -}} 161 | {{- if gt (len $traefik_path_prefix_strip) 0 -}} 162 | PathPrefixStrip: 163 | {{- $paths := replace $traefik_path_prefix_strip " " "" -}} 164 | {{- $path := split $paths "," -}} 165 | {{- range $i, $p := $path -}} 166 | {{- if $i -}},{{- end -}} 167 | {{- if not (eq $p "") -}}{{- tolower $p -}}{{- end -}} 168 | {{- end -}} 169 | ; 170 | {{- end -}} 171 | " 172 | {{- $traefik_ratelimit_enable := (index $service.Labels "traefik.ratelimit.enable") -}} 173 | {{- if eq $traefik_ratelimit_enable "true" -}} 174 | {{- $traefik_ratelimit_period := (index $service.Labels "traefik.ratelimit.period") -}} 175 | {{- $traefik_ratelimit_average := (index $service.Labels "traefik.ratelimit.average") -}} 176 | {{- $traefik_ratelimit_burst := (index $service.Labels "traefik.ratelimit.burst") }} 177 | [frontends.{{$service.Name}}__{{$stack.Name}}.ratelimit] 178 | extractorfunc = "client.ip" 179 | [frontends.{{$service.Name}}__{{$stack.Name}}.ratelimit.rateset.rateset1] 180 | period = {{if gt (len $traefik_ratelimit_period) 0 -}}"{{$traefik_ratelimit_period}}s" 181 | {{- else -}} "10s"{{- end }} 182 | average = {{if gt (len $traefik_ratelimit_average) 0 -}}{{$traefik_ratelimit_average}} 183 | {{- else -}}100{{- end}} 184 | burst = {{if gt (len $traefik_ratelimit_burst) 0}}{{$traefik_ratelimit_burst}} 185 | {{- else -}}200{{- end}} 186 | {{- end -}} 187 | {{- end -}} 188 | {{- end -}} 189 | {{- end}} 190 | {{- range $stack_index, $stack := . }} 191 | {{- range $service_index, $service := $stack.Services }} 192 | {{- $traefik_enable := (index $service.Labels "traefik.enable") -}} 193 | {{- if or (eq $traefik_enable "true") (eq $traefik_enable "stack")}} 194 | {{- $traefik_acme := ( index $service.Labels "traefik.acme") -}} 195 | {{- if eq $traefik_acme "true" -}} 196 | {{- $traefik_domain := ( index $service.Labels "traefik.domain") -}} 197 | {{- $traefik_alias := ( index $service.Labels "traefik.alias") -}} 198 | {{- $traefik_alias_fqdn := ( index $service.Labels "traefik.alias.fqdn") -}} 199 | {{- if gt (len $traefik_domain) 0 -}} 200 | {{- $domains := replace $traefik_domain " " "" -}} 201 | {{- $domain := split $domains ","}} 202 | {{- range $i, $v := $domain -}} 203 | {{- if not $i}} 204 | [[acme.domains]] 205 | {{- if eq $traefik_enable "true"}} 206 | main = "{{tolower $service.Name}}.{{tolower $stack.Name}}.{{$v}}" 207 | {{- end}} 208 | {{- if eq $traefik_enable "stack"}} 209 | main = "{{tolower $stack.Name}}.{{$v}}" 210 | {{- end}} 211 | {{- if gt (len $traefik_alias) 0 -}} 212 | {{- $aliases := replace $traefik_alias " " "" -}} 213 | {{- $alias := split $aliases "," -}} 214 | {{- if or (gt (len $domain) 1) (len $alias)}} 215 | sans = [" 216 | {{- range $i2, $a := $alias -}} 217 | {{- if or ($i) ($i2) -}},{{- end -}} 218 | {{- if not (eq $a "") -}}{{- tolower $a -}}.{{- end -}}{{- $v -}} 219 | {{- end -}} 220 | {{- if gt (len $traefik_alias_fqdn) 0 -}} 221 | {{- $afqdns := replace $traefik_alias_fqdn " " "" -}} 222 | {{- $afqdn := split $afqdns "," -}} 223 | {{- range $i2, $af := $afqdn -}} 224 | ,{{- if not (eq $af "") -}}{{- tolower $af -}}{{- end -}} 225 | {{- end -}} 226 | {{- end -}} 227 | {{- if (eq (len $domain) 1) -}} 228 | "] 229 | {{end -}} 230 | {{- end -}} 231 | {{- else -}} 232 | {{- if or (gt (len $domain) 1) (len $traefik_alias_fqdn)}} 233 | sans = [" 234 | {{- if gt (len $traefik_alias_fqdn) 0 -}} 235 | {{- $afqdns := replace $traefik_alias_fqdn " " "" -}} 236 | {{- $afqdn := split $afqdns "," -}} 237 | {{- range $i2, $af := $afqdn -}} 238 | {{- if or ($i) ($i2) -}},{{- end -}} 239 | {{- if not (eq $af "") -}}{{- tolower $af -}}{{- end -}} 240 | {{- end -}} 241 | {{- if (gt (len $domain) 1) -}},{{- end -}} 242 | {{- end -}} 243 | {{- if (eq (len $domain) 1) -}} 244 | "] 245 | {{end -}} 246 | {{- end -}} 247 | {{- end -}} 248 | {{- else -}} 249 | {{- if gt (len $traefik_alias) 0 -}} 250 | {{- if eq $traefik_enable "true" -}} 251 | ,{{- tolower $service.Name -}}.{{- tolower $stack.Name -}}.{{- $v -}} 252 | {{- end -}} 253 | {{- if eq $traefik_enable "stack" -}} 254 | ,{{- tolower $stack.Name -}}.{{- $v -}} 255 | {{- end -}} 256 | {{- $aliases := replace $traefik_alias " " "" -}} 257 | {{- $alias := split $aliases "," -}} 258 | {{- range $i2 , $a:= $alias -}} 259 | ,{{- if not (eq $a "") -}}{{- tolower $a -}}.{{- end -}}{{- $v -}} 260 | {{- end}} 261 | {{- else -}} 262 | {{- if gt $i 1 -}},{{- end -}} 263 | {{- if eq $traefik_enable "true" -}} 264 | {{- tolower $service.Name -}}.{{- tolower $stack.Name -}}.{{- $v -}} 265 | {{- else -}} 266 | {{- if eq $traefik_enable "stack" -}} 267 | {{- tolower $stack.Name -}}.{{- $v -}} 268 | {{- end -}} 269 | {{- end -}} 270 | {{- end -}} 271 | "] 272 | {{end -}} 273 | {{- end -}} 274 | {{- end -}} 275 | {{- end -}} 276 | {{- end -}} 277 | {{- end -}} 278 | {{- end}} 279 | -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- 1 | 1.5.0 2 | --------------------------------------------------------------------------------