Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Docker dynamic configuration for container with host or custom networks #5559

Closed
dduportal opened this issue Oct 1, 2019 · 16 comments
Closed
Labels

Comments

@dduportal
Copy link
Contributor

dduportal commented Oct 1, 2019

Do you want to request a feature or report a bug?

Proposal/Feature

What did you expect to see?

This proposal follows #5535.

As a Traefik user with the Docker provider,
When I start a backend container with the network mode host (see diagram below),
Then I want to configure Route and Service with labels as any Docker backend service

(N.B. one of the reason to have such a setup would be to expose a container with different network entrypoints, not only the HTTP service, or where you cannot NAT. Examples: streaming system with both TCP and UDP services, or a system like http://homebridge.io/).

traefik-docker-backend-host

Currently, Traefik is not creating the router and service associated to this "host" container, and print a logs like this:

traefik       | time="2019-10-04T16:27:16Z" level=error msg="unable to find the IP address for the container \"/homebridge\": the server is ignored" providerName=docker container=homebridge_gh-5559-backend-host-71e907c2f86adb92e43ce87bab13e1fc01f4570e8fbbf4d47e5760f2cf9b17a9

It sounds legit as the Docker API reports an empty field for the IP Address:

"NetworkSettings": {
            "Bridge": "",
            "SandboxID": "1ee5633542e17172125e8a2ebf722860b8139ba52320e2dcddbb56a20f79fc69",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {},
            "SandboxKey": "/var/run/docker/netns/default",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "",
            "Gateway": "",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "",
            "IPPrefixLen": 0,
            "IPv6Gateway": "",
            "MacAddress": "",
            "Networks": {
                "host": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "8e212bdf91ce7710ab6011138aaebfb37127dd8bd9e46d70427c5c8c5d37e71d",
                    "EndpointID": "f83f1a8f6fbb4fe7014c622f881302962011213bb70012d2a81c095d32512997",
                    "Gateway": "",
                    "IPAddress": "",
                    "IPPrefixLen": 0,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "",
                    "DriverOpts": null
                }
            }

There is a workaround, which is enabling the File provider, and creating the router + service manually, where the service points to the IP 172.17.0.1, which is the default docker gateway, that points to the interface docker0: if the backend container process listens on 0.0.0.0, then it can answer to docker0 upcoming requests as it is an host interface.

One of the ideas would be having Traefik able to detect that case, and create Routers + Service , with the Service IP set to the gateway, so the configuration could still happen.

It looks like that https://github.com/containous/traefik/blob/v2.0/pkg/provider/docker/config.go#L257 means 127.0.0.1 should be returned. But this is not expected to work (unless Traefik container is ALSO run as network=host) as 127.0.0.1 would be the loopback of the Traefik, which cannot route to the host interfaces as docker0.

@dduportal dduportal added the kind/proposal a proposal that needs to be discussed. label Oct 1, 2019
@dduportal
Copy link
Contributor Author

(Proposal written after a short discussion with @juliens )

@FuNK3Y
Copy link
Contributor

FuNK3Y commented Oct 13, 2019

Ha ! I am facing the problem as well, and was about to open an issue.

From my little chair, the following shall be done: instead of returning 127.0.0.1 the line 257 should return the IP of the docker0 interface (default = 172.17.0.1). This would work in every cases (traefik & exposed container in network_mode = host, or just the exposed container in network_mode = host).

The part that I haven't figured out is how to properly retrieve that IP from within the traefik container. If traefik networking mode is bridge this IP is the default gateway; if traefik is in host mode it would be the interface of the docker0 interface (but docker0 is only the default name - it can be renamed to anything...). Writing to code to achieve that while maintaining multi platform compatibility seems pretty complex.

An easier approach would be to implement the following pseudo-code (sorry - I don't speak golang)

gateway = net.LookupAddr("host.docker.internal")
if(gateway) return gateway
else return "127.0.0.1"

The sad part is that "host.docker.internal" is not yet available on linux (docker/for-linux#264), but it can be tackled manually in the meantime by using extra_hosts.

  • If traefik is in host mode or on a docker platform / version that does not provide "host.docker.internal", it will still return "127.0.0.1". This is not always ideal but it will be consistent with the current behavior
  • If traefik is running on a docker version / platform that provides "host.docker.internal" it shall work as intended

If someone can validate my understanding of the problem, I could try to create a PR

@man4j

This comment has been minimized.

@djhworld
Copy link

djhworld commented Jan 6, 2020

I have a use case where I have some containers that need to issue Wake-on-LAN packets to other devices on the network.

This works with network=host but the traefik routing breaks, I'll give the file provider a go (as mentioned in #5535) but ideally some label based solution would definitely be more attractive.

@gaieges
Copy link

gaieges commented Mar 8, 2020

I struggled to get the workaround to this solution working with homeassistant, and figured I'd share my solution for others until this issue gets addressed: https://gist.github.com/gaieges/936bdf91e01e4cc782eb047e5873089b

@teadur
Copy link

teadur commented Mar 18, 2020

Does the issue affect macvlan aswell ?
Guess i need to try solution from #5535 aswell.

@bjeanes

This comment has been minimized.

@bjeanes

This comment has been minimized.

@ldez

This comment has been minimized.

@bjeanes

This comment has been minimized.

@bjeanes

This comment has been minimized.

@bjeanes

This comment has been minimized.

@ldez

This comment has been minimized.

@bjeanes

This comment has been minimized.

@michaelkrieger
Copy link

Any more thoughts on this important feature? Have a number of containers which:

  • have networking mode of another container (a VPN provider) and the VPN container publishes the ports on the host
  • have network mode of host where the ports are published directly on the host

In both cases, the services need to be manually set in a file provider which seems silly. The URL I use for 'http.services.XXXX-srv.loadBalancer.servers' is 'http://172.17.0.1:PORT' but really any of the valid IPv4 gateway addresses work like 'http://172.18.0.1:PORT'. Of course, we want to use the right one. Traefik should simply use the gateway on its own network (which is available via the API or even ip route show default | awk '/default/ {print $3}') to reach the host.

Provided that the service is created by docker, it will listen on 0.0.0.0 and be fine. So long as it doesn't bind to a specific external IP (in which case a file provider is probably needed anyway), just using the gateway for the service is the way to go.

The logic would be:

  • if host networking, get the gateway IP of the traefik network, use that as the service IP
  • if not host networking, get the IP of the container service, and use that as the service IP

@kevinpollet
Copy link
Member

If we are not mistaken this issue has been closed by #5698.
Feel free to reopen it if you think that we missed something.

@traefik traefik locked and limited conversation to collaborators Aug 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests