547 lines
15 KiB
Markdown
547 lines
15 KiB
Markdown
# Traefik & Docker
|
|
|
|
A Story of Labels & Containers
|
|
{: .subtitle }
|
|
|
|
![Docker](../assets/img/providers/docker.png)
|
|
|
|
Attach labels to your containers and let Traefik do the rest!
|
|
|
|
!!! tip "The Quick Start Uses Docker"
|
|
If you haven't already, maybe you'd like to go through the [quick start](../getting-started/quick-start.md) that uses the docker provider!
|
|
|
|
## Configuration Examples
|
|
|
|
??? example "Configuring Docker & Deploying / Exposing Services"
|
|
|
|
Enabling the docker provider
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker]
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker: {}
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker=true
|
|
```
|
|
|
|
Attaching labels to containers (in your docker compose file)
|
|
|
|
```yaml
|
|
version: "3"
|
|
services:
|
|
my-container:
|
|
# ...
|
|
labels:
|
|
- traefik.http.routers.my-container.rule=Host(`mydomain.com`)
|
|
```
|
|
|
|
??? example "Configuring Docker Swarm & Deploying / Exposing Services"
|
|
|
|
Enabling the docker provider (Swarm Mode)
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker]
|
|
# swarm classic (1.12-)
|
|
# endpoint = "tcp://127.0.0.1:2375"
|
|
# docker swarm mode (1.12+)
|
|
endpoint = "tcp://127.0.0.1:2377"
|
|
swarmMode = true
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
# swarm classic (1.12-)
|
|
# endpoint = "tcp://127.0.0.1:2375"
|
|
# docker swarm mode (1.12+)
|
|
endpoint: "tcp://127.0.0.1:2375"
|
|
swarmMode: true
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.endpoint=tcp://127.0.0.1:2375
|
|
--providers.docker.swarmMode=true
|
|
```
|
|
|
|
Attach labels to services (not to containers) while in Swarm mode (in your docker compose file)
|
|
|
|
```yaml
|
|
version: "3"
|
|
services:
|
|
my-container:
|
|
deploy:
|
|
labels:
|
|
- traefik.http.routers.my-container.rule=Host(`mydomain.com`)
|
|
- traefik.http.services.my-container-service.loadbalancer.server.port=8080
|
|
```
|
|
|
|
!!! important "Labels in Docker Swarm Mode"
|
|
While in Swarm Mode, Traefik uses labels found on services, not on individual containers.
|
|
|
|
Therefore, if you use a compose file with Swarm Mode, labels should be defined in the `deploy` part of your service.
|
|
This behavior is only enabled for docker-compose version 3+ ([Compose file reference](https://docs.docker.com/compose/compose-file/#labels-1)).
|
|
|
|
## Routing Configuration
|
|
|
|
See the dedicated section in [routing](../routing/providers/docker.md).
|
|
|
|
## Provider Configuration
|
|
|
|
### `endpoint`
|
|
|
|
_Required, Default="unix:///var/run/docker.sock"_
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker]
|
|
endpoint = "unix:///var/run/docker.sock"
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
endpoint: "unix:///var/run/docker.sock"
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.endpoint=unix:///var/run/docker.sock
|
|
```
|
|
|
|
Traefik requires access to the docker socket to get its dynamic configuration.
|
|
|
|
??? warning "Security Notes"
|
|
|
|
Depending on your context, accessing the Docker API without any restriction can be a security concern: If Traefik is attacked, then the attacker might get access to the Docker (or Swarm Mode) backend.
|
|
|
|
As explained in the Docker documentation: ([Docker Daemon Attack Surface page](https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface)):
|
|
|
|
`[...] only **trusted** users should be allowed to control your Docker daemon [...]`
|
|
|
|
!!! tip "Improved Security"
|
|
|
|
[TraefikEE](https://containo.us/traefikee) solves this problem by separating the control plane (connected to Docker) and the data plane (handling the requests).
|
|
|
|
??? info "Resources about Docker's Security"
|
|
|
|
- [KubeCon EU 2018 Keynote, Running with Scissors, from Liz Rice](https://www.youtube.com/watch?v=ltrV-Qmh3oY)
|
|
- [Don't expose the Docker socket (not even to a container)](https://www.lvh.io/posts/dont-expose-the-docker-socket-not-even-to-a-container/)
|
|
- [A thread on Stack Overflow about sharing the `/var/run/docker.sock` file](https://news.ycombinator.com/item?id=17983623)
|
|
- [To DinD or not to DinD](https://blog.loof.fr/2018/01/to-dind-or-not-do-dind.html)
|
|
|
|
??? tip "Security Compensation"
|
|
|
|
Expose the Docker socket over TCP, instead of the default Unix socket file.
|
|
It allows different implementation levels of the [AAA (Authentication, Authorization, Accounting) concepts](https://en.wikipedia.org/wiki/AAA_(computer_security)), depending on your security assessment:
|
|
|
|
- Authentication with Client Certificates as described in ["Protect the Docker daemon socket."](https://docs.docker.com/engine/security/https/)
|
|
- Authorization with the [Docker Authorization Plugin Mechanism](https://docs.docker.com/engine/extend/plugins_authorization/)
|
|
- Accounting at networking level, by exposing the socket only inside a Docker private network, only available for Traefik.
|
|
- Accounting at container level, by exposing the socket on a another container than Traefik's.
|
|
With Swarm mode, it allows scheduling of Traefik on worker nodes, with only the "socket exposer" container on the manager nodes.
|
|
- Accounting at kernel level, by enforcing kernel calls with mechanisms like [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux), to only allows an identified set of actions for Traefik's process (or the "socket exposer" process).
|
|
|
|
??? info "Additional Resources"
|
|
|
|
- [Traefik issue GH-4174 about security with Docker socket](https://github.com/containous/traefik/issues/4174)
|
|
- [Inspecting Docker Activity with Socat](https://developers.redhat.com/blog/2015/02/25/inspecting-docker-activity-with-socat/)
|
|
- [Letting Traefik run on Worker Nodes](https://blog.mikesir87.io/2018/07/letting-traefik-run-on-worker-nodes/)
|
|
- [Docker Socket Proxy from Tecnativa](https://github.com/Tecnativa/docker-socket-proxy)
|
|
|
|
!!! info "Traefik & Swarm Mode"
|
|
To let Traefik access the Docker Socket of the Swarm manager, it is mandatory to schedule Traefik on the Swarm manager nodes.
|
|
|
|
??? example "Using the docker.sock"
|
|
|
|
The docker-compose file shares the docker sock with the Traefik container
|
|
|
|
```yaml
|
|
version: '3'
|
|
|
|
services:
|
|
traefik:
|
|
image: traefik:v2.0 # The official v2.0 Traefik docker image
|
|
ports:
|
|
- "80:80"
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
```
|
|
|
|
We specify the docker.sock in traefik's configuration file.
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker]
|
|
endpoint = "unix:///var/run/docker.sock"
|
|
# ...
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
endpoint: "unix:///var/run/docker.sock"
|
|
# ...
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.endpoint=unix:///var/run/docker.sock
|
|
# ...
|
|
```
|
|
|
|
### `useBindPortIP`
|
|
|
|
_Optional, Default=false_
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker]
|
|
useBindPortIP = true
|
|
# ...
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
useBindPortIP: true
|
|
# ...
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.useBindPortIP=true
|
|
# ...
|
|
```
|
|
|
|
Traefik routes requests to the IP/Port of the matching container.
|
|
When setting `useBindPortIP=true`, you tell Traefik to use the IP/Port attached to the container's _binding_ instead of its inner network IP/Port.
|
|
|
|
When used in conjunction with the `traefik.http.services.<name>.loadbalancer.server.port` label (that tells Traefik to route requests to a specific port),
|
|
Traefik tries to find a binding on port `traefik.http.services.<name>.loadbalancer.server.port`.
|
|
If it can't find such a binding, Traefik falls back on the internal network IP of the container,
|
|
but still uses the `traefik.http.services.<name>.loadbalancer.server.port` that is set in the label.
|
|
|
|
??? example "Examples of `usebindportip` in different situations."
|
|
|
|
| port label | Container's binding | Routes to |
|
|
|--------------------|----------------------------------------------------|----------------|
|
|
| - | - | IntIP:IntPort |
|
|
| - | ExtPort:IntPort | IntIP:IntPort |
|
|
| - | ExtIp:ExtPort:IntPort | ExtIp:ExtPort |
|
|
| LblPort | - | IntIp:LblPort |
|
|
| LblPort | ExtIp:ExtPort:LblPort | ExtIp:ExtPort |
|
|
| LblPort | ExtIp:ExtPort:OtherPort | IntIp:LblPort |
|
|
| LblPort | ExtIp1:ExtPort1:IntPort1 & ExtIp2:LblPort:IntPort2 | ExtIp2:LblPort |
|
|
|
|
!!! info ""
|
|
In the above table:
|
|
|
|
- `ExtIp` stands for "external IP found in the binding"
|
|
- `IntIp` stands for "internal network container's IP",
|
|
- `ExtPort` stands for "external Port found in the binding"
|
|
- `IntPort` stands for "internal network container's port."
|
|
|
|
### `exposedByDefault`
|
|
|
|
_Optional, Default=true_
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker]
|
|
exposedByDefault = false
|
|
# ...
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
exposedByDefault: false
|
|
# ...
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.exposedByDefault=false
|
|
# ...
|
|
```
|
|
|
|
Expose containers by default through Traefik.
|
|
If set to false, containers that don't have a `traefik.enable=true` label will be ignored from the resulting routing configuration.
|
|
|
|
See also [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).
|
|
|
|
### `network`
|
|
|
|
_Optional, Default=empty_
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker]
|
|
network = "test"
|
|
# ...
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
network: test
|
|
# ...
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.network=test
|
|
# ...
|
|
```
|
|
|
|
Defines a default docker network to use for connections to all containers.
|
|
|
|
This option can be overridden on a container basis with the `traefik.docker.network` label.
|
|
|
|
### `defaultRule`
|
|
|
|
_Optional, Default=```Host(`{{ normalize .Name }}`)```_
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker]
|
|
defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
|
|
# ...
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
|
|
# ...
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)
|
|
# ...
|
|
```
|
|
|
|
For a given container if no routing rule was defined by a label, it is defined by this defaultRule instead.
|
|
It must be a valid [Go template](https://golang.org/pkg/text/template/),
|
|
augmented with the [sprig template functions](http://masterminds.github.io/sprig/).
|
|
The container service name can be accessed as the `Name` identifier,
|
|
and the template has access to all the labels defined on this container.
|
|
|
|
### `swarmMode`
|
|
|
|
_Optional, Default=false_
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker]
|
|
swarmMode = true
|
|
# ...
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
swarmMode: true
|
|
# ...
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.swarmMode=true
|
|
# ...
|
|
```
|
|
|
|
Activates the Swarm Mode.
|
|
|
|
### `swarmModeRefreshSeconds`
|
|
|
|
_Optional, Default=15_
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker]
|
|
swarmModeRefreshSeconds = "30s"
|
|
# ...
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
swarmModeRefreshSeconds: "30s"
|
|
# ...
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.swarmModeRefreshSeconds=30s
|
|
# ...
|
|
```
|
|
|
|
Defines the polling interval (in seconds) in Swarm Mode.
|
|
|
|
### `constraints`
|
|
|
|
_Optional, Default=""_
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker]
|
|
constraints = "Label(`a.label.name`,`foo`)"
|
|
# ...
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
constraints: "Label(`a.label.name`,`foo`)"
|
|
# ...
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.constraints=Label(`a.label.name`,`foo`)
|
|
# ...
|
|
```
|
|
|
|
Constraints is an expression that Traefik matches against the container's labels to determine whether to create any route for that container.
|
|
That is to say, if none of the container's labels match the expression, no route for the container is created.
|
|
If the expression is empty, all detected containers are included.
|
|
|
|
The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions, as well as the usual boolean logic, as shown in examples below.
|
|
|
|
??? example "Constraints Expression Examples"
|
|
|
|
```toml
|
|
# Includes only containers having a label with key `a.label.name` and value `foo`
|
|
constraints = "Label(`a.label.name`, `foo`)"
|
|
```
|
|
|
|
```toml
|
|
# Excludes containers having any label with key `a.label.name` and value `foo`
|
|
constraints = "!Label(`a.label.name`, `value`)"
|
|
```
|
|
|
|
```toml
|
|
# With logical AND.
|
|
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
|
|
```
|
|
|
|
```toml
|
|
# With logical OR.
|
|
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
|
|
```
|
|
|
|
```toml
|
|
# With logical AND and OR, with precedence set by parentheses.
|
|
constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
|
|
```
|
|
|
|
```toml
|
|
# Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression.
|
|
constraints = "LabelRegex(`a.label.name`, `a.+`)"
|
|
```
|
|
|
|
See also [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).
|
|
|
|
### `tls`
|
|
|
|
_Optional_
|
|
|
|
#### `tls.ca`
|
|
|
|
Certificate Authority used for the secured connection to Docker.
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker.tls]
|
|
ca = "path/to/ca.crt"
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
tls:
|
|
ca: path/to/ca.crt
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.tls.ca=path/to/ca.crt
|
|
```
|
|
|
|
#### `tls.caOptional`
|
|
|
|
Policy followed for the secured connection with TLS Client Authentication to Docker.
|
|
Requires `tls.ca` to be defined.
|
|
|
|
- `true`: VerifyClientCertIfGiven
|
|
- `false`: RequireAndVerifyClientCert
|
|
- if `tls.ca` is undefined NoClientCert
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker.tls]
|
|
caOptional = true
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
tls:
|
|
caOptional: true
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.tls.caOptional=true
|
|
```
|
|
|
|
#### `tls.cert`
|
|
|
|
Public certificate used for the secured connection to Docker.
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker.tls]
|
|
cert = "path/to/foo.cert"
|
|
key = "path/to/foo.key"
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
tls:
|
|
cert: path/to/foo.cert
|
|
key: path/to/foo.key
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.tls.cert=path/to/foo.cert
|
|
--providers.docker.tls.key=path/to/foo.key
|
|
```
|
|
|
|
#### `tls.key`
|
|
|
|
Private certificate used for the secured connection to Docker.
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker.tls]
|
|
cert = "path/to/foo.cert"
|
|
key = "path/to/foo.key"
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
tls:
|
|
cert: path/to/foo.cert
|
|
key: path/to/foo.key
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.tls.cert=path/to/foo.cert
|
|
--providers.docker.tls.key=path/to/foo.key
|
|
```
|
|
|
|
#### `tls.insecureSkipVerify`
|
|
|
|
If `insecureSkipVerify` is `true`, TLS for the connection to Docker accepts any certificate presented by the server and any host name in that certificate.
|
|
|
|
```toml tab="File (TOML)"
|
|
[providers.docker.tls]
|
|
insecureSkipVerify = true
|
|
```
|
|
|
|
```yaml tab="File (YAML)"
|
|
providers:
|
|
docker:
|
|
tls:
|
|
insecureSkipVerify: true
|
|
```
|
|
|
|
```bash tab="CLI"
|
|
--providers.docker.tls.insecureSkipVerify=true
|
|
```
|