diff --git a/.dockerignore b/.dockerignore index bbf209676..cc707f389 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,4 @@ dist/ vendor/ !dist/traefik +site/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index cac197c4c..866aca26c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ traefik.toml *.test vendor/ static/ -.vscode/ \ No newline at end of file +.vscode/ +site/ \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index b93c9a850..9373d8597 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,31 +1,39 @@ branches: except: - - /^v\d\.\d\.\d.*$/ - + - /^v\d\.\d\.\d.*$/ + env: REPO: $TRAVIS_REPO_SLUG VERSION: v1.0.0-beta.$TRAVIS_BUILD_NUMBER - + sudo: required services: - - docker +- docker + +before_install: +- openssl aes-256-cbc -K $encrypted_27087ae1f4db_key -iv $encrypted_27087ae1f4db_iv -in .travis/traefik.id_rsa.enc -out ~/.ssh/traefik.id_rsa -d +- eval "$(ssh-agent -s)" +- chmod 600 ~/.ssh/traefik.id_rsa +- ssh-add ~/.ssh/traefik.id_rsa install: - - sudo service docker stop - - sudo curl https://get.docker.com/builds/Linux/x86_64/docker-1.10.1 -o /usr/bin/docker - - sudo chmod +x /usr/bin/docker - - sudo service docker start +- sudo service docker stop +- sudo curl https://get.docker.com/builds/Linux/x86_64/docker-1.10.1 -o /usr/bin/docker +- sudo chmod +x /usr/bin/docker +- sudo service docker start +- pip install --user mkdocs +- pip install --user pymdown-extensions before_script: - - make validate - - make binary +- make validate +- make binary script: - - make test-unit - - make test-integration - - make crossbinary - - make image +- make test-unit +- make test-integration +- make crossbinary +- make image after_success: - - make deploy +- make deploy \ No newline at end of file diff --git a/.travis/traefik.id_rsa.enc b/.travis/traefik.id_rsa.enc new file mode 100644 index 000000000..bb347b95d Binary files /dev/null and b/.travis/traefik.id_rsa.enc differ diff --git a/README.md b/README.md index 956da967b..96c358d5d 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,42 @@

-Træfɪk +Træfɪk

