From c6e783e7c316e72f5f6790649920685ad3a6a273 Mon Sep 17 00:00:00 2001 From: mpl Date: Thu, 26 Sep 2019 12:48:05 +0200 Subject: [PATCH] clarify automatic service creation/assignment with labels --- docs/content/routing/providers/docker.md | 28 +++++++++- docs/content/routing/providers/marathon.md | 28 +++++++++- docs/content/routing/providers/rancher.md | 28 +++++++++- .../routing/providers/service-by-label.md | 16 ++++++ docs/content/routing/routers/index.md | 10 +++- pkg/provider/docker/config_test.go | 51 +++++++++++++++++++ 6 files changed, 156 insertions(+), 5 deletions(-) create mode 100644 docs/content/routing/providers/service-by-label.md diff --git a/docs/content/routing/providers/docker.md b/docs/content/routing/providers/docker.md index 52347640d..1538b02cc 100644 --- a/docs/content/routing/providers/docker.md +++ b/docs/content/routing/providers/docker.md @@ -87,7 +87,7 @@ Attach labels to your containers and let Traefik do the rest! !!! info "Labels" - Labels are case insensitive. - - The complete list of labels can be found [the reference page](../../reference/dynamic-configuration/docker.md) + - The complete list of labels can be found in [the reference page](../../reference/dynamic-configuration/docker.md). ### General @@ -96,6 +96,32 @@ Traefik creates, for each container, a corresponding [service](../services/index 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). +#### Service definition + +--8<-- "content/routing/providers/service-by-label.md" + +??? example "Automatic service assignment with labels" + + With labels in a compose file + + ```yaml + labels: + - "traefik.http.routers.myproxy.rule=Host(`foo.com`)" + # service myservice gets automatically assigned to router myproxy + - "traefik.http.services.myservice.loadbalancer.server.port=80" + ``` + +??? example "Automatic service creation and assignment with labels" + + With labels in a compose file + + ```yaml + labels: + # no service specified or defined and yet one gets automatically created + # and assigned to router myproxy. + - "traefik.http.routers.myproxy.rule=Host(`foo.com`)" + ``` + ### Routers To update the configuration of the Router automatically attached to the container, diff --git a/docs/content/routing/providers/marathon.md b/docs/content/routing/providers/marathon.md index 3fbad1408..6c77076bb 100644 --- a/docs/content/routing/providers/marathon.md +++ b/docs/content/routing/providers/marathon.md @@ -10,7 +10,7 @@ See also [Marathon user guide](../../user-guides/marathon.md). !!! info "Labels" - Labels are case insensitive. - - The complete list of labels can be found [the reference page](../../reference/dynamic-configuration/marathon.md) + - The complete list of labels can be found in [the reference page](../../reference/dynamic-configuration/marathon.md). ### General @@ -19,6 +19,32 @@ Traefik creates, for each Marathon application, a corresponding [service](../ser The Service automatically gets a server per instance of the application, and the router automatically gets a rule defined by defaultRule (if no rule for it was defined in labels). +#### Service definition + +--8<-- "content/routing/providers/service-by-label.md" + +??? example "Automatic service assignment with labels" + + Service myservice gets automatically assigned to router myproxy. + + ```json + labels: { + "traefik.http.routers.myproxy.rule": "Host(`foo.com`)", + "traefik.http.services.myservice.loadbalancer.server.port": "80" + } + ``` + +??? example "Automatic service creation and assignment with labels" + + No service specified or defined, and yet one gets automatically created. + and assigned to router myproxy. + + ```json + labels: { + "traefik.http.routers.myproxy.rule": "Host(`foo.com`)" + } + ``` + ### Routers To update the configuration of the Router automatically attached to the application, diff --git a/docs/content/routing/providers/rancher.md b/docs/content/routing/providers/rancher.md index 9c4804b91..a37f80d25 100644 --- a/docs/content/routing/providers/rancher.md +++ b/docs/content/routing/providers/rancher.md @@ -17,7 +17,7 @@ Attach labels to your services and let Traefik do the rest! !!! info "Labels" - Labels are case insensitive. - - The complete list of labels can be found [the reference page](../../reference/dynamic-configuration/rancher.md) + - The complete list of labels can be found in [the reference page](../../reference/dynamic-configuration/rancher.md). ### General @@ -25,6 +25,32 @@ Traefik creates, for each rancher service, a corresponding [service](../services The Service automatically gets a server per container in this rancher service, and the router gets a default rule attached to it, based on the service name. +#### Service definition + +--8<-- "content/routing/providers/service-by-label.md" + +??? example "Automatic service assignment with labels" + + With labels in a compose file + + ```yaml + labels: + - "traefik.http.routers.myproxy.rule=Host(`foo.com`)" + # service myservice gets automatically assigned to router myproxy + - "traefik.http.services.myservice.loadbalancer.server.port=80" + ``` + +??? example "Automatic service creation and assignment with labels" + + With labels in a compose file + + ```yaml + labels: + # no service specified or defined and yet one gets automatically created + # and assigned to router myproxy. + - "traefik.http.routers.myproxy.rule=Host(`foo.com`)" + ``` + ### Routers To update the configuration of the Router automatically attached to the container, add labels starting with `traefik.routers.{name-of-your-choice}.` and followed by the option you want to change. diff --git a/docs/content/routing/providers/service-by-label.md b/docs/content/routing/providers/service-by-label.md new file mode 100644 index 000000000..bd16fd43e --- /dev/null +++ b/docs/content/routing/providers/service-by-label.md @@ -0,0 +1,16 @@ +In general when configuring a Traefik provider, +a service assigned to one (or several) router(s) must be defined as well for the routing to be functional. + +There are, however, exceptions when using label-based configurations: + +1. If a label defines a router (e.g. through a router Rule) +and a label defines a service (e.g. implicitly through a loadbalancer server port value), +but the router does not specify any service, +then that service is automatically assigned to the router. +1. If a label defines a router (e.g. through a router Rule) +but no service is defined, then a service is automatically created +and assigned to the router. + +!!! info "" + As one would expect, in either of these cases, if in addition a service is specified for the router, + then that service is the one assigned, regardless of whether it actually is defined or whatever else other services are defined. diff --git a/docs/content/routing/routers/index.md b/docs/content/routing/routers/index.md index bf717a8a1..0a935f826 100644 --- a/docs/content/routing/routers/index.md +++ b/docs/content/routing/routers/index.md @@ -288,8 +288,14 @@ The middlewares will take effect only if the rule matches, and before forwarding ### Service -You must attach a [service](../services/index.md) per router. -Services are the target for the router. +Each request must eventually be handled by a [service](../services/index.md), +which is why each router definition should include a service target, +which is basically where the request will be passed along to. + +In general, a service assigned to a router should have been defined, +but there are exceptions for label-based providers. +See the specific [docker](../providers/docker.md#service-definition), [rancher](../providers/rancher.md#service-definition), +or [marathon](../providers/marathon.md#service-definition) documentation. !!! important "HTTP routers can only target HTTP services (not TCP services)." diff --git a/pkg/provider/docker/config_test.go b/pkg/provider/docker/config_test.go index dcaa20d4a..e24e470d9 100644 --- a/pkg/provider/docker/config_test.go +++ b/pkg/provider/docker/config_test.go @@ -798,6 +798,57 @@ func Test_buildConfiguration(t *testing.T) { }, }, }, + { + desc: "one router, one specified but undefined service -> specified one is assigned, but automatic is created instead", + containers: []dockerData{ + { + ServiceName: "Test", + Name: "Test", + Labels: map[string]string{ + "traefik.http.routers.Router1.rule": "Host(`foo.com`)", + "traefik.http.routers.Router1.service": "Service1", + }, + NetworkSettings: networkSettings{ + Ports: nat.PortMap{ + nat.Port("80/tcp"): []nat.PortBinding{}, + }, + Networks: map[string]*networkData{ + "bridge": { + Name: "bridge", + Addr: "127.0.0.1", + }, + }, + }, + }, + }, + expected: &dynamic.Configuration{ + TCP: &dynamic.TCPConfiguration{ + Routers: map[string]*dynamic.TCPRouter{}, + Services: map[string]*dynamic.TCPService{}, + }, + HTTP: &dynamic.HTTPConfiguration{ + Routers: map[string]*dynamic.Router{ + "Router1": { + Service: "Service1", + Rule: "Host(`foo.com`)", + }, + }, + Middlewares: map[string]*dynamic.Middleware{}, + Services: map[string]*dynamic.Service{ + "Test": { + LoadBalancer: &dynamic.ServersLoadBalancer{ + Servers: []dynamic.Server{ + { + URL: "http://127.0.0.1:80", + }, + }, + PassHostHeader: true, + }, + }, + }, + }, + }, + }, { desc: "two containers with same service name and different passhostheader", containers: []dockerData{