docs/content/reference/install-configuration/providers/swarm.md
This provider works with Docker Swarm Mode.
!!! tip "The Quick Start Uses Docker"
If you have not already read it, maybe you would like to go through the [quick start guide](../../../getting-started/index.md) that uses the Docker provider.
You can enable the Swarm provider as detailed below:
providers:
swarm: {}
[providers.swarm]
--providers.swarm=true
Attach labels to a single service (not containers) while in Swarm mode (in your Docker compose file). When there is only one service, and the router does not specify a service, then that service is automatically assigned to the router.
services:
my-container:
deploy:
labels:
- traefik.http.routers.my-container.rule=Host(`example.com`)
- traefik.http.services.my-container-service.loadbalancer.server.port=8080
| Field | Description | Default | Required |
|---|---|---|---|
<a id="opt-providers-providersThrottleDuration" href="#opt-providers-providersThrottleDuration" title="#opt-providers-providersThrottleDuration">providers.providersThrottleDuration</a> | Minimum amount of time to wait for, after a configuration reload, before taking into account any new configuration refresh event. | ||
| If multiple events occur within this time, only the most recent one is taken into account, and all others are discarded. | |||
| This option cannot be set per provider, but the throttling algorithm applies to each of them independently. | 2s | No | |
<a id="opt-providers-swarm-endpoint" href="#opt-providers-swarm-endpoint" title="#opt-providers-swarm-endpoint">providers.swarm.endpoint</a> | Specifies the Docker API endpoint. See here for more information | unix:///var/run/docker.sock | Yes |
<a id="opt-providers-swarm-username" href="#opt-providers-swarm-username" title="#opt-providers-swarm-username">providers.swarm.username</a> | Defines the username for Basic HTTP authentication. This should be used when the Docker daemon socket is exposed through an HTTP proxy that requires Basic HTTP authentication. | "" | No |
<a id="opt-providers-swarm-password" href="#opt-providers-swarm-password" title="#opt-providers-swarm-password">providers.swarm.password</a> | Defines the password for Basic HTTP authentication. This should be used when the Docker daemon socket is exposed through an HTTP proxy that requires Basic HTTP authentication. | "" | No |
<a id="opt-providers-swarm-useBindPortIP" href="#opt-providers-swarm-useBindPortIP" title="#opt-providers-swarm-useBindPortIP">providers.swarm.useBindPortIP</a> | Instructs Traefik to use the IP/Port attached to the container's binding instead of its inner network IP/Port. See here for more information | false | No |
<a id="opt-providers-swarm-exposedByDefault" href="#opt-providers-swarm-exposedByDefault" title="#opt-providers-swarm-exposedByDefault">providers.swarm.exposedByDefault</a> | Expose containers by default through Traefik. See here for additional information | true | No |
<a id="opt-providers-swarm-network" href="#opt-providers-swarm-network" title="#opt-providers-swarm-network">providers.swarm.network</a> | 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.swarm.network label. | "" | No |
<a id="opt-providers-swarm-defaultRule" href="#opt-providers-swarm-defaultRule" title="#opt-providers-swarm-defaultRule">providers.swarm.defaultRule</a> | Defines what routing rule to apply to a container if no rule is defined by a label. See here for more information | "Host(`{{ normalize .Name }}`)" | No |
<a id="opt-providers-swarm-refreshSeconds" href="#opt-providers-swarm-refreshSeconds" title="#opt-providers-swarm-refreshSeconds">providers.swarm.refreshSeconds</a> | Defines the polling interval for Swarm Mode. | "15s" | No |
<a id="opt-providers-swarm-httpClientTimeout" href="#opt-providers-swarm-httpClientTimeout" title="#opt-providers-swarm-httpClientTimeout">providers.swarm.httpClientTimeout</a> | Defines the client timeout (in seconds) for HTTP connections. If its value is 0, no timeout is set. | 0 | No |
<a id="opt-providers-swarm-watch" href="#opt-providers-swarm-watch" title="#opt-providers-swarm-watch">providers.swarm.watch</a> | Instructs Traefik to watch Docker events or not. | True | No |
<a id="opt-providers-swarm-constraints" href="#opt-providers-swarm-constraints" title="#opt-providers-swarm-constraints">providers.swarm.constraints</a> | Defines an expression that Traefik matches against the container labels to determine whether to create any route for that container. See here for more information. | "" | No |
<a id="opt-providers-swarm-allowEmptyServices" href="#opt-providers-swarm-allowEmptyServices" title="#opt-providers-swarm-allowEmptyServices">providers.swarm.allowEmptyServices</a> | Instructs the provider to create any servers load balancer defined for Docker containers regardless of the healthiness of the corresponding containers. | false | No |
<a id="opt-providers-swarm-tls-ca" href="#opt-providers-swarm-tls-ca" title="#opt-providers-swarm-tls-ca">providers.swarm.tls.ca</a> | Defines the path to the certificate authority used for the secure connection to Docker, it defaults to the system bundle. | "" | No |
<a id="opt-providers-swarm-tls-cert" href="#opt-providers-swarm-tls-cert" title="#opt-providers-swarm-tls-cert">providers.swarm.tls.cert</a> | Defines the path to the public certificate used for the secure connection to Docker. When using this option, setting the key option is required. | "" | Yes |
<a id="opt-providers-swarm-tls-key" href="#opt-providers-swarm-tls-key" title="#opt-providers-swarm-tls-key">providers.swarm.tls.key</a> | Defines the path to the private key used for the secure connection to Docker. When using this option, setting the cert option is required. | "" | Yes |
<a id="opt-providers-swarm-tls-insecureSkipVerify" href="#opt-providers-swarm-tls-insecureSkipVerify" title="#opt-providers-swarm-tls-insecureSkipVerify">providers.swarm.tls.insecureSkipVerify</a> | Instructs the provider to accept any certificate presented by the Docker server when establishing a TLS connection, regardless of the hostnames the certificate covers. | false | No |
endpointSee the Docker Swarm API Access section for more information.
??? example "Using the docker.sock"
The docker-compose file shares the docker sock with the Traefik container
```yaml
services:
traefik:
image: traefik:v3.1 # The official v3 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.
```yaml tab="File (YAML)"
providers:
swarm:
endpoint: "unix:///var/run/docker.sock"
# ...
```
```toml tab="File (TOML)"
[providers.swarm]
endpoint = "unix:///var/run/docker.sock"
# ...
```
```bash tab="CLI"
--providers.swarm.endpoint=unix:///var/run/docker.sock
# ...
```
??? example "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 if the server requires public keys for authentication, you must have them accessible for the user running Traefik.
```yaml tab="File (YAML)"
providers:
swarm:
endpoint: "ssh://[email protected]:2022"
# ...
```
```toml tab="File (TOML)"
[providers.swarm]
endpoint = "ssh://[email protected]:2022"
# ...
```
```bash tab="CLI"
--providers.swarm.endpoint=ssh://[email protected]:2022
# ...
```
??? example "Using HTTP"
Using Docker Engine API you can connect Traefik to remote daemon using HTTP.
```yaml tab="File (YAML)"
providers:
swarm:
endpoint: "http://127.0.0.1:2375"
# ...
```
```toml tab="Static Configuration (TOML)"
[providers.swarm]
endpoint = "http://127.0.0.1:2375"
# ...
```
```bash tab="CLI"
--providers.swarm.endpoint=http://127.0.0.1:2375
# ...
```
??? example "Using TCP"
Using Docker Engine API you can connect Traefik to remote daemon using TCP.
```yaml tab="File (YAML)"
providers:
swarm:
endpoint: "tcp://127.0.0.1:2375"
# ...
```
```toml tab="File (TOML)"
[providers.swarm]
endpoint = "tcp://127.0.0.1:2375"
# ...
```
```bash tab="CLI"
--providers.swarm.endpoint=tcp://127.0.0.1:2375
# ...
```
providers:
swarm:
endpoint: "unix:///var/run/docker.sock"
[providers.swarm]
endpoint = "unix:///var/run/docker.sock"
--providers.swarm.endpoint=unix:///var/run/docker.sock
useBindPortIPTraefik 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.
??? example "Examples of usebindportip in different situations."
| port label | Container's binding | Routes to |
|--------------------|----------------------------------------------------|----------------|
| <a id="opt-row" href="#opt-row" title="#opt-row">-</a> | - | IntIP:IntPort |
| <a id="opt-row-2" href="#opt-row-2" title="#opt-row-2">-</a> | ExtPort:IntPort | IntIP:IntPort |
| <a id="opt-row-3" href="#opt-row-3" title="#opt-row-3">-</a> | ExtIp:ExtPort:IntPort | ExtIp:ExtPort |
| <a id="opt-LblPort" href="#opt-LblPort" title="#opt-LblPort">LblPort</a> | - | IntIp:LblPort |
| <a id="opt-LblPort-2" href="#opt-LblPort-2" title="#opt-LblPort-2">LblPort</a> | ExtIp:ExtPort:LblPort | ExtIp:ExtPort |
| <a id="opt-LblPort-3" href="#opt-LblPort-3" title="#opt-LblPort-3">LblPort</a> | ExtIp:ExtPort:OtherPort | IntIp:LblPort |
| <a id="opt-LblPort-4" href="#opt-LblPort-4" title="#opt-LblPort-4">LblPort</a> | 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."
providers:
swarm:
useBindPortIP: true
# ...
[providers.swarm]
useBindPortIP = true
# ...
--providers.swarm.useBindPortIP=true
# ...
defaultRuleThe 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 name can be accessed with the ContainerName identifier.
The service name can be accessed with the Name identifier.
The template has access to all the labels defined on this container with the Labels identifier.
providers:
swarm:
defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
[providers.swarm]
defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
# ...
--providers.swarm.defaultRule='Host(`{{ .Name }}.{{ index .Labels "customLabel"}}`)'
# ...
??? info "Default rule and Traefik service"
The exposure of the Traefik container, combined with the default rule mechanism,
can lead to create a router targeting itself in a loop.
In this case, to prevent an infinite loop,
Traefik adds an internal middleware to refuse the request if it comes from the same router.
constraintsThe 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.
!!! tip "Constraints key limitations"
Note that `traefik.*` is a reserved label namespace for configuration and can not be used as a key for custom constraints.
??? 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.+`)"
```
For additional information, refer to Restrict the Scope of Service Discovery.
providers:
swarm:
constraints: "Label(`a.label.name`,`foo`)"
# ...
[providers.swarm]
constraints = "Label(`a.label.name`,`foo`)"
# ...
--providers.swarm.constraints=Label(`a.label.name`,`foo`)
# ...
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.
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.
!!! tip "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 Swarm provider.
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).
Traefik retrieves the private IP and port of containers from the Docker API.
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 Swarm).
When exposing containers that are configured with host networking, the IP address of the host is resolved as follows:
<!-- TODO: verify and document the swarm mode case with container.Node.IPAddress coming from the API -->host.docker.internalhost.containers.internal, (Podman equivalent of host.docker.internal)127.0.0.1On 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
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.
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.
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":
docker service create \
--constraint=node.role==manager \
#... \
services:
traefik:
# ...
deploy:
placement:
constraints:
- node.role == manager
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.
Accessing the Docker API without any restriction is a security concern: If Traefik is attacked, then the attacker might get access to the underlying host.
As explained in the Docker Daemon Attack Surface documentation:
!!! quote
[...] only **trusted** users should be allowed to control your Docker daemon [...]
Expose the Docker socket over TCP or SSH, instead of the default Unix socket file. It allows different implementation levels of the AAA (Authentication, Authorization, Accounting) concepts, depending on your security assessment:
/var/run/docker.sock file{% include-markdown "includes/traefik-for-business-applications.md" %}