1
0
mirror of https://github.com/thib8956/nginx-proxy synced 2025-02-24 01:38:15 +00:00

fix: Generate at most one server directive per container

This commit is contained in:
Richard Hansen 2023-01-28 00:19:21 -05:00
parent bcec2d9075
commit 6162427c45
3 changed files with 50 additions and 7 deletions

View File

@ -118,6 +118,7 @@ upstream {{ .Upstream }} {
# Container: {{ $container.Name }} # Container: {{ $container.Name }}
{{- /* If only 1 port exposed, use that as a default, else 80 */}} {{- /* If only 1 port exposed, use that as a default, else 80 */}}
{{- $defaultPort := (when (eq (len $container.Addresses) 1) (first $container.Addresses) (dict "Port" "80")).Port }} {{- $defaultPort := (when (eq (len $container.Addresses) 1) (first $container.Addresses) (dict "Port" "80")).Port }}
{{- $ip := "" }}
{{- $port := (coalesce $container.Env.VIRTUAL_PORT $defaultPort) }} {{- $port := (coalesce $container.Env.VIRTUAL_PORT $defaultPort) }}
{{- $addr_obj := where $container.Addresses "Port" $port | first }} {{- $addr_obj := where $container.Addresses "Port" $port | first }}
# Exposed ports:{{ range $container.Addresses }} {{ .Port }}/{{ .Proto }}{{ else }} (none){{ end }} # Exposed ports:{{ range $container.Addresses }} {{ .Port }}/{{ .Proto }}{{ else }} (none){{ end }}
@ -141,23 +142,37 @@ upstream {{ .Upstream }} {
# {{ $containerNetwork.Name }} (unreachable) # {{ $containerNetwork.Name }} (unreachable)
{{- continue }} {{- continue }}
{{- end }} {{- end }}
{{- /*
* Do not emit multiple `server` directives for this container
* if it is reachable over multiple networks. This avoids
* accidentally inflating the effective round-robin weight of
* this container due to the redundant upstreams that nginx sees
* as belonging to distinct servers.
*/}}
{{- if $ip }}
# {{ $containerNetwork.Name }} (ignored; reachable but redundant)
{{- continue }}
{{- end }}
# {{ $containerNetwork.Name }} (reachable) # {{ $containerNetwork.Name }} (reachable)
{{- /* {{- /*
* If we got the containers from swarm and this container's * If we got the containers from swarm and this container's
* port is published to host, use host IP:PORT. * port is published to host, use host IP:PORT.
*/}} */}}
{{- if and $container.Node.ID $addr_obj $addr_obj.HostPort }} {{- if and $container.Node.ID $addr_obj $addr_obj.HostPort }}
{{- $server_found = true }} {{- $ip = $container.Node.Address.IP }}
server {{ $container.Node.Address.IP }}:{{ $addr_obj.HostPort }}; {{- $port = $addr_obj.HostPort }}
{{- else if and $containerNetwork $containerNetwork.IP }} {{- else if and $containerNetwork $containerNetwork.IP }}
{{- $server_found = true }} {{- $ip = $containerNetwork.IP }}
server {{ $containerNetwork.IP }}:{{ $port }};
{{- else }} {{- else }}
# /!\ No IP for this network! # /!\ No IP for this network!
{{- end }} {{- end }}
{{- else }} {{- else }}
# (none) # (none)
{{- end }} {{- end }}
{{- if $ip }}
{{- $server_found = true }}
server {{ $ip }}:{{ $port }};
{{- end }}
{{- end }} {{- end }}
{{- /* nginx-proxy/nginx-proxy#1105 */}} {{- /* nginx-proxy/nginx-proxy#1105 */}}
{{- if not $server_found }} {{- if not $server_found }}

View File

@ -1,15 +1,28 @@
import re
import pytest import pytest
def test_unknown_virtual_host(docker_compose, nginxproxy): def test_unknown_virtual_host(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/") r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503 assert r.status_code == 503
def test_forwards_to_web1(docker_compose, nginxproxy): def test_forwards_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.local/port") r = nginxproxy.get("http://web1.nginx-proxy.local/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 81\n" assert r.text == "answer from port 81\n"
def test_forwards_to_web2(docker_compose, nginxproxy): def test_forwards_to_web2(docker_compose, nginxproxy):
r = nginxproxy.get("http://web2.nginx-proxy.local/port") r = nginxproxy.get("http://web2.nginx-proxy.local/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 82\n" assert r.text == "answer from port 82\n"
def test_multipath(docker_compose, nginxproxy):
r = nginxproxy.get("http://web3.nginx-proxy.test/port")
assert r.status_code == 200
assert r.text == "answer from port 83\n"
cfg = nginxproxy.get_conf().decode()
lines = cfg.splitlines()
web3_server_lines = [l for l in lines
if re.search(r'(?m)^\s*server\s+[^\s]*:83;\s*$', l)]
assert len(web3_server_lines) == 1

View File

@ -3,6 +3,8 @@ version: '2'
networks: networks:
net1: {} net1: {}
net2: {} net2: {}
net3a: {}
net3b: {}
services: services:
nginx-proxy: nginx-proxy:
@ -12,6 +14,8 @@ services:
networks: networks:
- net1 - net1
- net2 - net2
- net3a
- net3b
web1: web1:
image: web image: web
@ -32,3 +36,14 @@ services:
VIRTUAL_HOST: web2.nginx-proxy.local VIRTUAL_HOST: web2.nginx-proxy.local
networks: networks:
- net2 - net2
web3:
image: web
expose:
- "83"
environment:
WEB_PORTS: 83
VIRTUAL_HOST: web3.nginx-proxy.test
networks:
- net3a
- net3b