Traefik Docker Documentation – Traefik
Mục Lục
Traefik & Docker¶
A Story of Labels & Containers
Attach labels to your containers and let Traefik do the rest!
Traefik works with both Docker (standalone) Engine
and Docker Swarm Mode.
The Quick Start Uses Docker
If you have not already read it, maybe you would like to go through the quick start guide that uses the Docker provider.
Configuration Examples¶
Configuring Docker & Deploying / Exposing Services
Enabling the docker provider
File (YAML)
providers:
docker: {}
File (TOML)
[providers.docker]
CLI
--providers.docker=true
Attaching labels to containers (in your docker compose file)
version: "3"
services:
my-container:
# ...
labels:
- traefik.http.routers.my-container.rule=Host(`example.com`)
Configuring Docker Swarm & Deploying / Exposing Services
Enabling the docker provider (Swarm Mode)
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:2377"
swarmMode: true
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
CLI
# swarm classic (1.12-)
# --providers.docker.endpoint=tcp://127.0.0.1:2375
# docker swarm mode (1.12+)
--providers.docker.endpoint=tcp://127.0.0.1:2377
--providers.docker.swarmMode=true
Attach labels to services (not to containers) while in Swarm mode (in your docker compose file)
version: "3"
services:
my-container:
deploy:
labels:
- traefik.http.routers.my-container.rule=Host(`example.com`)
- traefik.http.services.my-container-service.loadbalancer.server.port=8080
Routing Configuration¶
When using Docker as a provider,
Traefik uses container labels to retrieve its routing configuration.
See the list of labels in the dedicated routing section.
Routing Configuration with Labels¶
By default, Traefik watches for container level labels on a standalone Docker Engine.
When using Docker Compose, labels are specified by the directive
labels
from the
“services” objects.
Not Only Docker
Please note that any tool like Nomad, Terraform, Ansible, etc.
that is able to define a Docker container with labels can work
with Traefik and the Docker provider.
Port Detection¶
Traefik retrieves the private IP and port of containers from the Docker API.
Port detection works as follows:
- If a container exposes a single port,
then Traefik uses this port for private communication. - If a container exposes multiple ports,
or does not expose any port, then you must manually specify which port Traefik should use for communication
by using the labeltraefik.http.services.<service_name>.loadbalancer.server.port
(Read more on this label in the dedicated section in routing).
Host networking¶
When exposing containers that are configured with host networking,
the IP address of the host is resolved as follows:
- try a lookup of
host.docker.internal
- if the lookup was unsuccessful, try a lookup of
host.containers.internal
, (Podman equivalent ofhost.docker.internal
) - if that lookup was also unsuccessful, fall back to
127.0.0.1
On Linux, for versions of Docker older than 20.10.0, for host.docker.internal
to be defined, it should be provided
as an extra_host
to the Traefik container, using the --add-host
flag. For example, to set it to the IP address of
the bridge interface (docker0
by default): --add-host=host.docker.internal:172.17.0.1
IPv4 && IPv6¶
When using a docker stack that uses IPv6,
Traefik will use the IPv4 container IP before its IPv6 counterpart.
Therefore, on an IPv6 Docker stack,
Traefik will use the IPv6 container IP.
Docker API Access¶
Traefik requires access to the docker socket to get its dynamic configuration.
You can specify which Docker API Endpoint to use with the directive endpoint
.
Docker Swarm Mode¶
To enable Docker Swarm (instead of standalone Docker) as a configuration provider,
set the swarmMode
directive to true
.
Routing Configuration with Labels¶
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).
Port Detection¶
Docker Swarm does not provide any port detection information to Traefik.
Therefore, you must specify the port to use for communication by using the label traefik.http.services.<service_name>.loadbalancer.server.port
(Check the reference for this label in the routing section for Docker).
Docker API Access¶
Docker Swarm Mode follows the same rules as Docker API Access.
Since the Swarm API is only exposed on the manager nodes,
these are the nodes that Traefik should be scheduled on by deploying Traefik with a constraint on the node “role”:
With Docker CLI
docker service create \
--constraint=node.role==manager \
#... \
With Docker Compose
version: '3'
services:
traefik:
# ...
deploy:
placement:
constraints:
- node.role == manager
Scheduling Traefik on Worker Nodes
Following the guidelines given in the previous section “Docker API Access”,
if you expose the Docker API through TCP, then Traefik can be scheduled on any node if the TCP
socket is reachable.
Please consider the security implications by reading the Security Note.
A good example can be found on Bret Fisher’s repository.
Provider Configuration¶
Required, Default=”unix:///var/run/docker.sock”
See the sections Docker API Access and Docker Swarm API Access for more information.
Using the docker.sock
The docker-compose file shares the docker sock with the Traefik container
version: '3'
services:
traefik:
image: traefik:v2.9 # The official v2 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.
File (YAML)
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
# ...
File (TOML)
[providers.docker]
endpoint = "unix:///var/run/docker.sock"
# ...
CLI
--providers.docker.endpoint=unix:///var/run/docker.sock
# ...
Using SSH
Using Docker 18.09+ you can connect Traefik to daemon using SSH
We specify the SSH host and user in Traefik’s configuration file.
Note that is server requires public keys for authentication you must have those accessible for user who runs Traefik.
File (YAML)
providers:
docker:
endpoint: "ssh://[email protected]:2022"
# ...
File (TOML)
[providers.docker]
endpoint = "ssh://[email protected]:2022"
# ...
CLI
--providers.docker.endpoint=ssh://[email protected]:2022
# ...
File (YAML)
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
File (TOML)
[providers.docker]
endpoint = "unix:///var/run/docker.sock"
CLI
--providers.docker.endpoint=unix:///var/run/docker.sock
Optional, Default=false
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 cannot 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.
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
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.”
File (YAML)
providers:
docker:
useBindPortIP: true
# ...
File (TOML)
[providers.docker]
useBindPortIP = true
# ...
CLI
--providers.docker.useBindPortIP=true
# ...
Optional, Default=true
Expose containers by default through Traefik.
If set to false
, containers that do not have a traefik.enable=true
label are ignored from the resulting routing configuration.
For additional information, refer to Restrict the Scope of Service Discovery.
File (YAML)
providers:
docker:
exposedByDefault: false
# ...
File (TOML)
[providers.docker]
exposedByDefault = false
# ...
CLI
--providers.docker.exposedByDefault=false
# ...
Optional, Default=””
Defines a default docker network to use for connections to all containers.
This option can be overridden on a per-container basis with the traefik.docker.network
label.
File (YAML)
providers:
docker:
network: test
# ...
File (TOML)
[providers.docker]
network = "test"
# ...
CLI
--providers.docker.network=test
# ...
Optional, Default=Host(`{{ normalize .Name }}`)
The defaultRule
option defines what routing rule to apply to a container if no rule is defined by a label.
It must be a valid Go template, and can use
sprig template functions.
The container service name can be accessed with the Name
identifier,
and the template has access to all the labels defined on this container.
File (YAML)
providers:
docker:
defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
File (TOML)
[providers.docker]
defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
CLI
--providers.docker.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)
# ...
Optional, Default=false
Enables the Swarm Mode (instead of standalone Docker).
File (YAML)
providers:
docker:
swarmMode: true
# ...
File (TOML)
[providers.docker]
swarmMode = true
# ...
CLI
--providers.docker.swarmMode=true
# ...
Optional, Default=15
Defines the polling interval (in seconds) for Swarm Mode.
File (YAML)
providers:
docker:
swarmModeRefreshSeconds: 30
# ...
File (TOML)
[providers.docker]
swarmModeRefreshSeconds = 30
# ...
CLI
--providers.docker.swarmModeRefreshSeconds=30
# ...
Optional, Default=0
Defines the client timeout (in seconds) for HTTP connections. If its value is 0
, no timeout is set.
File (YAML)
providers:
docker:
httpClientTimeout: 300
# ...
File (TOML)
[providers.docker]
httpClientTimeout = 300
# ...
CLI
--providers.docker.httpClientTimeout=300
# ...
Optional, Default=true
Watch Docker events.
File (YAML)
providers:
docker:
watch: false
# ...
File (TOML)
[providers.docker]
watch = false
# ...
CLI
--providers.docker.watch=false
# ...
Optional, Default=””
The constraints
option can be set to an expression that Traefik matches against the container labels to determine whether
to create any route for that container. If none of the container labels match the expression, no route for that 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.
Constraints Expression Examples
# Includes only containers having a label with key `a.label.name` and value `foo`
constraints = "Label(`a.label.name`, `foo`)"
# Excludes containers having any label with key `a.label.name` and value `foo`
constraints = "!Label(`a.label.name`, `value`)"
# With logical AND.
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
# With logical OR.
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
# 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`))"
# 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.+`)"
For additional information, refer to Restrict the Scope of Service Discovery.
File (YAML)
providers:
docker:
constraints: "Label(`a.label.name`,`foo`)"
# ...
File (TOML)
[providers.docker]
constraints = "Label(`a.label.name`,`foo`)"
# ...
CLI
--providers.docker.constraints=Label(`a.label.name`,`foo`)
# ...
Optional
Defines the TLS configuration used for the secure connection to Docker.
Optional
ca
is the path to the certificate authority used for the secure connection to Docker,
it defaults to the system bundle.
File (YAML)
providers:
docker:
tls:
ca: path/to/ca.crt
File (TOML)
[providers.docker.tls]
ca = "path/to/ca.crt"
CLI
--providers.docker.tls.ca=path/to/ca.crt
cert
is the path to the public certificate used for the secure connection to Docker.
When using this option, setting the key
option is required.
File (YAML)
providers:
docker:
tls:
cert: path/to/foo.cert
key: path/to/foo.key
File (TOML)
[providers.docker.tls]
cert = "path/to/foo.cert"
key = "path/to/foo.key"
CLI
--providers.docker.tls.cert=path/to/foo.cert
--providers.docker.tls.key=path/to/foo.key
Optional
key
is the path to the private key used for the secure connection Docker.
When using this option, setting the cert
option is required.
File (YAML)
providers:
docker:
tls:
cert: path/to/foo.cert
key: path/to/foo.key
File (TOML)
[providers.docker.tls]
cert = "path/to/foo.cert"
key = "path/to/foo.key"
CLI
--providers.docker.tls.cert=path/to/foo.cert
--providers.docker.tls.key=path/to/foo.key
Optional, Default=false
If insecureSkipVerify
is true
, the TLS connection to Docker accepts any certificate presented by the server regardless of the hostnames it covers.
File (YAML)
providers:
docker:
tls:
insecureSkipVerify: true
File (TOML)
[providers.docker.tls]
insecureSkipVerify = true
CLI
--providers.docker.tls.insecureSkipVerify=true
Optional, Default=false
If the parameter is set to true
,
any servers load balancer defined for Docker containers is created
regardless of the healthiness of the corresponding containers.
It also then stays alive and responsive even at times when it becomes empty,
i.e. when all its children containers become unhealthy.
This results in 503
HTTP responses instead of 404
ones,
in the above cases.
File (YAML)
providers:
docker:
allowEmptyServices: true
File (TOML)
[providers.docker]
allowEmptyServices = true
CLI
--providers.docker.allowEmptyServices=true