• Traefik & Docker
    • Configuration Examples
    • Provider Configuration Options
      • endpoint
      • useBindPortIP
      • exposedByDefault
      • network
      • defaultRule
      • swarmMode
      • swarmModeRefreshSeconds
      • constraints
      • tls
        • tls.ca
        • tls.caOptional
        • tls.cert
        • tls.key
        • tls.insecureSkipVerify
    • Routing Configuration Options
      • General
      • Routers
      • Services
      • Middleware
      • TCP
      • Specific Options
        • traefik.enable
        • traefik.docker.network
        • traefik.docker.lbswarm

    Traefik & Docker

    A Story of Labels & Containers

    Docker

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

    The Quick Start Uses Docker

    If you haven't already, maybe you'd like to go through the quick start that uses the docker provider!

    Configuration Examples

    Configuring Docker & Deploying / Exposing ServicesEnabling the docker provider

    1. [providers.docker]
    1. providers:
    2. docker: {}
    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(`my-domain`)

    Configuring Docker Swarm & Deploying / Exposing ServicesEnabling the docker provider (Swarm Mode)

    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
    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:2375"
    7. swarmMode: true
    1. --providers.docker.endpoint="tcp://127.0.0.1:2375"
    2. --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(`my-domain`)
    7. - traefik.http.services.my-container-service.loadbalancer.server.port=8080

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

    Provider Configuration Options

    Browse the Reference

    If you're in a hurry, maybe you'd rather go through the static and the dynamic configuration references.

    endpoint

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

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

    Traefik requires access to the docker socket to get its dynamic configuration.Security NotesDepending 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):

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

    Improved Security

    TraefikEE solves this problem by separating the control plane (connected to Docker) and the data plane (handling the requests).

    Resources about Docker's Security

    • KubeCon EU 2018 Keynote, Running with Scissors, from Liz Rice
    • Don't expose the Docker socket (not even to a container)
    • A thread on Stack Overflow about sharing the /var/run/docker.sock file
    • To DinD or not to DinDSecurity CompensationExpose the Docker socket over TCP, 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 "Protect the Docker daemon socket."

    • Authorization with the Docker Authorization Plugin Mechanism
    • 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).Additional Resources
    • Traefik issue GH-4174 about security with Docker socket
    • Inspecting Docker Activity with Socat
    • Letting Traefik run on Worker Nodes
    • Docker Socket Proxy from Tecnativa

    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.

    Using the docker.sockThe docker-compose file shares the docker sock with the Traefik container

    1. version: '3'
    2. services:
    3. traefik:
    4. image: traefik:v2.0 # The official v2.0 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.

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

    useBindPortIP

    Optional, Default=false

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

    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.XXX.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.XXX.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.XXX.loadbalancer.server.port that is set in the label.Examples of usebindportip in different situations.

    port labelContainer's bindingRoutes to
    --IntIP:IntPort
    -ExtPort:IntPortIntIP:IntPort
    -ExtIp:ExtPort:IntPortExtIp:ExtPort
    LblPort-IntIp:LblPort
    LblPortExtIp:ExtPort:LblPortExtIp:ExtPort
    LblPortExtIp:ExtPort:OtherPortIntIp:LblPort
    LblPortExtIp1:ExtPort1:IntPort1 & ExtIp2:LblPort:IntPort2ExtIp2:LblPort

    Note

    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", and IntPort stands for "internal network container's port."

    exposedByDefault

    Optional, Default=true

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

    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.

    network

    Optional, Default=empty

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

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

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

    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,augmented with the sprig template functions.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

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

    Activates the Swarm Mode.

    swarmModeRefreshSeconds

    Optional, Default=15

    1. [providers.docker]
    2. swarmModeRefreshSeconds = "30s"
    3. # ...
    1. providers:
    2. docker:
    3. swarmModeRefreshSeconds: "30s"
    4. # ...
    1. --providers.docker.swarmModeRefreshSeconds=30s
    2. # ...

    Defines the polling interval (in seconds) in Swarm Mode.

    constraints

    Optional, Default=""

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

    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.Constraints Expression Examples

    1. # Includes only containers having a label with key `a.label.name` and value `foo`
    2. constraints = "Label(`a.label.name`, `foo`)"
    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.+`)"

    See also Restrict the Scope of Service Discovery.

    tls

    Optional

    tls.ca

    TODO add description.

    1. [providers.docker.tls]
    2. ca = "path/to/ca.crt"
    1. providers:
    2. docker:
    3. tls:
    4. ca: path/to/ca.crt
    1. --providers.docker.tls.ca=path/to/ca.crt

    tls.caOptional

    TODO add description.

    1. [providers.docker.tls]
    2. caOptional = true
    1. providers:
    2. docker:
    3. tls:
    4. caOptional: true
    1. --providers.docker.tls.caOptional=true

    tls.cert

    TODO add description.

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

    tls.key

    TODO add description.

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

    tls.insecureSkipVerify

    TODO add description.

    1. [providers.docker.tls]
    2. insecureSkipVerify = true
    1. providers:
    2. docker:
    3. tls:
    4. insecureSkipVerify: true
    1. --providers.docker.tls.insecureSkipVerify=true

    Routing Configuration Options

    General

    Traefik creates, for each container, a corresponding service and router.

    The Service automatically gets a server per instance of the container,and the router automatically gets a rule defined by defaultRule (if no rule for it was defined in labels).

    Routers

    To update the configuration of the Router automatically attached to the container, add labels starting with traefik.http.routers.{name-of-your-choice}. and followed by the option you want to change. For example, to change the rule, you could add the label traefik.http.routers.my-container.rule=Host(my-domain).

    Every Router parameter can be updated this way.

    Services

    To update the configuration of the Service automatically attached to the container, add labels starting with traefik.http.services.{name-of-your-choice}., followed by the option you want to change. For example, to change the passhostheader behavior, you'd add the label traefik.http.services.{name-of-your-choice}.loadbalancer.passhostheader=false.

    Every Service parameter can be updated this way.

    Middleware

    You can declare pieces of middleware using labels starting with traefik.http.middlewares.{name-of-your-choice}., followed by the middleware type/options. For example, to declare a middleware redirectscheme named my-redirect, you'd write traefik.http.middlewares.my-redirect.redirectscheme.scheme: https.Declaring and Referencing a Middleware

    1. services:
    2. my-container:
    3. # ...
    4. labels:
    5. - traefik.http.middlewares.my-redirect.redirectscheme.scheme=https
    6. - traefik.http.routers.my-container.middlewares=my-redirect

    Conflicts in Declaration

    If you declare multiple middleware with the same name but with different parameters, the middleware fails to be declared.

    More information about available middlewares in the dedicated middlewares section.

    TCP

    You can declare TCP Routers and/or Services using labels.Declaring TCP Routers and Services

    1. services:
    2. my-container:
    3. # ...
    4. labels:
    5. - traefik.tcp.routers.my-router.rule="HostSNI(`my-host.com`)"
    6. - traefik.tcp.routers.my-router.tls="true"
    7. - traefik.tcp.services.my-service.loadbalancer.server.port="4123"

    TCP and HTTP

    If you declare a TCP Router/Service, it will prevent Traefik from automatically creating an HTTP Router/Service (like it does by default if no TCP Router/Service is defined).You can declare both a TCP Router/Service and an HTTP Router/Service for the same container (but you have to do so manually).

    Specific Options

    traefik.enable

    You can tell Traefik to consider (or not) the container by setting traefik.enable to true or false.

    This option overrides the value of exposedByDefault.

    traefik.docker.network

    Overrides the default docker network to use for connections to the container.

    If a container is linked to several networks, be sure to set the proper network name (you can check this with docker inspect <container_id>), otherwise it will randomly pick one (depending on how docker is returning them).

    Warning

    When deploying a stack from a compose file stack, the networks defined are prefixed with stack.

    traefik.docker.lbswarm

    Enables Swarm's inbuilt load balancer (only relevant in Swarm Mode).

    If you enable this option, Traefik will use the virtual IP provided by docker swarm instead of the containers IPs.Which means that Traefik will not perform any kind of load balancing and will delegate this task to swarm.