[![Build Status](https://travis-ci.org/containous/traefik.svg?branch=master)](https://travis-ci.org/containous/traefik) -[![Go Report Card](http://goreportcard.com/badge/kubernetes/helm)](http://goreportcard.com/report/containous/traefik) +[![Docs](https://img.shields.io/badge/docs-current-brightgreen.svg)](https://docs.traefik.io) +[![Go Report Card](https://goreportcard.com/badge/kubernetes/helm)](http://goreportcard.com/report/containous/traefik) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/containous/traefik/blob/master/LICENSE.md) [![Join the chat at https://traefik.herokuapp.com](https://img.shields.io/badge/style-register-green.svg?style=social&label=Slack)](https://traefik.herokuapp.com) [![Twitter](https://img.shields.io/twitter/follow/traefikproxy.svg?style=social)](https://twitter.com/intent/follow?screen_name=traefikproxy) - Træfɪk is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease. -It supports several backends ([Docker :whale:](https://www.docker.com/), [Swarm :whale: :whale:](https://docs.docker.com/swarm), [Mesos/Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Zookeeper](https://zookeeper.apache.org), [BoltDB](https://github.com/boltdb/bolt), Rest API, file...) to manage its configuration automatically and dynamically. +It supports several backends ([Docker](https://www.docker.com/), [Swarm](https://docs.docker.com/swarm), [Mesos/Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Zookeeper](https://zookeeper.apache.org), [BoltDB](https://github.com/boltdb/bolt), Rest API, file...) to manage its configuration automatically and dynamically. + +## Overview + +Imagine that you have deployed a bunch of microservices on your infrastructure. You probably used a service registry (like etcd or consul) and/or an orchestrator (swarm, Mesos/Marathon) to manage all these services. +If you want your users to access some of your microservices from the Internet, you will have to use a reverse proxy and configure it using virtual hosts or prefix paths: + +- domain `api.domain.com` will point the microservice `api` in your private network +- path `domain.com/web` will point the microservice `web` in your private network +- domain `backoffice.domain.com` will point the microservices `backoffice` in your private network, load-balancing between your multiple instances + +But a microservices architecture is dynamic... Services are added, removed, killed or upgraded often, eventually several times a day. + +Traditional reverse-proxies are not natively dynamic. You can't change their configuration and hot-reload easily. + +Here enters Træfɪk. + +![Architecture](docs/img/architecture.png) + +Træfɪk can listen to your service registry/orchestrator API, and knows each time a microservice is added, removed, killed or upgraded, and can generate its configuration automatically. +Routes to your services will be created instantly. + +Run it and forget it! + + ## Features @@ -79,7 +103,7 @@ git clone https://github.com/containous/traefik ## Documentation -You can find the complete documentation [here](docs/index.md). +You can find the complete documentation [here](https://docs.traefik.io). ## Contributing diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 000000000..f4446d431 --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +docs.traefik.io \ No newline at end of file diff --git a/docs/basics.md b/docs/basics.md new file mode 100644 index 000000000..b7d44a17d --- /dev/null +++ b/docs/basics.md @@ -0,0 +1,181 @@ + +# Concepts + +Let's take our example from the [overview](https://docs.traefik.io/#overview) again: + + +> Imagine that you have deployed a bunch of microservices on your infrastructure. You probably used a service registry (like etcd or consul) and/or an orchestrator (swarm, Mesos/Marathon) to manage all these services. +> If you want your users to access some of your microservices from the Internet, you will have to use a reverse proxy and configure it using virtual hosts or prefix paths: + +> - domain `api.domain.com` will point the microservice `api` in your private network +> - path `domain.com/web` will point the microservice `web` in your private network +> - domain `backoffice.domain.com` will point the microservices `backoffice` in your private network, load-balancing between your multiple instances + +> ![Architecture](img/architecture.png) + +Let's zoom on Træfɪk and have an overview of its internal architecture: + + +![Architecture](img/internal.png) + +- Incoming requests end on [entrypoints](#entrypoints), as the name suggests, they are the network entry points into Træfɪk (listening port, SSL, traffic redirection...). +- Traffic is then forwared to a matching [frontend](#frontends). A frontend defines routes from [entrypoints](#entrypoints) to [backends](#backends). +Routes are created using requests fields (`Host`, `Path`, `Headers`...) and can match or not a request. +- The [frontend](#frontends) will then send the request to a [backend](#backends). A backend can be composed by one or more [servers](#servers), and by a load-balancing strategy. +- Finally, the [server](#servers) will forward the request to the corresponding microservice in the private network. + +## Entrypoints + +Entrypoints are the network entry points into Træfɪk. +They can be defined using: + +- a port (80, 443...) +- SSL (Certificates. Keys...) +- redirection to another entrypoint (redirect `HTTP` to `HTTPS`) + +Here is an example of entrypoints definition: + +```toml +[entryPoints] + [entryPoints.http] + address = ":80" + [entryPoints.http.redirect] + entryPoint = "https" + [entryPoints.https] + address = ":443" + [entryPoints.https.tls] + [[entryPoints.https.tls.certificates]] + certFile = "tests/traefik.crt" + keyFile = "tests/traefik.key" +``` + +- Two entrypoints are defined `http` and `https`. +- `http` listens on port `80` et `https` on port `443`. +- We enable SSL en `https` by giving a certificate and a key. +- We also redirect all the traffic from entrypoint `http` to `https`. + +## Frontends + +A frontend is a set of rules that forwards the incoming traffic from an entrypoint to a backend. +Frontends can be defined using the following rules: + +- `Headers`: Headers adds a matcher for request header values. It accepts a sequence of key/value pairs to be matched. For example: `Content-Type, application/json` +- `HeadersRegexp`: Regular expressions can be used with headers as well. It accepts a sequence of key/value pairs, where the value has regex support. For example: `Content-Type, application/(text|json)` +- `Host`: Host adds a matcher for the URL host. It accepts a template with zero or more URL variables enclosed by `{}`. Variables can define an optional regexp pattern to be matched: `www.traefik.io`, `{subdomain:[a-z]+}.traefik.io` +- `Methods`: Methods adds a matcher for HTTP methods. It accepts a sequence of one or more methods to be matched, e.g.: `GET`, `POST`, `PUT` +- `Path`: Path adds a matcher for the URL path. It accepts a template with zero or more URL variables enclosed by `{}`. The template must start with a `/`. For exemple `/products/` `/articles/{category}/{id:[0-9]+}` +- `PathStrip`: Same as `Path` but strip the given prefix from the request URL's Path. +- `PathPrefix`: PathPrefix adds a matcher for the URL path prefix. This matches if the given template is a prefix of the full URL path. +- `PathPrefixStrip`: Same as `PathPrefix` but strip the given prefix from the request URL's Path. + +You can optionally enable `passHostHeader` to forward client `Host` header to the backend. + +Here is an example of frontends definition: + +```toml +[frontends] + [frontends.frontend1] + backend = "backend2" + [frontends.frontend1.routes.test_1] + rule = "Host:test.localhost" + [frontends.frontend2] + backend = "backend1" + passHostHeader = true + entrypoints = ["https"] # overrides defaultEntryPoints + [frontends.frontend2.routes.test_1] + rule = "Host:{subdomain:[a-z]+}.localhost" + [frontends.frontend3] + backend = "backend2" + rule = "Path:/test" +``` + +- Three frontends are defined: `frontend1`, `frontend2` and `frontend3` +- `frontend1` will forward the traffic to the `backend2` if the rule `Host:test.localhost` is matched +- `frontend2` will forward the traffic to the `backend1` if the rule `Host:{subdomain:[a-z]+}.localhost` is matched (forwarding client `Host` header to the backend) +- `frontend3` will forward the traffic to the `backend2` if the rule `Path:/test` is matched + +## Backends + +A backend is responsible to load-balance the traffic coming from one or more frontends to a set of http servers. +Various methods of load-balancing is supported: + +- `wrr`: Weighted Round Robin +- `drr`: Dynamic Round Robin: increases weights on servers that perform better than others. It also rolls back to original weights if the servers have changed. + +A circuit breaker can also be applied to a backend, preventing high loads on failing servers. +Initial state is Standby. CB observes the statistics and does not modify the request. +In case if condition matches, CB enters Tripped state, where it responds with predefines code or redirects to another frontend. +Once Tripped timer expires, CB enters Recovering state and resets all stats. +In case if the condition does not match and recovery timer expries, CB enters Standby state. + +It can be configured using: + +- Methods: `LatencyAtQuantileMS`, `NetworkErrorRatio`, `ResponseCodeRatio` +- Operators: `AND`, `OR`, `EQ`, `NEQ`, `LT`, `LE`, `GT`, `GE` + +For example: + +- `NetworkErrorRatio() > 0.5`: watch error ratio over 10 second sliding window for a frontend +- `LatencyAtQuantileMS(50.0) > 50`: watch latency at quantile in milliseconds. +- `ResponseCodeRatio(500, 600, 0, 600) > 0.5`: ratio of response codes in range [500-600) to [0-600) + +## Servers + +Servers are simply defined using a `URL`. You can also apply a custom `weight` to each server (this will be used by load-balacning). + +Here is an example of backends and servers definition: + +```toml +[backends] + [backends.backend1] + [backends.backend1.circuitbreaker] + expression = "NetworkErrorRatio() > 0.5" + [backends.backend1.servers.server1] + url = "http://172.17.0.2:80" + weight = 10 + [backends.backend1.servers.server2] + url = "http://172.17.0.3:80" + weight = 1 + [backends.backend2] + [backends.backend2.LoadBalancer] + method = "drr" + [backends.backend2.servers.server1] + url = "http://172.17.0.4:80" + weight = 1 + [backends.backend2.servers.server2] + url = "http://172.17.0.5:80" + weight = 2 +``` + +- Two backends are defined: `backend1` and `backend2` +- `backend1` will forward the traffic to two servers: `http://172.17.0.2:80"` with weight `10` and `http://172.17.0.3:80` with weight `1` using default `wrr` load-balancing strategy. +- `backend2` will forward the traffic to two servers: `http://172.17.0.4:80"` with weight `1` and `http://172.17.0.5:80` with weight `2` using `drr` load-balancing strategy. +- a circuit breaker is added on `backend1` using the expression `NetworkErrorRatio() > 0.5`: watch error ratio over 10 second sliding window + +# Launch + +Træfɪk can be configured using a TOML file configuration, arguments, or both. +By default, Træfɪk will try to find a `traefik.toml` in the following places: + +- `/etc/traefik/` +- `$HOME/.traefik/` +- `.` *the working directory* + +You can override this by setting a `configFile` argument: + +```bash +$ traefik --configFile=foo/bar/myconfigfile.toml +``` + +Træfɪk uses the following precedence order. Each item takes precedence over the item below it: + +- arguments +- configuration file +- default + +It means that arguments overrides configuration file. +Each argument is described in the help section: + +```bash +$ traefik --help +``` diff --git a/docs/benchmarks.md b/docs/benchmarks.md new file mode 100644 index 000000000..96c501173 --- /dev/null +++ b/docs/benchmarks.md @@ -0,0 +1,70 @@ +# Benchmarks + +Here are some early Benchmarks between Nginx, HA-Proxy and Træfɪk acting as simple load balancers between two servers. + +- Nginx: + +```sh +$ docker run -d -e VIRTUAL_HOST=test.nginx.localhost emilevauge/whoami +$ docker run -d -e VIRTUAL_HOST=test.nginx.localhost emilevauge/whoami +$ docker run --log-driver=none -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy +$ wrk -t12 -c400 -d60s -H "Host: test.nginx.localhost" --latency http://127.0.0.1:80 +Running 1m test @ http://127.0.0.1:80 + 12 threads and 400 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 162.61ms 203.34ms 1.72s 91.07% + Req/Sec 277.57 107.67 790.00 67.53% + Latency Distribution + 50% 128.19ms + 75% 218.22ms + 90% 342.12ms + 99% 1.08s + 197991 requests in 1.00m, 82.32MB read + Socket errors: connect 0, read 0, write 0, timeout 18 +Requests/sec: 3296.04 +Transfer/sec: 1.37MB +``` + +- HA-Proxy: + +```sh +$ docker run -d --name web1 -e VIRTUAL_HOST=test.haproxy.localhost emilevauge/whoami +$ docker run -d --name web2 -e VIRTUAL_HOST=test.haproxy.localhost emilevauge/whoami +$ docker run -d -p 80:80 --link web1:web1 --link web2:web2 dockercloud/haproxy +$ wrk -t12 -c400 -d60s -H "Host: test.haproxy.localhost" --latency http://127.0.0.1:80 +Running 1m test @ http://127.0.0.1:80 + 12 threads and 400 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 158.08ms 187.88ms 1.75s 89.61% + Req/Sec 281.33 120.47 0.98k 65.88% + Latency Distribution + 50% 121.77ms + 75% 227.10ms + 90% 351.98ms + 99% 1.01s + 200462 requests in 1.00m, 59.65MB read +Requests/sec: 3337.66 +Transfer/sec: 0.99MB +``` + +- Træfɪk: + +```sh +$ docker run -d -l traefik.backend=test1 -l traefik.frontend.rule=Host -l traefik.frontend.value=test.traefik.localhost emilevauge/whoami +$ docker run -d -l traefik.backend=test1 -l traefik.frontend.rule=Host -l traefik.frontend.value=test.traefik.localhost emilevauge/whoami +$ docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.toml:/traefik.toml -v /var/run/docker.sock:/var/run/docker.sock containous/traefik +$ wrk -t12 -c400 -d60s -H "Host: test.traefik.localhost" --latency http://127.0.0.1:80 +Running 1m test @ http://127.0.0.1:80 + 12 threads and 400 connections + Thread Stats Avg Stdev Max +/- Stdev + Latency 132.93ms 121.89ms 1.20s 66.62% + Req/Sec 280.95 104.88 740.00 68.26% + Latency Distribution + 50% 128.71ms + 75% 214.15ms + 90% 281.45ms + 99% 498.44ms + 200734 requests in 1.00m, 80.02MB read +Requests/sec: 3340.13 +Transfer/sec: 1.33MB +``` \ No newline at end of file diff --git a/docs/css/traefik.css b/docs/css/traefik.css new file mode 100644 index 000000000..051a0b486 --- /dev/null +++ b/docs/css/traefik.css @@ -0,0 +1,43 @@ +a { + color: #37ABC8; + text-decoration: none; +} + +a:hover, a:focus { + color: #25606F; + text-decoration: underline; +} + +h1, h2, h3, H4 { + color: #37ABC8; +} + +.navbar-default { + background-color: #37ABC8; + border-color: #25606F; +} + +.navbar-default .navbar-nav>.active>a, .navbar-default .navbar-nav>.active>a:hover, .navbar-default .navbar-nav>.active>a:focus { + color: #fff; + background-color: #25606F; +} + +.navbar-default .navbar-nav>li>a:hover, .navbar-default .navbar-nav>li>a:focus { + color: #fff; + background-color: #25606F; +} + +.navbar-default .navbar-toggle { + border-color: #25606F; +} + +.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus .navbar-toggle { + background-color: #25606F; +} +.navbar-default .navbar-collapse, .navbar-default .navbar-form { + border-color: #25606F; +} + +blockquote p { + font-size: 14px; +} \ No newline at end of file diff --git a/docs/img/architecture.png b/docs/img/architecture.png new file mode 100644 index 000000000..85cde6491 Binary files /dev/null and b/docs/img/architecture.png differ diff --git a/docs/img/architecture.svg b/docs/img/architecture.svg new file mode 100644 index 000000000..db214d233 --- /dev/null +++ b/docs/img/architecture.svg @@ -0,0 +1,2407 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + API + + BACKOFFICE 1 + + DATA + + WEB + + ADMIN + + BACKOFFICE 2 + + BACKOFFICE 3 + + + + + API.DOMAIN.COM + DOMAIN.COM/WEB + BACKOFFICE.DOMAIN.COM + + + + + + + ORCHESTRATOR + + PRIVATE NETWORK + INTERNET + + API + LISTEN + (DOCKER, SWARM, MESOS...) + + + + + diff --git a/docs/img/internal.png b/docs/img/internal.png new file mode 100644 index 000000000..0abe8799f Binary files /dev/null and b/docs/img/internal.png differ diff --git a/docs/img/letsencrypt-logo-horizontal.svg b/docs/img/letsencrypt-logo-horizontal.svg new file mode 100644 index 000000000..5498a1e7b --- /dev/null +++ b/docs/img/letsencrypt-logo-horizontal.svg @@ -0,0 +1,172 @@ + + + + + + image/svg+xml + + + + + + + + Layer 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/img/overview.svg b/docs/img/overview.svg new file mode 100644 index 000000000..6d6bc027c --- /dev/null +++ b/docs/img/overview.svg @@ -0,0 +1,5394 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + Port: 80Redirect: SSL + + Port: 443Redirect: no + + + + + FRONTENDS + ENTRYPOINTS + HTTP + SSL + Host:api.domain.com + + Host:backoffice.domain.com + + Host:domain.comPath:/web + + BACKENDS + + BACK 1 + + BACK 2 + BACK 3 + + WEB + + API + + + + + + + + + + + + + + + API + WEB + BACKOFFICE 1 + BACKOFFICE 2 + + + + + + BACKOFFICE 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/img/traefik.icon.png b/docs/img/traefik.icon.png new file mode 100644 index 000000000..9708dd0ba Binary files /dev/null and b/docs/img/traefik.icon.png differ diff --git a/docs/img/traefik.logo.png b/docs/img/traefik.logo.png new file mode 100644 index 000000000..4778d0f5b Binary files /dev/null and b/docs/img/traefik.logo.png differ diff --git a/docs/index.md b/docs/index.md index 6ab689904..17d702344 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,1238 +1,131 @@

-Træfɪk +Træfɪk

-# Documentation - -- [Basics](#basics) -- [Launch configuration](#launch-configuration) -- [Global configuration](#global-configuration) -- [File backend](#file-backend) -- [API backend](#api-backend) -- [Docker backend](#docker-backend) -- [Mesos/Marathon backend](#marathon-backend) -- [Consul backend](#consul-backend) -- [Consul catalog backend](#consul-catalog-backend) -- [Etcd backend](#etcd-backend) -- [Zookeeper backend](#zookeeper-backend) -- [Boltdb backend](#boltdb-backend) -- [Atomic configuration changes](#atomic-configuration-changes) -- [Benchmarks](#benchmarks) - - -## Basics +[![Build Status](https://travis-ci.org/containous/traefik.svg?branch=master)](https://travis-ci.org/containous/traefik) +[![Docs](https://img.shields.io/badge/docs-current-brightgreen.svg)](https://docs.traefik.io) +[![Go Report Card](https://goreportcard.com/badge/kubernetes/helm)](http://goreportcard.com/report/containous/traefik) +[![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/containous/traefik/blob/master/LICENSE.md) +[![Join the chat at https://traefik.herokuapp.com](https://img.shields.io/badge/style-register-green.svg?style=social&label=Slack)](https://traefik.herokuapp.com) +[![Twitter](https://img.shields.io/twitter/follow/traefikproxy.svg?style=social)](https://twitter.com/intent/follow?screen_name=traefikproxy) Træfɪk is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease. -It supports several backends ([Docker :whale:](https://www.docker.com/), [Mesos/Marathon](https://mesosphere.github.io/marathon/), [Consul](https://consul.io/), [Etcd](https://coreos.com/etcd/), Rest API, file...) to manage its configuration automatically and dynamically. +It supports several backends ([Docker](https://www.docker.com/), [Swarm](https://docs.docker.com/swarm), [Mesos/Marathon](https://mesosphere.github.io/marathon/), [Consul](https://www.consul.io/), [Etcd](https://coreos.com/etcd/), [Zookeeper](https://zookeeper.apache.org), [BoltDB](https://github.com/boltdb/bolt), Rest API, file...) to manage its configuration automatically and dynamically. -Basically, Træfɪk is a http router, which sends traffic from frontends to http backends, following rules you have configured. +## Overview -### Frontends +Imagine that you have deployed a bunch of microservices on your infrastructure. You probably used a service registry (like etcd or consul) and/or an orchestrator (swarm, Mesos/Marathon) to manage all these services. +If you want your users to access some of your microservices from the Internet, you will have to use a reverse proxy and configure it using virtual hosts or prefix paths: -Frontends can be defined using the following rules: +- domain `api.domain.com` will point the microservice `api` in your private network +- path `domain.com/web` will point the microservice `web` in your private network +- domain `backoffice.domain.com` will point the microservices `backoffice` in your private network, load-balancing between your multiple instances -- `Headers`: Headers adds a matcher for request header values. It accepts a sequence of key/value pairs to be matched. For example: `Content-Type, application/json` -- `HeadersRegexp`: Regular expressions can be used with headers as well. It accepts a sequence of key/value pairs, where the value has regex support. For example: `Content-Type, application/(text|json)` -- `Host`: Host adds a matcher for the URL host. It accepts a template with zero or more URL variables enclosed by `{}`. Variables can define an optional regexp pattern to be matched: `www.traefik.io`, `{subdomain:[a-z]+}.traefik.io` -- `Methods`: Methods adds a matcher for HTTP methods. It accepts a sequence of one or more methods to be matched, e.g.: `GET`, `POST`, `PUT` -- `Path`: Path adds a matcher for the URL path. It accepts a template with zero or more URL variables enclosed by `{}`. The template must start with a `/`. For exemple `/products/` `/articles/{category}/{id:[0-9]+}` -- `PathStrip`: Same as `Path` but strip the given prefix from the request URL's Path. -- `PathPrefix`: PathPrefix adds a matcher for the URL path prefix. This matches if the given template is a prefix of the full URL path. -- `PathPrefixStrip`: Same as `PathPrefix` but strip the given prefix from the request URL's Path. +But a microservices architecture is dynamic... Services are added, removed, killed or upgraded often, eventually several times a day. +Traditional reverse-proxies are not natively dynamic. You can't change their configuration and hot-reload easily. - A frontend is a set of rules that forwards the incoming http traffic to a backend. - You can optionally enable `passHostHeader` to forward client `Host` header to the backend. +Here enters Træfɪk. -### HTTP Backends +![Architecture](img/architecture.png) -A backend is responsible to load-balance the traffic coming from one or more frontends to a set of http servers. -Various methods of load-balancing is supported: +Træfɪk can listen to your service registry/orchestrator API, and knows each time a microservice is added, removed, killed or upgraded, and can generate its configuration automatically. +Routes to your services will be created instantly. -- `wrr`: Weighted Round Robin -- `drr`: Dynamic Round Robin: increases weights on servers that perform better than others. It also rolls back to original weights if the servers have changed. +Run it and forget it! + -A circuit breaker can also be applied to a backend, preventing high loads on failing servers. -Initial state is Standby. CB observes the statistics and does not modify the request. -In case if condition matches, CB enters Tripped state, where it responds with predefines code or redirects to another frontend. -Once Tripped timer expires, CB enters Recovering state and resets all stats. -In case if the condition does not match and recovery timer expries, CB enters Standby state. +## Demo -It can be configured using: +Here is a demo of Træfɪk using Docker backend, showing a load-balancing between two servers, hot reloading of configuration, and graceful shutdown. -- Methods: `LatencyAtQuantileMS`, `NetworkErrorRatio`, `ResponseCodeRatio` -- Operators: `AND`, `OR`, `EQ`, `NEQ`, `LT`, `LE`, `GT`, `GE` +[![asciicast](https://asciinema.org/a/4tcyde7riou5vxulo6my3mtko.png)](https://asciinema.org/a/4tcyde7riou5vxulo6my3mtko) -For example: -- `NetworkErrorRatio() > 0.5`: watch error ratio over 10 second sliding window for a frontend -- `LatencyAtQuantileMS(50.0) > 50`: watch latency at quantile in milliseconds. -- `ResponseCodeRatio(500, 600, 0, 600) > 0.5`: ratio of response codes in range [500-600) to [0-600) +## Get it +### Binary -## Launch configuration +You can grab the latest binary from the [releases](https://github.com/containous/traefik/releases) page and just run it with the [sample configuration file](https://raw.githubusercontent.com/containous/traefik/master/traefik.sample.toml): -Træfɪk can be configured using a TOML file configuration, arguments, or both. -By default, Træfɪk will try to find a `traefik.toml` in the following places: -- `/etc/traefik/` -- `$HOME/.traefik/` -- `.` the working directory +```shell +./traefik -c traefik.toml +``` -You can override this by setting a `configFile` argument: +### Docker + +Using the tiny Docker image: + +```shell +docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.toml:/etc/traefik/traefik.toml containous/traefik +``` + +## Test it + +You can test Træfɪk easily using [Docker compose](https://docs.docker.com/compose), with this `docker-compose.yml` file: + +```yaml +traefik: + image: containous/traefik + command: --web --docker --docker.domain=docker.localhost --logLevel=DEBUG + ports: + - "80:80" + - "8080:8080" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /dev/null:/traefik.toml + +whoami1: + image: emilevauge/whoami + labels: + - "traefik.backend=whoami" + - "traefik.frontend.rule=Host:whoami.docker.localhost" + +whoami2: + image: emilevauge/whoami + labels: + - "traefik.backend=whoami" + - "traefik.frontend.rule=Host:whoami.docker.localhost" +``` + +Then, start it: + +``` +docker-compose up -d +``` + +Finally, test load-balancing between the two servers `whoami1` and `whoami2`: ```bash -$ traefik --configFile=foo/bar/myconfigfile.toml -``` - -Træfɪk uses the following precedence order. Each item takes precedence over the item below it: - -- arguments -- configuration file -- default - -It means that arguments overrides configuration file. -Each argument is described in the help section: - -```bash -$ traefik --help -traefik is a modern HTTP reverse proxy and load balancer made to deploy microservices with ease. -Complete documentation is available at http://traefik.io - -Usage: - traefik [flags] - traefik [command] - -Available Commands: - version Print version - -Flags: - --accessLogsFile string Access logs file (default "log/access.log") - --boltdb Enable Boltdb backend - --boltdb.endpoint string Boltdb server endpoint (default "127.0.0.1:4001") - --boltdb.filename string Override default configuration template. For advanced users :) - --boltdb.prefix string Prefix used for KV store (default "/traefik") - --boltdb.watch Watch provider (default true) - -c, --configFile string Configuration file to use (TOML, JSON, YAML, HCL). - --consul Enable Consul backend - --consul.endpoint string Comma sepparated Consul server endpoints (default "127.0.0.1:8500") - --consul.filename string Override default configuration template. For advanced users :) - --consul.prefix string Prefix used for KV store (default "/traefik") - --consul.tls Enable Consul TLS support - --consul.tls.ca string TLS CA - --consul.tls.cert string TLS cert - --consul.tls.insecureSkipVerify TLS insecure skip verify - --consul.tls.key string TLS key - --consul.watch Watch provider (default true) - --consulCatalog Enable Consul catalog backend - --consulCatalog.domain string Default domain used - --consulCatalog.endpoint string Consul server endpoint (default "127.0.0.1:8500") - --defaultEntryPoints value Entrypoints to be used by frontends that do not specify any entrypoint (default &main.DefaultEntryPoints(nil)) - --docker Enable Docker backend - --docker.domain string Default domain used - --docker.endpoint string Docker server endpoint. Can be a tcp or a unix socket endpoint (default "unix:///var/run/docker.sock") - --docker.filename string Override default configuration template. For advanced users :) - --docker.tls Enable Docker TLS support - --docker.tls.ca string TLS CA - --docker.tls.cert string TLS cert - --docker.tls.insecureSkipVerify TLS insecure skip verify - --docker.tls.key string TLS key - --docker.watch Watch provider (default true) - --entryPoints value Entrypoints definition using format: --entryPoints='Name:http Address::8000 Redirect.EntryPoint:https' --entryPoints='Name:https Address::4442 TLS:tests/traefik.crt,tests/traefik.key' - --etcd Enable Etcd backend - --etcd.endpoint string Comma sepparated Etcd server endpoints (default "127.0.0.1:4001") - --etcd.filename string Override default configuration template. For advanced users :) - --etcd.prefix string Prefix used for KV store (default "/traefik") - --etcd.tls Enable Etcd TLS support - --etcd.tls.ca string TLS CA - --etcd.tls.cert string TLS cert - --etcd.tls.insecureSkipVerify TLS insecure skip verify - --etcd.tls.key string TLS key - --etcd.watch Watch provider (default true) - --file Enable File backend - --file.filename string Override default configuration template. For advanced users :) - --file.watch Watch provider (default true) - -g, --graceTimeOut string Timeout in seconds. Duration to give active requests a chance to finish during hot-reloads (default "10") - -l, --logLevel string Log level (default "ERROR") - --marathon Enable Marathon backend - --marathon.domain string Default domain used - --marathon.endpoint string Marathon server endpoint. You can also specify multiple endpoint for Marathon (default "http://127.0.0.1:8080") - --marathon.exposedByDefault Expose Marathon apps by default (default true) - --marathon.filename string Override default configuration template. For advanced users :) - --marathon.watch Watch provider (default true) - --maxIdleConnsPerHost int If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used - --providersThrottleDuration duration Backends throttle duration: minimum duration between 2 events from providers before applying a new configuration. It avoids unnecessary reloads if multiples events are sent in a short amount of time. (default 2s) - --traefikLogsFile string Traefik logs file (default "log/traefik.log") - --web Enable Web backend - --web.address string Web administration port (default ":8080") - --web.cerFile string SSL certificate - --web.keyFile string SSL certificate - --web.readOnly Enable read only API - --zookeeper Enable Zookeeper backend - --zookeeper.endpoint string Comma sepparated Zookeeper server endpoints (default "127.0.0.1:2181") - --zookeeper.filename string Override default configuration template. For advanced users :) - --zookeeper.prefix string Prefix used for KV store (default "/traefik") - --zookeeper.watch Watch provider (default true) - -Use "traefik [command] --help" for more information about a command. -``` - -## Global configuration - -```toml -# traefik.toml -################################################################ -# Global configuration -################################################################ - -# Timeout in seconds. -# Duration to give active requests a chance to finish during hot-reloads -# -# Optional -# Default: 10 -# -# graceTimeOut = 10 - -# Traefik logs file -# If not defined, logs to stdout -# -# Optional -# -# traefikLogsFile = "log/traefik.log" - -# Access logs file -# -# Optional -# -# accessLogsFile = "log/access.log" - -# Log level -# -# Optional -# Default: "ERROR" -# -# logLevel = "ERROR" - -# Backends throttle duration: minimum duration between 2 events from providers -# before applying a new configuration. It avoids unnecessary reloads if multiples events -# are sent in a short amount of time. -# -# Optional -# Default: "2s" -# -# ProvidersThrottleDuration = "5s" - -# If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used. -# If you encounter 'too many open files' errors, you can either change this value, or change `ulimit` value. -# -# Optional -# Default: http.DefaultMaxIdleConnsPerHost -# -# MaxIdleConnsPerHost = 200 - -# Entrypoints to be used by frontends that do not specify any entrypoint. -# Each frontend can specify its own entrypoints. -# -# Optional -# Default: ["http"] -# -# defaultEntryPoints = ["http", "https"] - -# Enable ACME (Let's Encrypt): automatic SSL -# -# Optional -# -# [acme] - -# Email address used for registration -# -# Required -# -# email = "test@traefik.io" - -# File used for certificates storage. -# WARNING, if you use Traefik in Docker, don't forget to mount this file as a volume. -# -# Required -# -# storageFile = "acme.json" - -# Entrypoint to proxy acme challenge to. -# WARNING, must point to an entrypoint on port 443 -# -# Required -# -# entryPoint = "https" - -# Enable on demand certificate. This will request a certificate from Let's Encrypt during the first TLS handshake for a hostname that does not yet have a certificate. -# WARNING, TLS handshakes will be slow when requesting a hostname certificate for the first time, this can leads to DoS attacks. -# WARNING, Take note that Let's Encrypt have rate limiting: https://community.letsencrypt.org/t/quick-start-guide/1631 -# -# Optional -# -# onDemand = true - -# CA server to use -# Uncomment the line to run on the staging let's encrypt server -# Leave comment to go to prod -# -# Optional -# -# caServer = "https://acme-staging.api.letsencrypt.org/directory" - -# Domains list -# You can provide SANs (alternative domains) to each main domain -# WARNING, Take note that Let's Encrypt have rate limiting: https://community.letsencrypt.org/t/quick-start-guide/1631 -# Each domain & SANs will lead to a certificate request. -# -# [[acme.domains]] -# main = "local1.com" -# sans = ["test1.local1.com", "test2.local1.com"] -# [[acme.domains]] -# main = "local2.com" -# sans = ["test1.local2.com", "test2x.local2.com"] -# [[acme.domains]] -# main = "local3.com" -# [[acme.domains]] -# main = "local4.com" - - -# Entrypoints definition -# -# Optional -# Default: -# [entryPoints] -# [entryPoints.http] -# address = ":80" -# -# To redirect an http entrypoint to an https entrypoint (with SNI support): -# [entryPoints] -# [entryPoints.http] -# address = ":80" -# [entryPoints.http.redirect] -# entryPoint = "https" -# [entryPoints.https] -# address = ":443" -# [entryPoints.https.tls] -# [[entryPoints.https.tls.certificates]] -# CertFile = "integration/fixtures/https/snitest.com.cert" -# KeyFile = "integration/fixtures/https/snitest.com.key" -# [[entryPoints.https.tls.certificates]] -# CertFile = "integration/fixtures/https/snitest.org.cert" -# KeyFile = "integration/fixtures/https/snitest.org.key" -# -# To redirect an entrypoint rewriting the URL: -# [entryPoints] -# [entryPoints.http] -# address = ":80" -# [entryPoints.http.redirect] -# regex = "^http://localhost/(.*)" -# replacement = "http://mydomain/$1" - -# Enable retry sending request if network error -# -# Optional -# -# [retry] - -# Number of attempts -# -# Optional -# Default: (number servers in backend) -1 -# -# attempts = 3 - -# Sets the maximum request body to be stored in memory in Mo -# -# Optional -# Default: 2 -# -# maxMem = 3 -``` - -### Samples - -#### HTTP only - -``` -defaultEntryPoints = ["http"] -[entryPoints] - [entryPoints.http] - address = ":80" -``` - -### HTTP + HTTPS (with SNI) - -``` -defaultEntryPoints = ["http", "https"] -[entryPoints] - [entryPoints.http] - address = ":80" - [entryPoints.https] - address = ":443" - [entryPoints.https.tls] - [[entryPoints.https.tls.certificates]] - CertFile = "integration/fixtures/https/snitest.com.cert" - KeyFile = "integration/fixtures/https/snitest.com.key" - [[entryPoints.https.tls.certificates]] - CertFile = "integration/fixtures/https/snitest.org.cert" - KeyFile = "integration/fixtures/https/snitest.org.key" -``` - -### HTTP redirect on HTTPS - -``` -defaultEntryPoints = ["http", "https"] -[entryPoints] - [entryPoints.http] - address = ":80" - [entryPoints.http.redirect] - entryPoint = "https" - [entryPoints.https] - address = ":443" - [entryPoints.https.tls] - [[entryPoints.https.tls.certificates]] - certFile = "tests/traefik.crt" - keyFile = "tests/traefik.key" -``` - -### Let's Encrypt support - -``` -[entryPoints] - [entryPoints.https] - address = ":443" - [entryPoints.https.tls] - # certs used as default certs - [[entryPoints.https.tls.certificates]] - certFile = "tests/traefik.crt" - keyFile = "tests/traefik.key" -[acme] -email = "test@traefik.io" -storageFile = "acme.json" -onDemand = true -caServer = "http://172.18.0.1:4000/directory" -entryPoint = "https" - -[[acme.domains]] - main = "local1.com" - sans = ["test1.local1.com", "test2.local1.com"] -[[acme.domains]] - main = "local2.com" - sans = ["test1.local2.com", "test2x.local2.com"] -[[acme.domains]] - main = "local3.com" -[[acme.domains]] - main = "local4.com" -``` - -### Override entrypoints in frontends - -``` -[frontends] - [frontends.frontend1] - backend = "backend2" - [frontends.frontend1.routes.test_1] - rule = "Host:test.localhost" - [frontends.frontend2] - backend = "backend1" - passHostHeader = true - entrypoints = ["https"] # overrides defaultEntryPoints - [frontends.frontend2.routes.test_1] - rule = "Host:{subdomain:[a-z]+}.localhost" - [frontends.frontend3] - entrypoints = ["http", "https"] # overrides defaultEntryPoints - backend = "backend2" - rule = "Path:/test" -``` - - -## File backend - -Like any other reverse proxy, Træfɪk can be configured with a file. You have two choices: - -- simply add your configuration at the end of the global configuration file `traefik.toml` : - -```toml -# traefik.toml -defaultEntryPoints = ["http", "https"] -[entryPoints] - [entryPoints.http] - address = ":80" - [entryPoints.http.redirect] - entryPoint = "https" - [entryPoints.https] - address = ":443" - [entryPoints.https.tls] - [[entryPoints.https.tls.certificates]] - CertFile = "integration/fixtures/https/snitest.com.cert" - KeyFile = "integration/fixtures/https/snitest.com.key" - [[entryPoints.https.tls.certificates]] - CertFile = "integration/fixtures/https/snitest.org.cert" - KeyFile = "integration/fixtures/https/snitest.org.key" -graceTimeOut = 10 -logLevel = "DEBUG" - -[file] - -# rules -[backends] - [backends.backend1] - [backends.backend1.circuitbreaker] - expression = "NetworkErrorRatio() > 0.5" - [backends.backend1.servers.server1] - url = "http://172.17.0.2:80" - weight = 10 - [backends.backend1.servers.server2] - url = "http://172.17.0.3:80" - weight = 1 - [backends.backend2] - [backends.backend2.LoadBalancer] - method = "drr" - [backends.backend2.servers.server1] - url = "http://172.17.0.4:80" - weight = 1 - [backends.backend2.servers.server2] - url = "http://172.17.0.5:80" - weight = 2 - -[frontends] - [frontends.frontend1] - backend = "backend2" - [frontends.frontend1.routes.test_1] - rule = "Host:test.localhost" - [frontends.frontend2] - backend = "backend1" - passHostHeader = true - entrypoints = ["https"] # overrides defaultEntryPoints - [frontends.frontend2.routes.test_1] - rule = "Host:{subdomain:[a-z]+}.localhost" - [frontends.frontend3] - entrypoints = ["http", "https"] # overrides defaultEntryPoints - backend = "backend2" - rule = "Path:/test" -``` - -- or put your rules in a separate file, for example `rules.tml`: - -```toml -# traefik.toml -[entryPoints] - [entryPoints.http] - address = ":80" - [entryPoints.http.redirect] - entryPoint = "https" - [entryPoints.https] - address = ":443" - [entryPoints.https.tls] - [[entryPoints.https.tls.certificates]] - CertFile = "integration/fixtures/https/snitest.com.cert" - KeyFile = "integration/fixtures/https/snitest.com.key" - [[entryPoints.https.tls.certificates]] - CertFile = "integration/fixtures/https/snitest.org.cert" - KeyFile = "integration/fixtures/https/snitest.org.key" -graceTimeOut = 10 -logLevel = "DEBUG" - -[file] -filename = "rules.toml" -``` - -```toml -# rules.toml -[backends] - [backends.backend1] - [backends.backend1.circuitbreaker] - expression = "NetworkErrorRatio() > 0.5" - [backends.backend1.servers.server1] - url = "http://172.17.0.2:80" - weight = 10 - [backends.backend1.servers.server2] - url = "http://172.17.0.3:80" - weight = 1 - [backends.backend2] - [backends.backend2.LoadBalancer] - method = "drr" - [backends.backend2.servers.server1] - url = "http://172.17.0.4:80" - weight = 1 - [backends.backend2.servers.server2] - url = "http://172.17.0.5:80" - weight = 2 - -[frontends] - [frontends.frontend1] - backend = "backend2" - [frontends.frontend1.routes.test_1] - rule = "Host:test.localhost" - [frontends.frontend2] - backend = "backend1" - passHostHeader = true - entrypoints = ["https"] # overrides defaultEntryPoints - [frontends.frontend2.routes.test_1] - rule = "Host:{subdomain:[a-z]+}.localhost" - [frontends.frontend3] - entrypoints = ["http", "https"] # overrides defaultEntryPoints - backend = "backend2" - rule = "Path:/test" -``` - -If you want Træfɪk to watch file changes automatically, just add: - -```toml -[file] -watch = true -``` - -## API backend - -Træfik can be configured using a restful api. -To enable it: - -```toml -[web] -address = ":8080" - -# SSL certificate and key used -# -# Optional -# -# CertFile = "traefik.crt" -# KeyFile = "traefik.key" -# -# Set REST API to read-only mode -# -# Optional -# ReadOnly = false -``` - -- `/`: provides a simple HTML frontend of Træfik - -![Web UI Providers](img/web.frontend.png) -![Web UI Health](img/traefik-health.png) - -- `/health`: `GET` json metrics - -```sh -$ curl -s "http://localhost:8080/health" | jq . -{ - // Træfɪk PID - "pid": 2458, - // Træfɪk server uptime (formated time) - "uptime": "39m6.885931127s", - // Træfɪk server uptime in seconds - "uptime_sec": 2346.885931127, - // current server date - "time": "2015-10-07 18:32:24.362238909 +0200 CEST", - // current server date in seconds - "unixtime": 1444235544, - // count HTTP response status code in realtime - "status_code_count": { - "502": 1 - }, - // count HTTP response status code since Træfɪk started - "total_status_code_count": { - "200": 7, - "404": 21, - "502": 13 - }, - // count HTTP response - "count": 1, - // count HTTP response - "total_count": 41, - // sum of all response time (formated time) - "total_response_time": "35.456865605s", - // sum of all response time in seconds - "total_response_time_sec": 35.456865605, - // average response time (formated time) - "average_response_time": "864.8016ms", - // average response time in seconds - "average_response_time_sec": 0.8648016000000001 -} -``` - -- `/api`: `GET` configuration for all providers - -```sh -$ curl -s "http://localhost:8080/api" | jq . -{ - "file": { - "frontends": { - "frontend2": { - "routes": { - "test_2": { - "rule": "Path:/test" - } - }, - "backend": "backend1" - }, - "frontend1": { - "routes": { - "test_1": { - "rule": "Host:test.localhost" - } - }, - "backend": "backend2" - } - }, - "backends": { - "backend2": { - "loadBalancer": { - "method": "drr" - }, - "servers": { - "server2": { - "weight": 2, - "URL": "http://172.17.0.5:80" - }, - "server1": { - "weight": 1, - "url": "http://172.17.0.4:80" - } - } - }, - "backend1": { - "loadBalancer": { - "method": "wrr" - }, - "circuitBreaker": { - "expression": "NetworkErrorRatio() > 0.5" - }, - "servers": { - "server2": { - "weight": 1, - "url": "http://172.17.0.3:80" - }, - "server1": { - "weight": 10, - "url": "http://172.17.0.2:80" - } - } - } - } - } -} -``` - -- `/api/providers`: `GET` providers -- `/api/providers/{provider}`: `GET` or `PUT` provider -- `/api/providers/{provider}/backends`: `GET` backends -- `/api/providers/{provider}/backends/{backend}`: `GET` a backend -- `/api/providers/{provider}/backends/{backend}/servers`: `GET` servers in a backend -- `/api/providers/{provider}/backends/{backend}/servers/{server}`: `GET` a server in a backend -- `/api/providers/{provider}/frontends`: `GET` frontends -- `/api/providers/{provider}/frontends/{frontend}`: `GET` a frontend -- `/api/providers/{provider}/frontends/{frontend}/routes`: `GET` routes in a frontend -- `/api/providers/{provider}/frontends/{frontend}/routes/{route}`: `GET` a route in a frontend - - -## Docker backend - -Træfɪk can be configured to use Docker as a backend configuration: - -```toml -################################################################ -# Docker configuration backend -################################################################ - -# Enable Docker configuration backend -# -# Optional -# -[docker] - -# Docker server endpoint. Can be a tcp or a unix socket endpoint. -# -# Required -# -endpoint = "unix:///var/run/docker.sock" - -# Default domain used. -# Can be overridden by setting the "traefik.domain" label on a container. -# -# Required -# -domain = "docker.localhost" - -# Enable watch docker changes -# -# Optional -# -watch = true - -# Override default configuration template. For advanced users :) -# -# Optional -# -# filename = "docker.tmpl" - -# Enable docker TLS connection -# -# [docker.tls] -# ca = "/etc/ssl/ca.crt" -# cert = "/etc/ssl/docker.crt" -# key = "/etc/ssl/docker.key" -# insecureskipverify = true -``` - -Labels can be used on containers to override default behaviour: - -- `traefik.backend=foo`: assign the container to `foo` backend -- `traefik.port=80`: register this port. Useful when the container exposes multiples ports. -- `traefik.protocol=https`: override the default `http` protocol -- `traefik.weight=10`: assign this weight to the container -- `traefik.enable=false`: disable this container in Træfɪk -- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`). See [frontends](#frontends). -- `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend. -- `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`. -* `traefik.domain=traefik.localhost`: override the default domain - - -## Marathon backend - -Træfɪk can be configured to use Marathon as a backend configuration: - - -```toml -################################################################ -# Mesos/Marathon configuration backend -################################################################ - -# Enable Marathon configuration backend -# -# Optional -# -[marathon] - -# Marathon server endpoint. -# You can also specify multiple endpoint for Marathon: -# endpoint := "http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080" -# -# Required -# -endpoint = "http://127.0.0.1:8080" - -# Enable watch Marathon changes -# -# Optional -# -watch = true - -# Default domain used. -# Can be overridden by setting the "traefik.domain" label on an application. -# -# Required -# -domain = "marathon.localhost" - -# Override default configuration template. For advanced users :) -# -# Optional -# -# filename = "marathon.tmpl" - -# Expose Marathon apps by default in traefik -# -# Optional -# Default: false -# -# ExposedByDefault = true - -# Enable Marathon basic authentication -# -# Optional -# -# [marathon.basic] -# httpBasicAuthUser = "foo" -# httpBasicPassword = "bar" - -# TLS client configuration. https://golang.org/pkg/crypto/tls/#Config -# -# Optional -# -# [marathon.TLS] -# InsecureSkipVerify = true -``` - -Labels can be used on containers to override default behaviour: - -- `traefik.backend=foo`: assign the application to `foo` backend -- `traefik.portIndex=1`: register port by index in the application's ports array. Useful when the application exposes multiple ports. -- `traefik.port=80`: register the explicit application port value. Cannot be used alongside `traefik.portIndex`. -- `traefik.protocol=https`: override the default `http` protocol -- `traefik.weight=10`: assign this weight to the application -- `traefik.enable=false`: disable this application in Træfɪk -- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`). See [frontends](#frontends). -- `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend. -- `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`. -* `traefik.domain=traefik.localhost`: override the default domain - -## Consul backend - -Træfɪk can be configured to use Consul as a backend configuration: - -```toml -################################################################ -# Consul KV configuration backend -################################################################ - -# Enable Consul KV configuration backend -# -# Optional -# -[consul] - -# Consul server endpoint -# -# Required -# -endpoint = "127.0.0.1:8500" - -# Enable watch Consul changes -# -# Optional -# -watch = true - -# Prefix used for KV store. -# -# Optional -# -prefix = "traefik" - -# Override default configuration template. For advanced users :) -# -# Optional -# -# filename = "consul.tmpl" - -# Enable consul TLS connection -# -# Optional -# -# [consul.tls] -# ca = "/etc/ssl/ca.crt" -# cert = "/etc/ssl/consul.crt" -# key = "/etc/ssl/consul.key" -# insecureskipverify = true -``` - -Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. - -## Consul catalog backend - -Træfɪk can be configured to use service discovery catalog of Consul as a backend configuration: - -```toml -################################################################ -# Consul Catalog configuration backend -################################################################ - -# Enable Consul Catalog configuration backend -# -# Optional -# -[consulCatalog] - -# Consul server endpoint -# -# Required -# -endpoint = "127.0.0.1:8500" - -# Default domain used. -# -# Optional -# -domain = "consul.localhost" -``` - -This backend will create routes matching on hostname based on the service name -used in consul. - - -## Etcd backend - -Træfɪk can be configured to use Etcd as a backend configuration: - -```toml -################################################################ -# Etcd configuration backend -################################################################ - -# Enable Etcd configuration backend -# -# Optional -# -# [etcd] - -# Etcd server endpoint -# -# Required -# -# endpoint = "127.0.0.1:4001" - -# Enable watch Etcd changes -# -# Optional -# -# watch = true - -# Prefix used for KV store. -# -# Optional -# -# prefix = "/traefik" - -# Override default configuration template. For advanced users :) -# -# Optional -# -# filename = "etcd.tmpl" - -# Enable etcd TLS connection -# -# Optional -# -# [etcd.tls] -# ca = "/etc/ssl/ca.crt" -# cert = "/etc/ssl/etcd.crt" -# key = "/etc/ssl/etcd.key" -# insecureskipverify = true -``` - -Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. - - -## Zookeeper backend - -Træfɪk can be configured to use Zookeeper as a backend configuration: - -```toml -################################################################ -# Zookeeper configuration backend -################################################################ - -# Enable Zookeeperconfiguration backend -# -# Optional -# -# [zookeeper] - -# Zookeeper server endpoint -# -# Required -# -# endpoint = "127.0.0.1:2181" - -# Enable watch Zookeeper changes -# -# Optional -# -# watch = true - -# Prefix used for KV store. -# -# Optional -# -# prefix = "/traefik" - -# Override default configuration template. For advanced users :) -# -# Optional -# -# filename = "zookeeper.tmpl" -``` - -Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. - -## BoltDB backend - -Træfɪk can be configured to use BoltDB as a backend configuration: - -```toml -################################################################ -# BoltDB configuration backend -################################################################ - -# Enable BoltDB configuration backend -# -# Optional -# -# [boltdb] - -# BoltDB file -# -# Required -# -# endpoint = "/my.db" - -# Enable watch BoltDB changes -# -# Optional -# -# watch = true - -# Prefix used for KV store. -# -# Optional -# -# prefix = "/traefik" - -# Override default configuration template. For advanced users :) -# -# Optional -# -# filename = "boltdb.tmpl" -``` - -Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. - -## Key-value storage structure - -The Keys-Values structure should look (using `prefix = "/traefik"`): - -- backend 1 - -| Key | Value | -|--------------------------------------------------------|-----------------------------| -| `/traefik/backends/backend1/circuitbreaker/expression` | `NetworkErrorRatio() > 0.5` | -| `/traefik/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | -| `/traefik/backends/backend1/servers/server1/weight` | `10` | -| `/traefik/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` | -| `/traefik/backends/backend1/servers/server2/weight` | `1` | - -- backend 2 - -| Key | Value | -|-----------------------------------------------------|------------------------| -| `/traefik/backends/backend2/loadbalancer/method` | `drr` | -| `/traefik/backends/backend2/servers/server1/url` | `http://172.17.0.4:80` | -| `/traefik/backends/backend2/servers/server1/weight` | `1` | -| `/traefik/backends/backend2/servers/server2/url` | `http://172.17.0.5:80` | -| `/traefik/backends/backend2/servers/server2/weight` | `2` | - -- frontend 1 - -| Key | Value | -|---------------------------------------------------|-----------------------| -| `/traefik/frontends/frontend1/backend` | `backend2` | -| `/traefik/frontends/frontend1/routes/test_1/rule` | `Host:test.localhost` | - -- frontend 2 - -| Key | Value | -|----------------------------------------------------|--------------| -| `/traefik/frontends/frontend2/backend` | `backend1` | -| `/traefik/frontends/frontend2/passHostHeader` | `true` | -| `/traefik/frontends/frontend2/entrypoints` | `http,https` | -| `/traefik/frontends/frontend2/routes/test_2/rule` | `Path:/test` | - -## Atomic configuration changes - -The [Etcd](https://github.com/coreos/etcd/issues/860) and [Consul](https://github.com/hashicorp/consul/issues/886) backends do not support updating multiple keys atomically. As a result, it may be possible for Træfɪk to read an intermediate configuration state despite judicious use of the `--providersThrottleDuration` flag. To solve this problem, Træfɪk supports a special key called `/traefik/alias`. If set, Træfɪk use the value as an alternative key prefix. - -Given the key structure below, Træfɪk will use the `http://172.17.0.2:80` as its only backend (frontend keys have been omitted for brevity). - -| Key | Value | -|-------------------------------------------------------------------------|-----------------------------| -| `/traefik/alias` | `/traefik_configurations/1` | -| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | -| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` | - -When an atomic configuration change is required, you may write a new configuration at an alternative prefix. Here, although the `/traefik_configurations/2/...` keys have been set, the old configuration is still active because the `/traefik/alias` key still points to `/traefik_configurations/1`: - -| Key | Value | -|-------------------------------------------------------------------------|-----------------------------| -| `/traefik/alias` | `/traefik_configurations/1` | -| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | -| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` | -| `/traefik_configurations/2/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | -| `/traefik_configurations/2/backends/backend1/servers/server1/weight` | `5` | -| `/traefik_configurations/2/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` | -| `/traefik_configurations/2/backends/backend1/servers/server2/weight` | `5` | - -Once the `/traefik/alias` key is updated, the new `/traefik_configurations/2` configuration becomes active atomically. Here, we have a 50% balance between the `http://172.17.0.3:80` and the `http://172.17.0.4:80` hosts while no traffic is sent to the `172.17.0.2:80` host: - -| Key | Value | -|-------------------------------------------------------------------------|-----------------------------| -| `/traefik/alias` | `/traefik_configurations/2` | -| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | -| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` | -| `/traefik_configurations/2/backends/backend1/servers/server1/url` | `http://172.17.0.3:80` | -| `/traefik_configurations/2/backends/backend1/servers/server1/weight` | `5` | -| `/traefik_configurations/2/backends/backend1/servers/server2/url` | `http://172.17.0.4:80` | -| `/traefik_configurations/2/backends/backend1/servers/server2/weight` | `5` | - -Note that Træfɪk *will not watch for key changes in the `/traefik_configurations` prefix*. It will only watch for changes in the `/traefik` prefix. Further, if the `/traefik/alias` key is set, all other sibling keys with the `/traefik` prefix are ignored. - - -## Benchmarks - -Here are some early Benchmarks between Nginx, HA-Proxy and Træfɪk acting as simple load balancers between two servers. - -- Nginx: - -```sh -$ docker run -d -e VIRTUAL_HOST=test.nginx.localhost emilevauge/whoami -$ docker run -d -e VIRTUAL_HOST=test.nginx.localhost emilevauge/whoami -$ docker run --log-driver=none -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy -$ wrk -t12 -c400 -d60s -H "Host: test.nginx.localhost" --latency http://127.0.0.1:80 -Running 1m test @ http://127.0.0.1:80 - 12 threads and 400 connections - Thread Stats Avg Stdev Max +/- Stdev - Latency 162.61ms 203.34ms 1.72s 91.07% - Req/Sec 277.57 107.67 790.00 67.53% - Latency Distribution - 50% 128.19ms - 75% 218.22ms - 90% 342.12ms - 99% 1.08s - 197991 requests in 1.00m, 82.32MB read - Socket errors: connect 0, read 0, write 0, timeout 18 -Requests/sec: 3296.04 -Transfer/sec: 1.37MB -``` - -- HA-Proxy: - -``` -$ docker run -d --name web1 -e VIRTUAL_HOST=test.haproxy.localhost emilevauge/whoami -$ docker run -d --name web2 -e VIRTUAL_HOST=test.haproxy.localhost emilevauge/whoami -$ docker run -d -p 80:80 --link web1:web1 --link web2:web2 dockercloud/haproxy -$ wrk -t12 -c400 -d60s -H "Host: test.haproxy.localhost" --latency http://127.0.0.1:80 -Running 1m test @ http://127.0.0.1:80 - 12 threads and 400 connections - Thread Stats Avg Stdev Max +/- Stdev - Latency 158.08ms 187.88ms 1.75s 89.61% - Req/Sec 281.33 120.47 0.98k 65.88% - Latency Distribution - 50% 121.77ms - 75% 227.10ms - 90% 351.98ms - 99% 1.01s - 200462 requests in 1.00m, 59.65MB read -Requests/sec: 3337.66 -Transfer/sec: 0.99MB -``` - -- Træfɪk: - -```sh -$ docker run -d -l traefik.backend=test1 -l traefik.frontend.rule=Host -l traefik.frontend.value=test.traefik.localhost emilevauge/whoami -$ docker run -d -l traefik.backend=test1 -l traefik.frontend.rule=Host -l traefik.frontend.value=test.traefik.localhost emilevauge/whoami -$ docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.toml:/traefik.toml -v /var/run/docker.sock:/var/run/docker.sock containous/traefik -$ wrk -t12 -c400 -d60s -H "Host: test.traefik.localhost" --latency http://127.0.0.1:80 -Running 1m test @ http://127.0.0.1:80 - 12 threads and 400 connections - Thread Stats Avg Stdev Max +/- Stdev - Latency 132.93ms 121.89ms 1.20s 66.62% - Req/Sec 280.95 104.88 740.00 68.26% - Latency Distribution - 50% 128.71ms - 75% 214.15ms - 90% 281.45ms - 99% 498.44ms - 200734 requests in 1.00m, 80.02MB read -Requests/sec: 3340.13 -Transfer/sec: 1.33MB +$ curl -H Host:whoami.docker.localhost http://127.0.0.1 +Hostname: ef194d07634a +IP: 127.0.0.1 +IP: ::1 +IP: 172.17.0.4 +IP: fe80::42:acff:fe11:4 +GET / HTTP/1.1 +Host: 172.17.0.4:80 +User-Agent: curl/7.35.0 +Accept: */* +Accept-Encoding: gzip +X-Forwarded-For: 172.17.0.1 +X-Forwarded-Host: 172.17.0.4:80 +X-Forwarded-Proto: http +X-Forwarded-Server: dbb60406010d + +$ curl -H Host:whoami.docker.localhost http://127.0.0.1 +Hostname: 6c3c5df0c79a +IP: 127.0.0.1 +IP: ::1 +IP: 172.17.0.3 +IP: fe80::42:acff:fe11:3 +GET / HTTP/1.1 +Host: 172.17.0.3:80 +User-Agent: curl/7.35.0 +Accept: */* +Accept-Encoding: gzip +X-Forwarded-For: 172.17.0.1 +X-Forwarded-Host: 172.17.0.3:80 +X-Forwarded-Proto: http +X-Forwarded-Server: dbb60406010d ``` diff --git a/docs/toml.md b/docs/toml.md new file mode 100644 index 000000000..2dd786bfc --- /dev/null +++ b/docs/toml.md @@ -0,0 +1,994 @@ + +# Global configuration + +## Main section + +```toml +# traefik.toml +################################################################ +# Global configuration +################################################################ + +# Traefik logs file +# If not defined, logs to stdout +# +# Optional +# +# traefikLogsFile = "log/traefik.log" + +# Access logs file +# +# Optional +# +# accessLogsFile = "log/access.log" + +# Log level +# +# Optional +# Default: "ERROR" +# +# logLevel = "ERROR" + +# Backends throttle duration: minimum duration between 2 events from providers +# before applying a new configuration. It avoids unnecessary reloads if multiples events +# are sent in a short amount of time. +# +# Optional +# Default: "2s" +# +# ProvidersThrottleDuration = "5s" + +# If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used. +# If you encounter 'too many open files' errors, you can either change this value, or change `ulimit` value. +# +# Optional +# Default: http.DefaultMaxIdleConnsPerHost +# +# MaxIdleConnsPerHost = 200 + +# Entrypoints to be used by frontends that do not specify any entrypoint. +# Each frontend can specify its own entrypoints. +# +# Optional +# Default: ["http"] +# +# defaultEntryPoints = ["http", "https"] +``` + +## Entrypoints definition + +```toml +# Entrypoints definition +# +# Optional +# Default: +# [entryPoints] +# [entryPoints.http] +# address = ":80" +# +# To redirect an http entrypoint to an https entrypoint (with SNI support): +# [entryPoints] +# [entryPoints.http] +# address = ":80" +# [entryPoints.http.redirect] +# entryPoint = "https" +# [entryPoints.https] +# address = ":443" +# [entryPoints.https.tls] +# [[entryPoints.https.tls.certificates]] +# CertFile = "integration/fixtures/https/snitest.com.cert" +# KeyFile = "integration/fixtures/https/snitest.com.key" +# [[entryPoints.https.tls.certificates]] +# CertFile = "integration/fixtures/https/snitest.org.cert" +# KeyFile = "integration/fixtures/https/snitest.org.key" +# +# To redirect an entrypoint rewriting the URL: +# [entryPoints] +# [entryPoints.http] +# address = ":80" +# [entryPoints.http.redirect] +# regex = "^http://localhost/(.*)" +# replacement = "http://mydomain/$1" +``` + +## Retry configuration + +```toml +# Enable retry sending request if network error +# +# Optional +# +# [retry] + +# Number of attempts +# +# Optional +# Default: (number servers in backend) -1 +# +# attempts = 3 + +# Sets the maximum request body to be stored in memory in Mo +# +# Optional +# Default: 2 +# +# maxMem = 3 +``` + +## ACME (Let's Encrypt) configuration + +```toml +# Enable ACME (Let's Encrypt): automatic SSL +# +# Optional +# +# [acme] + +# Email address used for registration +# +# Required +# +# email = "test@traefik.io" + +# File used for certificates storage. +# WARNING, if you use Traefik in Docker, don't forget to mount this file as a volume. +# +# Required +# +# storageFile = "acme.json" + +# Entrypoint to proxy acme challenge to. +# WARNING, must point to an entrypoint on port 443 +# +# Required +# +# entryPoint = "https" + +# Enable on demand certificate. This will request a certificate from Let's Encrypt during the first TLS handshake for a hostname that does not yet have a certificate. +# WARNING, TLS handshakes will be slow when requesting a hostname certificate for the first time, this can leads to DoS attacks. +# WARNING, Take note that Let's Encrypt have rate limiting: https://community.letsencrypt.org/t/quick-start-guide/1631 +# +# Optional +# +# onDemand = true + +# CA server to use +# Uncomment the line to run on the staging let's encrypt server +# Leave comment to go to prod +# +# Optional +# +# caServer = "https://acme-staging.api.letsencrypt.org/directory" + +# Domains list +# You can provide SANs (alternative domains) to each main domain +# WARNING, Take note that Let's Encrypt have rate limiting: https://community.letsencrypt.org/t/quick-start-guide/1631 +# Each domain & SANs will lead to a certificate request. +# +# [[acme.domains]] +# main = "local1.com" +# sans = ["test1.local1.com", "test2.local1.com"] +# [[acme.domains]] +# main = "local2.com" +# sans = ["test1.local2.com", "test2x.local2.com"] +# [[acme.domains]] +# main = "local3.com" +# [[acme.domains]] +# main = "local4.com" +``` + +# Configuration backends + +## File backend + +Like any other reverse proxy, Træfɪk can be configured with a file. You have two choices: + +- simply add your configuration at the end of the global configuration file `traefik.toml` : + +```toml +# traefik.toml +logLevel = "DEBUG" +defaultEntryPoints = ["http", "https"] +[entryPoints] + [entryPoints.http] + address = ":80" + [entryPoints.http.redirect] + entryPoint = "https" + [entryPoints.https] + address = ":443" + [entryPoints.https.tls] + [[entryPoints.https.tls.certificates]] + CertFile = "integration/fixtures/https/snitest.com.cert" + KeyFile = "integration/fixtures/https/snitest.com.key" + [[entryPoints.https.tls.certificates]] + CertFile = "integration/fixtures/https/snitest.org.cert" + KeyFile = "integration/fixtures/https/snitest.org.key" + +[file] + +# rules +[backends] + [backends.backend1] + [backends.backend1.circuitbreaker] + expression = "NetworkErrorRatio() > 0.5" + [backends.backend1.servers.server1] + url = "http://172.17.0.2:80" + weight = 10 + [backends.backend1.servers.server2] + url = "http://172.17.0.3:80" + weight = 1 + [backends.backend2] + [backends.backend2.LoadBalancer] + method = "drr" + [backends.backend2.servers.server1] + url = "http://172.17.0.4:80" + weight = 1 + [backends.backend2.servers.server2] + url = "http://172.17.0.5:80" + weight = 2 + +[frontends] + [frontends.frontend1] + backend = "backend2" + [frontends.frontend1.routes.test_1] + rule = "Host:test.localhost" + [frontends.frontend2] + backend = "backend1" + passHostHeader = true + entrypoints = ["https"] # overrides defaultEntryPoints + [frontends.frontend2.routes.test_1] + rule = "Host:{subdomain:[a-z]+}.localhost" + [frontends.frontend3] + entrypoints = ["http", "https"] # overrides defaultEntryPoints + backend = "backend2" + rule = "Path:/test" +``` + +- or put your rules in a separate file, for example `rules.tml`: + +```toml +# traefik.toml +logLevel = "DEBUG" +[entryPoints] + [entryPoints.http] + address = ":80" + [entryPoints.http.redirect] + entryPoint = "https" + [entryPoints.https] + address = ":443" + [entryPoints.https.tls] + [[entryPoints.https.tls.certificates]] + CertFile = "integration/fixtures/https/snitest.com.cert" + KeyFile = "integration/fixtures/https/snitest.com.key" + [[entryPoints.https.tls.certificates]] + CertFile = "integration/fixtures/https/snitest.org.cert" + KeyFile = "integration/fixtures/https/snitest.org.key" + +[file] +filename = "rules.toml" +``` + +```toml +# rules.toml +[backends] + [backends.backend1] + [backends.backend1.circuitbreaker] + expression = "NetworkErrorRatio() > 0.5" + [backends.backend1.servers.server1] + url = "http://172.17.0.2:80" + weight = 10 + [backends.backend1.servers.server2] + url = "http://172.17.0.3:80" + weight = 1 + [backends.backend2] + [backends.backend2.LoadBalancer] + method = "drr" + [backends.backend2.servers.server1] + url = "http://172.17.0.4:80" + weight = 1 + [backends.backend2.servers.server2] + url = "http://172.17.0.5:80" + weight = 2 + +[frontends] + [frontends.frontend1] + backend = "backend2" + [frontends.frontend1.routes.test_1] + rule = "Host:test.localhost" + [frontends.frontend2] + backend = "backend1" + passHostHeader = true + entrypoints = ["https"] # overrides defaultEntryPoints + [frontends.frontend2.routes.test_1] + rule = "Host:{subdomain:[a-z]+}.localhost" + [frontends.frontend3] + entrypoints = ["http", "https"] # overrides defaultEntryPoints + backend = "backend2" + rule = "Path:/test" +``` + +If you want Træfɪk to watch file changes automatically, just add: + +```toml +[file] +watch = true +``` + +## API backend + +Træfik can be configured using a restful api. +To enable it: + +```toml +[web] +address = ":8080" + +# SSL certificate and key used +# +# Optional +# +# CertFile = "traefik.crt" +# KeyFile = "traefik.key" +# +# Set REST API to read-only mode +# +# Optional +# ReadOnly = false +``` + +- `/`: provides a simple HTML frontend of Træfik + +![Web UI Providers](img/web.frontend.png) +![Web UI Health](img/traefik-health.png) + +- `/health`: `GET` json metrics + +```sh +$ curl -s "http://localhost:8080/health" | jq . +{ + // Træfɪk PID + "pid": 2458, + // Træfɪk server uptime (formated time) + "uptime": "39m6.885931127s", + // Træfɪk server uptime in seconds + "uptime_sec": 2346.885931127, + // current server date + "time": "2015-10-07 18:32:24.362238909 +0200 CEST", + // current server date in seconds + "unixtime": 1444235544, + // count HTTP response status code in realtime + "status_code_count": { + "502": 1 + }, + // count HTTP response status code since Træfɪk started + "total_status_code_count": { + "200": 7, + "404": 21, + "502": 13 + }, + // count HTTP response + "count": 1, + // count HTTP response + "total_count": 41, + // sum of all response time (formated time) + "total_response_time": "35.456865605s", + // sum of all response time in seconds + "total_response_time_sec": 35.456865605, + // average response time (formated time) + "average_response_time": "864.8016ms", + // average response time in seconds + "average_response_time_sec": 0.8648016000000001 +} +``` + +- `/api`: `GET` configuration for all providers + +```sh +$ curl -s "http://localhost:8080/api" | jq . +{ + "file": { + "frontends": { + "frontend2": { + "routes": { + "test_2": { + "rule": "Path:/test" + } + }, + "backend": "backend1" + }, + "frontend1": { + "routes": { + "test_1": { + "rule": "Host:test.localhost" + } + }, + "backend": "backend2" + } + }, + "backends": { + "backend2": { + "loadBalancer": { + "method": "drr" + }, + "servers": { + "server2": { + "weight": 2, + "URL": "http://172.17.0.5:80" + }, + "server1": { + "weight": 1, + "url": "http://172.17.0.4:80" + } + } + }, + "backend1": { + "loadBalancer": { + "method": "wrr" + }, + "circuitBreaker": { + "expression": "NetworkErrorRatio() > 0.5" + }, + "servers": { + "server2": { + "weight": 1, + "url": "http://172.17.0.3:80" + }, + "server1": { + "weight": 10, + "url": "http://172.17.0.2:80" + } + } + } + } + } +} +``` + +- `/api/providers`: `GET` providers +- `/api/providers/{provider}`: `GET` or `PUT` provider +- `/api/providers/{provider}/backends`: `GET` backends +- `/api/providers/{provider}/backends/{backend}`: `GET` a backend +- `/api/providers/{provider}/backends/{backend}/servers`: `GET` servers in a backend +- `/api/providers/{provider}/backends/{backend}/servers/{server}`: `GET` a server in a backend +- `/api/providers/{provider}/frontends`: `GET` frontends +- `/api/providers/{provider}/frontends/{frontend}`: `GET` a frontend +- `/api/providers/{provider}/frontends/{frontend}/routes`: `GET` routes in a frontend +- `/api/providers/{provider}/frontends/{frontend}/routes/{route}`: `GET` a route in a frontend + + +## Docker backend + +Træfɪk can be configured to use Docker as a backend configuration: + +```toml +################################################################ +# Docker configuration backend +################################################################ + +# Enable Docker configuration backend +# +# Optional +# +[docker] + +# Docker server endpoint. Can be a tcp or a unix socket endpoint. +# +# Required +# +endpoint = "unix:///var/run/docker.sock" + +# Default domain used. +# Can be overridden by setting the "traefik.domain" label on a container. +# +# Required +# +domain = "docker.localhost" + +# Enable watch docker changes +# +# Optional +# +watch = true + +# Override default configuration template. For advanced users :) +# +# Optional +# +# filename = "docker.tmpl" + +# Enable docker TLS connection +# +# [docker.tls] +# ca = "/etc/ssl/ca.crt" +# cert = "/etc/ssl/docker.crt" +# key = "/etc/ssl/docker.key" +# insecureskipverify = true +``` + +Labels can be used on containers to override default behaviour: + +- `traefik.backend=foo`: assign the container to `foo` backend +- `traefik.port=80`: register this port. Useful when the container exposes multiples ports. +- `traefik.protocol=https`: override the default `http` protocol +- `traefik.weight=10`: assign this weight to the container +- `traefik.enable=false`: disable this container in Træfɪk +- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`). See [frontends](#frontends). +- `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend. +- `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`. +* `traefik.domain=traefik.localhost`: override the default domain + + +## Marathon backend + +Træfɪk can be configured to use Marathon as a backend configuration: + + +```toml +################################################################ +# Mesos/Marathon configuration backend +################################################################ + +# Enable Marathon configuration backend +# +# Optional +# +[marathon] + +# Marathon server endpoint. +# You can also specify multiple endpoint for Marathon: +# endpoint := "http://10.241.1.71:8080,10.241.1.72:8080,10.241.1.73:8080" +# +# Required +# +endpoint = "http://127.0.0.1:8080" + +# Enable watch Marathon changes +# +# Optional +# +watch = true + +# Default domain used. +# Can be overridden by setting the "traefik.domain" label on an application. +# +# Required +# +domain = "marathon.localhost" + +# Override default configuration template. For advanced users :) +# +# Optional +# +# filename = "marathon.tmpl" + +# Expose Marathon apps by default in traefik +# +# Optional +# Default: false +# +# ExposedByDefault = true + +# Enable Marathon basic authentication +# +# Optional +# +# [marathon.basic] +# httpBasicAuthUser = "foo" +# httpBasicPassword = "bar" + +# TLS client configuration. https://golang.org/pkg/crypto/tls/#Config +# +# Optional +# +# [marathon.TLS] +# InsecureSkipVerify = true +``` + +Labels can be used on containers to override default behaviour: + +- `traefik.backend=foo`: assign the application to `foo` backend +- `traefik.portIndex=1`: register port by index in the application's ports array. Useful when the application exposes multiple ports. +- `traefik.port=80`: register the explicit application port value. Cannot be used alongside `traefik.portIndex`. +- `traefik.protocol=https`: override the default `http` protocol +- `traefik.weight=10`: assign this weight to the application +- `traefik.enable=false`: disable this application in Træfɪk +- `traefik.frontend.rule=Host:test.traefik.io`: override the default frontend rule (Default: `Host:{containerName}.{domain}`). See [frontends](#frontends). +- `traefik.frontend.passHostHeader=true`: forward client `Host` header to the backend. +- `traefik.frontend.entryPoints=http,https`: assign this frontend to entry points `http` and `https`. Overrides `defaultEntryPoints`. +* `traefik.domain=traefik.localhost`: override the default domain + +## Consul backend + +Træfɪk can be configured to use Consul as a backend configuration: + +```toml +################################################################ +# Consul KV configuration backend +################################################################ + +# Enable Consul KV configuration backend +# +# Optional +# +[consul] + +# Consul server endpoint +# +# Required +# +endpoint = "127.0.0.1:8500" + +# Enable watch Consul changes +# +# Optional +# +watch = true + +# Prefix used for KV store. +# +# Optional +# +prefix = "traefik" + +# Override default configuration template. For advanced users :) +# +# Optional +# +# filename = "consul.tmpl" + +# Enable consul TLS connection +# +# Optional +# +# [consul.tls] +# ca = "/etc/ssl/ca.crt" +# cert = "/etc/ssl/consul.crt" +# key = "/etc/ssl/consul.key" +# insecureskipverify = true +``` + +Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. + +## Consul catalog backend + +Træfɪk can be configured to use service discovery catalog of Consul as a backend configuration: + +```toml +################################################################ +# Consul Catalog configuration backend +################################################################ + +# Enable Consul Catalog configuration backend +# +# Optional +# +[consulCatalog] + +# Consul server endpoint +# +# Required +# +endpoint = "127.0.0.1:8500" + +# Default domain used. +# +# Optional +# +domain = "consul.localhost" +``` + +This backend will create routes matching on hostname based on the service name +used in consul. + + +## Etcd backend + +Træfɪk can be configured to use Etcd as a backend configuration: + +```toml +################################################################ +# Etcd configuration backend +################################################################ + +# Enable Etcd configuration backend +# +# Optional +# +# [etcd] + +# Etcd server endpoint +# +# Required +# +# endpoint = "127.0.0.1:4001" + +# Enable watch Etcd changes +# +# Optional +# +# watch = true + +# Prefix used for KV store. +# +# Optional +# +# prefix = "/traefik" + +# Override default configuration template. For advanced users :) +# +# Optional +# +# filename = "etcd.tmpl" + +# Enable etcd TLS connection +# +# Optional +# +# [etcd.tls] +# ca = "/etc/ssl/ca.crt" +# cert = "/etc/ssl/etcd.crt" +# key = "/etc/ssl/etcd.key" +# insecureskipverify = true +``` + +Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. + + +## Zookeeper backend + +Træfɪk can be configured to use Zookeeper as a backend configuration: + +```toml +################################################################ +# Zookeeper configuration backend +################################################################ + +# Enable Zookeeperconfiguration backend +# +# Optional +# +# [zookeeper] + +# Zookeeper server endpoint +# +# Required +# +# endpoint = "127.0.0.1:2181" + +# Enable watch Zookeeper changes +# +# Optional +# +# watch = true + +# Prefix used for KV store. +# +# Optional +# +# prefix = "/traefik" + +# Override default configuration template. For advanced users :) +# +# Optional +# +# filename = "zookeeper.tmpl" +``` + +Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. + +## BoltDB backend + +Træfɪk can be configured to use BoltDB as a backend configuration: + +```toml +################################################################ +# BoltDB configuration backend +################################################################ + +# Enable BoltDB configuration backend +# +# Optional +# +# [boltdb] + +# BoltDB file +# +# Required +# +# endpoint = "/my.db" + +# Enable watch BoltDB changes +# +# Optional +# +# watch = true + +# Prefix used for KV store. +# +# Optional +# +# prefix = "/traefik" + +# Override default configuration template. For advanced users :) +# +# Optional +# +# filename = "boltdb.tmpl" +``` + +Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure. + +## Key-value storage structure + +The Keys-Values structure should look (using `prefix = "/traefik"`): + +- backend 1 + +| Key | Value | +|--------------------------------------------------------|-----------------------------| +| `/traefik/backends/backend1/circuitbreaker/expression` | `NetworkErrorRatio() > 0.5` | +| `/traefik/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | +| `/traefik/backends/backend1/servers/server1/weight` | `10` | +| `/traefik/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` | +| `/traefik/backends/backend1/servers/server2/weight` | `1` | + +- backend 2 + +| Key | Value | +|-----------------------------------------------------|------------------------| +| `/traefik/backends/backend2/loadbalancer/method` | `drr` | +| `/traefik/backends/backend2/servers/server1/url` | `http://172.17.0.4:80` | +| `/traefik/backends/backend2/servers/server1/weight` | `1` | +| `/traefik/backends/backend2/servers/server2/url` | `http://172.17.0.5:80` | +| `/traefik/backends/backend2/servers/server2/weight` | `2` | + +- frontend 1 + +| Key | Value | +|---------------------------------------------------|-----------------------| +| `/traefik/frontends/frontend1/backend` | `backend2` | +| `/traefik/frontends/frontend1/routes/test_1/rule` | `Host:test.localhost` | + +- frontend 2 + +| Key | Value | +|----------------------------------------------------|--------------| +| `/traefik/frontends/frontend2/backend` | `backend1` | +| `/traefik/frontends/frontend2/passHostHeader` | `true` | +| `/traefik/frontends/frontend2/entrypoints` | `http,https` | +| `/traefik/frontends/frontend2/routes/test_2/rule` | `Path:/test` | + +## Atomic configuration changes + +The [Etcd](https://github.com/coreos/etcd/issues/860) and [Consul](https://github.com/hashicorp/consul/issues/886) backends do not support updating multiple keys atomically. As a result, it may be possible for Træfɪk to read an intermediate configuration state despite judicious use of the `--providersThrottleDuration` flag. To solve this problem, Træfɪk supports a special key called `/traefik/alias`. If set, Træfɪk use the value as an alternative key prefix. + +Given the key structure below, Træfɪk will use the `http://172.17.0.2:80` as its only backend (frontend keys have been omitted for brevity). + +| Key | Value | +|-------------------------------------------------------------------------|-----------------------------| +| `/traefik/alias` | `/traefik_configurations/1` | +| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | +| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` | + +When an atomic configuration change is required, you may write a new configuration at an alternative prefix. Here, although the `/traefik_configurations/2/...` keys have been set, the old configuration is still active because the `/traefik/alias` key still points to `/traefik_configurations/1`: + +| Key | Value | +|-------------------------------------------------------------------------|-----------------------------| +| `/traefik/alias` | `/traefik_configurations/1` | +| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | +| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` | +| `/traefik_configurations/2/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | +| `/traefik_configurations/2/backends/backend1/servers/server1/weight` | `5` | +| `/traefik_configurations/2/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` | +| `/traefik_configurations/2/backends/backend1/servers/server2/weight` | `5` | + +Once the `/traefik/alias` key is updated, the new `/traefik_configurations/2` configuration becomes active atomically. Here, we have a 50% balance between the `http://172.17.0.3:80` and the `http://172.17.0.4:80` hosts while no traffic is sent to the `172.17.0.2:80` host: + +| Key | Value | +|-------------------------------------------------------------------------|-----------------------------| +| `/traefik/alias` | `/traefik_configurations/2` | +| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` | +| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` | +| `/traefik_configurations/2/backends/backend1/servers/server1/url` | `http://172.17.0.3:80` | +| `/traefik_configurations/2/backends/backend1/servers/server1/weight` | `5` | +| `/traefik_configurations/2/backends/backend1/servers/server2/url` | `http://172.17.0.4:80` | +| `/traefik_configurations/2/backends/backend1/servers/server2/weight` | `5` | + +Note that Træfɪk *will not watch for key changes in the `/traefik_configurations` prefix*. It will only watch for changes in the `/traefik` prefix. Further, if the `/traefik/alias` key is set, all other sibling keys with the `/traefik` prefix are ignored. + + +# Examples + +## HTTP only + +``` +defaultEntryPoints = ["http"] +[entryPoints] + [entryPoints.http] + address = ":80" +``` + +## HTTP + HTTPS (with SNI) + +``` +defaultEntryPoints = ["http", "https"] +[entryPoints] + [entryPoints.http] + address = ":80" + [entryPoints.https] + address = ":443" + [entryPoints.https.tls] + [[entryPoints.https.tls.certificates]] + CertFile = "integration/fixtures/https/snitest.com.cert" + KeyFile = "integration/fixtures/https/snitest.com.key" + [[entryPoints.https.tls.certificates]] + CertFile = "integration/fixtures/https/snitest.org.cert" + KeyFile = "integration/fixtures/https/snitest.org.key" +``` + +## HTTP redirect on HTTPS + +``` +defaultEntryPoints = ["http", "https"] +[entryPoints] + [entryPoints.http] + address = ":80" + [entryPoints.http.redirect] + entryPoint = "https" + [entryPoints.https] + address = ":443" + [entryPoints.https.tls] + [[entryPoints.https.tls.certificates]] + certFile = "tests/traefik.crt" + keyFile = "tests/traefik.key" +``` + +## Let's Encrypt support + +``` +[entryPoints] + [entryPoints.https] + address = ":443" + [entryPoints.https.tls] + # certs used as default certs + [[entryPoints.https.tls.certificates]] + certFile = "tests/traefik.crt" + keyFile = "tests/traefik.key" +[acme] +email = "test@traefik.io" +storageFile = "acme.json" +onDemand = true +caServer = "http://172.18.0.1:4000/directory" +entryPoint = "https" + +[[acme.domains]] + main = "local1.com" + sans = ["test1.local1.com", "test2.local1.com"] +[[acme.domains]] + main = "local2.com" + sans = ["test1.local2.com", "test2x.local2.com"] +[[acme.domains]] + main = "local3.com" +[[acme.domains]] + main = "local4.com" +``` + +## Override entrypoints in frontends + +``` +[frontends] + [frontends.frontend1] + backend = "backend2" + [frontends.frontend1.routes.test_1] + rule = "Host:test.localhost" + [frontends.frontend2] + backend = "backend1" + passHostHeader = true + entrypoints = ["https"] # overrides defaultEntryPoints + [frontends.frontend2.routes.test_1] + rule = "Host:{subdomain:[a-z]+}.localhost" + [frontends.frontend3] + entrypoints = ["http", "https"] # overrides defaultEntryPoints + backend = "backend2" + rule = "Path:/test" +``` \ No newline at end of file diff --git a/tests/compose-consul.yml b/examples/compose-consul.yml similarity index 100% rename from tests/compose-consul.yml rename to examples/compose-consul.yml diff --git a/tests/compose-marathon.yml b/examples/compose-marathon.yml similarity index 100% rename from tests/compose-marathon.yml rename to examples/compose-marathon.yml diff --git a/examples/compose-traefik.yml b/examples/compose-traefik.yml new file mode 100644 index 000000000..6833d7ddd --- /dev/null +++ b/examples/compose-traefik.yml @@ -0,0 +1,21 @@ +traefik: + image: containous/traefik + command: --web --docker --docker.domain=docker.localhost --logLevel=DEBUG + ports: + - "80:80" + - "8080:8080" + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /dev/null:/traefik.toml + +whoami1: + image: emilevauge/whoami + labels: + - "traefik.backend=whoami" + - "traefik.frontend.rule=Host:whoami.docker.localhost" + +whoami2: + image: emilevauge/whoami + labels: + - "traefik.backend=whoami" + - "traefik.frontend.rule=Host:whoami.docker.localhost" \ No newline at end of file diff --git a/tests/consul-config.sh b/examples/consul-config.sh similarity index 100% rename from tests/consul-config.sh rename to examples/consul-config.sh diff --git a/tests/traefik.crt b/examples/traefik.crt similarity index 100% rename from tests/traefik.crt rename to examples/traefik.crt diff --git a/tests/traefik.key b/examples/traefik.key similarity index 100% rename from tests/traefik.key rename to examples/traefik.key diff --git a/tests/whoami.json b/examples/whoami.json similarity index 100% rename from tests/whoami.json rename to examples/whoami.json diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 000000000..88a867542 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,49 @@ +site_name: Traefik +site_description: Traefik Documentation +site_author: containo.us +site_url: https://docs.traefik.io + +repo_name: 'GitHub' +repo_url: 'https://github.com/containous/traefik' + +# Documentation and theme +docs_dir: 'docs' +theme: united +# theme: readthedocs +# theme: 'material' +# theme: bootstrap + +site_favicon: 'img/traefik.icon.png' + +# Copyright +copyright: Copyright (c) 2016 Containous SAS + +# Options +extra: +# version: 0.2.2 + logo: img/traefik.logo.png + # author: + # twitter: traefikproxy + palette: + primary: 'blue' + accent: 'light blue' + i18n: + prev: 'Previous' + next: 'Next' + +markdown_extensions: +# - codehilite(css_class=code) + - admonition +# - toc: +# permalink: '##' + # - fenced_code + +extra_css: + - css/traefik.css + +# Page tree +pages: + - Getting Started: index.md + - Basics: basics.md + - traefik.toml: toml.md + - Benchmarks: benchmarks.md \ No newline at end of file diff --git a/script/deploy.sh b/script/deploy.sh index 1c9b60a1d..c4b5b8285 100755 --- a/script/deploy.sh +++ b/script/deploy.sh @@ -16,16 +16,19 @@ sudo chmod +x /usr/bin/ghr # github release and tag ghr -t $GITHUB_TOKEN -u containous -r traefik --prerelease ${VERSION} dist/ +# update docs.traefik.io +mkdocs gh-deploy --clean + # update traefik-library-image repo (official Docker image) git config --global user.email "emile@vauge.com" git config --global user.name "Emile Vauge" -git clone https://github.com/containous/traefik-library-image.git +git clone git@github.com:containous/traefik-library-image.git cd traefik-library-image ./update.sh $VERSION git add -A echo $VERSION | git commit --file - echo $VERSION | git tag -a $VERSION --file - -git push -q --follow-tags https://emilevauge:${GITHUB_TOKEN}@github.com/containous/traefik-library-image.git +git push -q --follow-tags -u origin master # create docker image emilevauge/traefik (compatibility) docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS