Traefik & Docker

    Attach labels to your containers and let Traefik do the rest!

    Traefik works with both Docker (standalone) Engine and .

    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.

    Configuring Docker & Deploying / Exposing Services

    Enabling the docker provider

    File (YAML)

    File (TOML)

    1. [providers.docker]

    CLI

    1. --providers.docker=true

    Attaching labels to containers (in your docker compose file)

    1. version: "3"
    2. services:
    3. my-container:
    4. # ...
    5. labels:
    6. - traefik.http.routers.my-container.rule=Host(`example.com`)

    Configuring Docker Swarm & Deploying / Exposing Services

    Enabling the docker provider (Swarm Mode)

    File (YAML)

    1. providers:
    2. docker:
    3. # swarm classic (1.12-)
    4. # endpoint: "tcp://127.0.0.1:2375"
    5. # docker swarm mode (1.12+)
    6. endpoint: "tcp://127.0.0.1:2377"
    7. swarmMode: true

    File (TOML)

    1. [providers.docker]
    2. # swarm classic (1.12-)
    3. # endpoint = "tcp://127.0.0.1:2375"
    4. # docker swarm mode (1.12+)
    5. endpoint = "tcp://127.0.0.1:2377"
    6. swarmMode = true

    CLI

    1. # swarm classic (1.12-)
    2. # --providers.docker.endpoint=tcp://127.0.0.1:2375
    3. # docker swarm mode (1.12+)
    4. --providers.docker.endpoint=tcp://127.0.0.1:2377
    5. --providers.docker.swarmMode=true

    Attach labels to services (not to containers) while in Swarm mode (in your docker compose file)

    1. version: "3"
    2. services:
    3. my-container:
    4. deploy:
    5. labels:
    6. - traefik.http.routers.my-container.rule=Host(`example.com`)
    7. - traefik.http.services.my-container-service.loadbalancer.server.port=8080

    When using Docker as a , Traefik uses container labels to retrieve its routing configuration.

    See the list of labels in the dedicated section.

    By default, Traefik watches for container level labels on a standalone Docker Engine.

    When using Docker Compose, labels are specified by the directive 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 multiple ports, or does not expose any port, then you must manually specify which port Traefik should use for communication by using the label traefik.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, 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

    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.

    Security Note

    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 :

    Quote

    […] only trusted users should be allowed to control your Docker daemon […]

    Solutions

    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:

    • Authentication with Client Certificates as described in
    • Authorize and filter requests to restrict possible actions with the TecnativaDocker Socket Proxy.
    • Authorization with the
    • 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, to only allows an identified set of actions for Traefik’s process (or the “socket exposer” process).
    • SSH public key authentication (SSH is supported with Docker > 18.09)

    More Resources and Examples

    To enable Docker Swarm (instead of standalone Docker) as a configuration provider, set the 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 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 ).

    Docker Swarm Mode follows the same rules as Docker API Access.

    Since the Swarm API is only exposed on the , these are the nodes that Traefik should be scheduled on by deploying Traefik with a constraint on the node “role”:

    With Docker CLI

    1. docker service create \
    2. --constraint=node.role==manager \
    3. #... \

    With Docker Compose

    1. version: '3'
    2. services:
    3. traefik:
    4. # ...
    5. deploy:
    6. placement:
    7. constraints:
    8. - 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.

    A good example can be found on .

    endpoint

    Required, Default=”unix:///var/run/docker.sock”

    See the sections and Docker Swarm API Access for more information.

    Using the docker.sock

    The docker-compose file shares the docker sock with the Traefik container

    1. version: '3'
    2. services:
    3. traefik:
    4. image: traefik:v2.6 # The official v2 Traefik docker image
    5. ports:
    6. - "80:80"
    7. volumes:
    8. - /var/run/docker.sock:/var/run/docker.sock

    We specify the docker.sock in traefik’s configuration file.

    File (YAML)

    1. providers:
    2. docker:
    3. endpoint: "unix:///var/run/docker.sock"
    4. # ...

    File (TOML)

    1. [providers.docker]
    2. endpoint = "unix:///var/run/docker.sock"
    3. # ...

    CLI

    1. --providers.docker.endpoint=unix:///var/run/docker.sock
    2. # ...

    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)

    1. providers:
    2. docker:
    3. # ...

    File (TOML)

    1. [providers.docker]
    2. endpoint = "ssh://traefik@192.168.2.5:2022"
    3. # ...

    CLI

    1. --providers.docker.endpoint=ssh://traefik@192.168.2.5:2022
    2. # ...

    File (YAML)

    1. providers:
    2. docker:
    3. endpoint: "unix:///var/run/docker.sock"

    File (TOML)

    1. [providers.docker]
    2. endpoint = "unix:///var/run/docker.sock"

    CLI

    1. --providers.docker.endpoint=unix:///var/run/docker.sock

    useBindPortIP

    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.

    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)

    1. providers:
    2. docker:
    3. useBindPortIP: true
    4. # ...

    File (TOML)

    1. [providers.docker]
    2. useBindPortIP = true
    3. # ...

    CLI

    exposedByDefault

    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 .

    File (YAML)

    1. providers:
    2. docker:
    3. exposedByDefault: false
    4. # ...

    File (TOML)

    1. [providers.docker]
    2. exposedByDefault = false
    3. # ...

    CLI

    1. --providers.docker.exposedByDefault=false
    2. # ...

    network

    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)

    1. providers:
    2. docker:
    3. network: test
    4. # ...

    File (TOML)

    1. [providers.docker]
    2. network = "test"
    3. # ...

    CLI

    1. --providers.docker.network=test
    2. # ...

    defaultRule

    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 . 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)

    1. providers:
    2. docker:
    3. defaultRule: "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
    4. # ...

    File (TOML)

    1. [providers.docker]
    2. defaultRule = "Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)"
    3. # ...

    CLI

    1. --providers.docker.defaultRule=Host(`{{ .Name }}.{{ index .Labels \"customLabel\"}}`)
    2. # ...

    Optional, Default=false

    Enables the Swarm Mode (instead of standalone Docker).

    File (YAML)

    1. providers:
    2. docker:
    3. swarmMode: true
    4. # ...

    File (TOML)

    1. [providers.docker]
    2. swarmMode = true
    3. # ...

    CLI

    1. # ...

    swarmModeRefreshSeconds

    Optional, Default=15

    File (YAML)

    1. providers:
    2. docker:
    3. swarmModeRefreshSeconds: 30
    4. # ...

    File (TOML)

    1. [providers.docker]
    2. swarmModeRefreshSeconds = 30
    3. # ...

    CLI

    1. --providers.docker.swarmModeRefreshSeconds=30
    2. # ...

    httpClientTimeout

    Optional, Default=0

    Defines the client timeout (in seconds) for HTTP connections. If its value is 0, no timeout is set.

    File (YAML)

    1. providers:
    2. docker:
    3. httpClientTimeout: 300
    4. # ...

    File (TOML)

    1. httpClientTimeout = 300
    2. # ...

    CLI

    1. --providers.docker.httpClientTimeout=300
    2. # ...

    watch

    Optional, Default=true

    Watch Docker Swarm events.

    File (YAML)

    1. providers:
    2. docker:
    3. watch: false
    4. # ...

    File (TOML)

    1. [providers.docker]
    2. watch = false
    3. # ...

    CLI

    1. --providers.docker.watch=false
    2. # ...

    constraints

    Optional, Default=””

    The constraints option can be set to an expression that Traefik matches against the container tags to determine whether to create any route for that container. If none of the container tags 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 Tag(`tag`), and TagRegex(`tag`) functions, as well as the usual boolean logic, as shown in examples below.

    Constraints Expression Examples

    1. # Excludes containers having any label with key `a.label.name` and value `foo`
    2. constraints = "!Label(`a.label.name`, `value`)"
    1. # With logical AND.
    2. constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
    1. # With logical OR.
    2. constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
    1. # With logical AND and OR, with precedence set by parentheses.
    2. constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
    1. # Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression.
    2. constraints = "LabelRegex(`a.label.name`, `a.+`)"

    For additional information, refer to Restrict the Scope of Service Discovery.

    File (YAML)

    1. providers:
    2. docker:
    3. constraints: "Label(`a.label.name`,`foo`)"
    4. # ...

    File (TOML)

    1. [providers.docker]
    2. constraints = "Label(`a.label.name`,`foo`)"
    3. # ...

    CLI

    1. --providers.docker.constraints=Label(`a.label.name`,`foo`)
    2. # ...

    tls

    Optional

    Defines the TLS configuration used for the secure connection to Docker.

    ca

    Optional

    ca is the path to the certificate authority used for the secure connection to Docker, it defaults to the system bundle.

    File (YAML)

    1. providers:
    2. docker:
    3. tls:
    4. ca: path/to/ca.crt

    File (TOML)

    1. [providers.docker.tls]
    2. ca = "path/to/ca.crt"

    CLI

    1. --providers.docker.tls.ca=path/to/ca.crt

    caOptional

    Optional

    The value of caOptional defines which policy should be used for the secure connection with TLS Client Authentication to Docker.

    If ca is undefined, this option will be ignored, and no client certificate will be requested during the handshake. Any provided certificate will thus never be verified.

    When this option is set to true, a client certificate is requested during the handshake but is not required. If a certificate is sent, it is required to be valid.

    When this option is set to false, a client certificate is requested during the handshake, and at least one valid certificate should be sent by the client.

    File (YAML)

    1. providers:
    2. docker:
    3. tls:
    4. caOptional: true

    File (TOML)

    1. [providers.docker.tls]
    2. caOptional = true

    CLI

    1. --providers.docker.tls.caOptional=true

    cert

    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)

    1. providers:
    2. docker:
    3. tls:
    4. cert: path/to/foo.cert
    5. key: path/to/foo.key

    File (TOML)

    1. [providers.docker.tls]
    2. cert = "path/to/foo.cert"
    3. key = "path/to/foo.key"

    CLI

    1. --providers.docker.tls.cert=path/to/foo.cert
    2. --providers.docker.tls.key=path/to/foo.key

    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)

    1. providers:
    2. docker:
    3. tls:
    4. cert: path/to/foo.cert
    5. key: path/to/foo.key

    File (TOML)

    1. [providers.docker.tls]
    2. cert = "path/to/foo.cert"
    3. key = "path/to/foo.key"

    CLI

    1. --providers.docker.tls.cert=path/to/foo.cert
    2. --providers.docker.tls.key=path/to/foo.key

    insecureSkipVerify

    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)

    1. providers:
    2. docker:
    3. tls:

    File (TOML)