diff --git a/docs/README.md b/docs/README.md index f59d2aa..431fe60 100644 --- a/docs/README.md +++ b/docs/README.md @@ -520,7 +520,9 @@ services: > **Warning** > This feature is experimental. The behavior may change (or the feature may be removed entirely) without warning in a future release, even if the release is not a new major version. If you use this feature, or if you would like to use this feature but you require changes to it first, please [provide feedback in #2194](https://github.com/nginx-proxy/nginx-proxy/discussions/2194). Once we have collected enough feedback we will promote this feature to officially supported. -To enable HTTP keep-alive between `nginx-proxy` and a backend server, set the `com.github.nginx-proxy.nginx-proxy.keepalive` label on the server's container to the desired maximum number of idle connections. See the [nginx keepalive documentation](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) and the [Docker label documentation](https://docs.docker.com/config/labels-custom-metadata/) for details. +To enable HTTP keep-alive between `nginx-proxy` and backend server(s), set the `com.github.nginx-proxy.nginx-proxy.keepalive` label on the server's container either to `auto` or to the desired maximum number of idle connections. The `auto` setting will dynamically set the maximum number of idle connections to twice the number of servers listed in the corresponding `upstream{}` block, [per nginx recommendation](https://www.nginx.com/blog/avoiding-top-10-nginx-configuration-mistakes/#no-keepalives). + +See the [nginx keepalive documentation](https://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive) and the [Docker label documentation](https://docs.docker.com/config/labels-custom-metadata/) for details. ### Headers diff --git a/nginx.tmpl b/nginx.tmpl index 08606b9..e187a0f 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -249,7 +249,7 @@ {{- if exists $override }} include {{ $override }}; {{- else }} - {{- $keepalive := first (keys (groupByLabel .Containers "com.github.nginx-proxy.nginx-proxy.keepalive")) }} + {{- $keepalive := coalesce (first (keys (groupByLabel .Containers "com.github.nginx-proxy.nginx-proxy.keepalive"))) "disabled" }} location {{ .Path }} { {{- if eq .NetworkTag "internal" }} # Only allow traffic from internal clients @@ -263,14 +263,14 @@ root {{ trim .VhostRoot }}; include fastcgi_params; fastcgi_pass {{ trim .Upstream }}; - {{- if $keepalive }} + {{- if ne $keepalive "disabled" }} fastcgi_keep_conn on; {{- end }} {{- else if eq .Proto "grpc" }} grpc_pass {{ trim .Proto }}://{{ trim .Upstream }}; {{- else }} proxy_pass {{ trim .Proto }}://{{ trim .Upstream }}{{ trim .Dest }}; - set $upstream_keepalive {{ if $keepalive }}true{{ else }}false{{ end }}; + set $upstream_keepalive {{ if ne $keepalive "disabled" }}true{{ else }}false{{ end }}; {{- end }} {{- if (exists (printf "/etc/nginx/htpasswd/%s" .Host)) }} @@ -291,7 +291,7 @@ {{- define "upstream" }} upstream {{ .Upstream }} { - {{- $server_found := false }} + {{- $servers := 0 }} {{- $loadbalance := first (keys (groupByLabel .Containers "com.github.nginx-proxy.nginx-proxy.loadbalance")) }} {{- if $loadbalance }} # From the container's loadbalance label: @@ -306,18 +306,22 @@ upstream {{ .Upstream }} { {{- template "container_port" $args }} {{- $port := $args.port }} {{- if $ip }} - {{- $server_found = true }} + {{- $servers = add1 $servers }} server {{ $ip }}:{{ $port }}; {{- end }} {{- end }} {{- /* nginx-proxy/nginx-proxy#1105 */}} - {{- if not $server_found }} + {{- if lt $servers 1 }} # Fallback entry server 127.0.0.1 down; {{- end }} - {{- $keepalive := first (keys (groupByLabel .Containers "com.github.nginx-proxy.nginx-proxy.keepalive")) }} - {{- if $keepalive }} + {{- $keepalive := coalesce (first (keys (groupByLabel .Containers "com.github.nginx-proxy.nginx-proxy.keepalive"))) "disabled" }} + {{- if and (ne $keepalive "disabled") (gt $servers 0) }} + {{- if eq $keepalive "auto" }} + keepalive {{ mul $servers 2 }}; + {{- else }} keepalive {{ $keepalive }}; + {{- end }} {{- end }} } {{- end }} diff --git a/test/test_keepalive.py b/test/test_keepalive.py index b5b8353..c007cf1 100644 --- a/test/test_keepalive.py +++ b/test/test_keepalive.py @@ -20,10 +20,21 @@ def test_keepalive_disabled_other_headers_ok(docker_compose, nginxproxy): assert re.search(fr'(?m)^(?i:X-Real-IP): ', r.text) def test_keepalive_enabled(docker_compose, nginxproxy): + conf = nginxproxy.get_conf().decode('ASCII') + assert re.search(r"keepalive 64\;", conf) + r = nginxproxy.get("http://keepalive-enabled.nginx-proxy.test/headers") assert r.status_code == 200 assert not re.search(fr'(?m)^(?i:Connection):', r.text) +def test_keepalive_auto_enabled(docker_compose, nginxproxy): + conf = nginxproxy.get_conf().decode('ASCII') + assert re.search(r"keepalive 8\;", conf) + + r = nginxproxy.get("http://keepalive-auto.nginx-proxy.test/headers") + assert r.status_code == 200 + assert not re.search(fr'(?m)^(?i:Connection):', r.text) + def test_keepalive_enabled_other_headers_ok(docker_compose, nginxproxy): """See the docstring for the disabled case above.""" r = nginxproxy.get("http://keepalive-enabled.nginx-proxy.test/headers") diff --git a/test/test_keepalive.yml b/test/test_keepalive.yml index 62f5b25..6da66f0 100644 --- a/test/test_keepalive.yml +++ b/test/test_keepalive.yml @@ -18,6 +18,19 @@ services: VIRTUAL_HOST: keepalive-enabled.nginx-proxy.test labels: com.github.nginx-proxy.nginx-proxy.keepalive: "64" + + keepalive-auto: + image: web + deploy: + mode: replicated + replicas: 4 + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: keepalive-auto.nginx-proxy.test + labels: + com.github.nginx-proxy.nginx-proxy.keepalive: "auto" sut: image: nginxproxy/nginx-proxy:test