usebindportip can fall back on the container ip / port
This commit is contained in:
parent
78a9d20691
commit
6d4cf0d892
3 changed files with 108 additions and 74 deletions
|
@ -57,7 +57,9 @@ watch = true
|
|||
exposedByDefault = true
|
||||
|
||||
# Use the IP address from the binded port instead of the inner network one.
|
||||
# For specific use-case :)
|
||||
#
|
||||
# In case no IP address is attached to the binded port (or in case
|
||||
# there is no bind), the inner network one will be used as a fallback.
|
||||
#
|
||||
# Optional
|
||||
# Default: false
|
||||
|
@ -427,3 +429,25 @@ Segment labels override the default behavior.
|
|||
When running inside a container, Træfik will need network access through:
|
||||
|
||||
`docker network connect <network> <traefik-container>`
|
||||
|
||||
## usebindportip
|
||||
|
||||
The default behavior of Træfik is to route requests to the IP/Port of the matching container.
|
||||
When setting `usebindportip` to true, you tell Træfik to use the IP/Port attached to the container's binding instead of the inner network IP/Port.
|
||||
|
||||
When used in conjunction with the `traefik.port` label (that tells Træfik to route requests to a specific port), Træfik tries to find a binding with `traefik.port` port to select the container. If it can't find such a binding, Træfik falls back on the internal network IP of the container, but still uses the `traefik.port` that is set in the label.
|
||||
|
||||
Below is a recap of the behavior of `usebindportip` in different situations.
|
||||
|
||||
| traefik.port label | Container's binding | Routes to |
|
||||
|--------------------|----------------------------------------------------|----------------|
|
||||
| - | - | IntIP:IntPort |
|
||||
| - | ExtPort:IntPort | IntIP:IntPort |
|
||||
| - | ExtIp:ExtPort:IntPort | ExtIp:ExtPort |
|
||||
| LblPort | - | IntIp:LblPort |
|
||||
| LblPort | ExtIp:ExtPort:LblPort | ExtIp:ExtPort |
|
||||
| LblPort | ExtIp:ExtPort:OtherPort | IntIp:LblPort |
|
||||
| LblPort | ExtIp1:ExtPort1:IntPort1 & ExtIp2:LblPort:IntPort2 | ExtIp2: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."
|
|
@ -337,21 +337,22 @@ func (p *Provider) getPortBinding(container dockerData) (*nat.PortBinding, error
|
|||
|
||||
func (p *Provider) getIPPort(container dockerData) (string, string, error) {
|
||||
var ip, port string
|
||||
usedBound := false
|
||||
|
||||
if p.UseBindPortIP {
|
||||
portBinding, err := p.getPortBinding(container)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("unable to find a binding for the container %q: ignoring server", container.Name)
|
||||
}
|
||||
|
||||
if portBinding.HostIP == "0.0.0.0" {
|
||||
return "", "", fmt.Errorf("cannot determine the IP address (got 0.0.0.0) for the container %q: ignoring server", container.Name)
|
||||
}
|
||||
|
||||
log.Infof("Unable to find a binding for container %q, falling back on its internal IP/Port.", container.Name)
|
||||
} else if (portBinding.HostIP == "0.0.0.0") || (len(portBinding.HostIP) == 0) {
|
||||
log.Infof("Cannot determine the IP address (got %q) for %q's binding, falling back on its internal IP/Port.", portBinding.HostIP, container.Name)
|
||||
} else {
|
||||
ip = portBinding.HostIP
|
||||
port = portBinding.HostPort
|
||||
usedBound = true
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if !usedBound {
|
||||
ip = p.getIPAddress(container)
|
||||
port = getPort(container)
|
||||
}
|
||||
|
@ -359,6 +360,7 @@ func (p *Provider) getIPPort(container dockerData) (string, string, error) {
|
|||
if len(ip) == 0 {
|
||||
return "", "", fmt.Errorf("unable to find the IP address for the container %q: the server is ignored", container.Name)
|
||||
}
|
||||
|
||||
return ip, port, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1391,6 +1391,31 @@ func TestDockerGetIPPort(t *testing.T) {
|
|||
ip, port string
|
||||
expectsError bool
|
||||
}{
|
||||
{
|
||||
desc: "label traefik.port not set, no binding, falling back on the container's IP/Port",
|
||||
container: containerJSON(
|
||||
ports(nat.PortMap{
|
||||
"8080/tcp": {},
|
||||
}),
|
||||
withNetwork("testnet", ipv4("10.11.12.13"))),
|
||||
ip: "10.11.12.13",
|
||||
port: "8080",
|
||||
},
|
||||
{
|
||||
desc: "label traefik.port not set, single binding with port only, falling back on the container's IP/Port",
|
||||
container: containerJSON(
|
||||
withNetwork("testnet", ipv4("10.11.12.13")),
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": []nat.PortBinding{
|
||||
{
|
||||
HostPort: "8082",
|
||||
},
|
||||
},
|
||||
}),
|
||||
),
|
||||
ip: "10.11.12.13",
|
||||
port: "80",
|
||||
},
|
||||
{
|
||||
desc: "label traefik.port not set, binding with ip:port should create a route to the bound ip:port",
|
||||
container: containerJSON(
|
||||
|
@ -1406,6 +1431,52 @@ func TestDockerGetIPPort(t *testing.T) {
|
|||
ip: "1.2.3.4",
|
||||
port: "8081",
|
||||
},
|
||||
{
|
||||
desc: "label traefik.port set, no binding, falling back on the container's IP/traefik.port",
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
label.TraefikPort: "80",
|
||||
}),
|
||||
withNetwork("testnet", ipv4("10.11.12.13"))),
|
||||
ip: "10.11.12.13",
|
||||
port: "80",
|
||||
},
|
||||
{
|
||||
desc: "label traefik.port set, single binding with ip:port for the label, creates the route",
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
label.TraefikPort: "443",
|
||||
}),
|
||||
ports(nat.PortMap{
|
||||
"443/tcp": []nat.PortBinding{
|
||||
{
|
||||
HostIP: "5.6.7.8",
|
||||
HostPort: "8082",
|
||||
},
|
||||
},
|
||||
}),
|
||||
withNetwork("testnet", ipv4("10.11.12.13"))),
|
||||
ip: "5.6.7.8",
|
||||
port: "8082",
|
||||
},
|
||||
{
|
||||
desc: "label traefik.port set, no binding on the corresponding port, falling back on the container's IP/label.port",
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
label.TraefikPort: "80",
|
||||
}),
|
||||
ports(nat.PortMap{
|
||||
"443/tcp": []nat.PortBinding{
|
||||
{
|
||||
HostIP: "5.6.7.8",
|
||||
HostPort: "8082",
|
||||
},
|
||||
},
|
||||
}),
|
||||
withNetwork("testnet", ipv4("10.11.12.13"))),
|
||||
ip: "10.11.12.13",
|
||||
port: "80",
|
||||
},
|
||||
{
|
||||
desc: "label traefik.port set, multiple bindings on different ports, uses the label to select the correct (first) binding",
|
||||
container: containerJSON(
|
||||
|
@ -1454,69 +1525,6 @@ func TestDockerGetIPPort(t *testing.T) {
|
|||
ip: "5.6.7.8",
|
||||
port: "8082",
|
||||
},
|
||||
{
|
||||
desc: "label traefik.port set, single binding with ip:port for the label, creates the route",
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
label.TraefikPort: "443",
|
||||
}),
|
||||
ports(nat.PortMap{
|
||||
"443/tcp": []nat.PortBinding{
|
||||
{
|
||||
HostIP: "5.6.7.8",
|
||||
HostPort: "8082",
|
||||
},
|
||||
},
|
||||
}),
|
||||
withNetwork("testnet", ipv4("10.11.12.13"))),
|
||||
ip: "5.6.7.8",
|
||||
port: "8082",
|
||||
},
|
||||
{
|
||||
desc: "label traefik.port not set, single binding with port only, server ignored",
|
||||
container: containerJSON(
|
||||
ports(nat.PortMap{
|
||||
"80/tcp": []nat.PortBinding{
|
||||
{
|
||||
HostPort: "8082",
|
||||
},
|
||||
},
|
||||
}),
|
||||
withNetwork("testnet", ipv4("10.11.12.13"))),
|
||||
expectsError: true,
|
||||
},
|
||||
{
|
||||
desc: "label traefik.port not set, no binding, server ignored",
|
||||
container: containerJSON(
|
||||
withNetwork("testnet", ipv4("10.11.12.13"))),
|
||||
expectsError: true,
|
||||
},
|
||||
{
|
||||
desc: "label traefik.port set, no binding on the corresponding port, server ignored",
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
label.TraefikPort: "80",
|
||||
}),
|
||||
ports(nat.PortMap{
|
||||
"443/tcp": []nat.PortBinding{
|
||||
{
|
||||
HostIP: "5.6.7.8",
|
||||
HostPort: "8082",
|
||||
},
|
||||
},
|
||||
}),
|
||||
withNetwork("testnet", ipv4("10.11.12.13"))),
|
||||
expectsError: true,
|
||||
},
|
||||
{
|
||||
desc: "label traefik.port set, no binding, server ignored",
|
||||
container: containerJSON(
|
||||
labels(map[string]string{
|
||||
label.TraefikPort: "80",
|
||||
}),
|
||||
withNetwork("testnet", ipv4("10.11.12.13"))),
|
||||
expectsError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
|
@ -1529,7 +1537,7 @@ func TestDockerGetIPPort(t *testing.T) {
|
|||
dData.SegmentLabels = segmentProperties[""]
|
||||
|
||||
provider := &Provider{
|
||||
Network: "webnet",
|
||||
Network: "testnet",
|
||||
UseBindPortIP: true,
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue