From 325fd01ebbbe8af8fb684819e3db58dcc9c3091b Mon Sep 17 00:00:00 2001 From: Andy <59445582+rot169@users.noreply.github.com> Date: Sun, 23 Apr 2023 14:09:33 +0100 Subject: [PATCH 1/6] Support containers running --net=host (#1537) Detect if a target container is running host networking, and if so, use the IP address of the first bridge net gateway. --- nginx.tmpl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/nginx.tmpl b/nginx.tmpl index 2556acf..f322db9 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -67,6 +67,11 @@ # {{ .Name }} (ignored) {{- continue }} {{- end }} + {{- if eq .Name "host" }} + # {{ .Name }} (host network; using {{ (index $.globals.CurrentContainer.Networks 0).Name }} gateway) + {{- $ip = (index $.globals.CurrentContainer.Networks 0).Gateway }} + {{- continue }} + {{- end }} {{- if and (not (index $.globals.networks .Name)) (not $.globals.networks.host) }} # {{ .Name }} (unreachable) {{- continue }} From 882e9a3b3c4f99c2361b0191a106b34f09dfc4ce Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Fri, 28 Apr 2023 22:23:09 +0200 Subject: [PATCH 2/6] test: add tests for host mode fix --- .../test_host-network-mode.py | 13 +++++++++ .../test_host-network-mode.yml | 28 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 test/test_host-network-mode/test_host-network-mode.py create mode 100644 test/test_host-network-mode/test_host-network-mode.yml diff --git a/test/test_host-network-mode/test_host-network-mode.py b/test/test_host-network-mode/test_host-network-mode.py new file mode 100644 index 0000000..0c21348 --- /dev/null +++ b/test/test_host-network-mode/test_host-network-mode.py @@ -0,0 +1,13 @@ +import pytest + + +def test_forwards_to_bridge_network_container(docker_compose, nginxproxy): + r = nginxproxy.get("http://bridge-network.nginx-proxy.tld/port") + assert r.status_code == 200 + assert r.text == "answer from port 80\n" + + +def test_forwards_to_host_network_container(docker_compose, nginxproxy): + r = nginxproxy.get("http://host-network.nginx-proxy.tld/port") + assert r.status_code == 200 + assert r.text == "answer from port 8080\n" diff --git a/test/test_host-network-mode/test_host-network-mode.yml b/test/test_host-network-mode/test_host-network-mode.yml new file mode 100644 index 0000000..d8803ba --- /dev/null +++ b/test/test_host-network-mode/test_host-network-mode.yml @@ -0,0 +1,28 @@ +version: "2" + +networks: + net1: + +services: + bridge-network: + image: web + environment: + WEB_PORTS: "80" + VIRTUAL_HOST: "bridge-network.nginx-proxy.tld" + networks: + - net1 + + host-network: + image: web + environment: + WEB_PORTS: "8080" + VIRTUAL_HOST: "host-network.nginx-proxy.tld" + VIRTUAL_PORT: "8080" + network_mode: host + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + networks: + - net1 From b88d33d2f35b268c8e20f5f1dececa633bea1387 Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Tue, 9 May 2023 00:58:05 +0200 Subject: [PATCH 3/6] feat: handle multiple proxy networks --- nginx.tmpl | 13 ++++++++++--- .../test_host-network-mode.yml | 5 ++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/nginx.tmpl b/nginx.tmpl index f322db9..4aca11c 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -68,9 +68,16 @@ {{- continue }} {{- end }} {{- if eq .Name "host" }} - # {{ .Name }} (host network; using {{ (index $.globals.CurrentContainer.Networks 0).Name }} gateway) - {{- $ip = (index $.globals.CurrentContainer.Networks 0).Gateway }} - {{- continue }} + {{- range sortObjectsByKeysAsc $.globals.CurrentContainer.Networks "Name" }} + {{- if and . .Gateway }} + # container is in host network mode, using {{ .Name }} gateway IP + {{- $ip = .Gateway }} + {{- break }} + {{- end }} + {{- end }} + {{- if $ip }} + {{- continue }} + {{- end }} {{- end }} {{- if and (not (index $.globals.networks .Name)) (not $.globals.networks.host) }} # {{ .Name }} (unreachable) diff --git a/test/test_host-network-mode/test_host-network-mode.yml b/test/test_host-network-mode/test_host-network-mode.yml index d8803ba..1f2769c 100644 --- a/test/test_host-network-mode/test_host-network-mode.yml +++ b/test/test_host-network-mode/test_host-network-mode.yml @@ -2,6 +2,8 @@ version: "2" networks: net1: + internal: true + net2: services: bridge-network: @@ -10,7 +12,7 @@ services: WEB_PORTS: "80" VIRTUAL_HOST: "bridge-network.nginx-proxy.tld" networks: - - net1 + - net2 host-network: image: web @@ -26,3 +28,4 @@ services: - /var/run/docker.sock:/tmp/docker.sock:ro networks: - net1 + - net2 From 35b1493e16a504a2bce15ffb7bb7be4ba4a0296a Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Tue, 9 May 2023 19:31:42 +0200 Subject: [PATCH 4/6] feat: support proxy + container in host network mode --- nginx.tmpl | 6 +++++ test/conftest.py | 8 ++++++ .../test_proxy-host-network-mode.py | 13 ++++++++++ .../test_proxy-host-network-mode.yml | 26 +++++++++++++++++++ 4 files changed, 53 insertions(+) create mode 100644 test/test_host-network-mode/test_proxy-host-network-mode.py create mode 100644 test/test_host-network-mode/test_proxy-host-network-mode.yml diff --git a/nginx.tmpl b/nginx.tmpl index 4aca11c..3f4b019 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -68,6 +68,12 @@ {{- continue }} {{- end }} {{- if eq .Name "host" }} + {{- /* Handle containers in host nework mode */}} + {{- if (index $.globals.networks "host") }} + # both container and proxy are in host network mode, using localhost IP + {{- $ip = "127.0.0.1" }} + {{- continue }} + {{- end }} {{- range sortObjectsByKeysAsc $.globals.CurrentContainer.Networks "Name" }} {{- if and . .Gateway }} # container is in host network mode, using {{ .Name }} gateway IP diff --git a/test/conftest.py b/test/conftest.py index e7133e7..d58d504 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -160,6 +160,10 @@ def container_ip(container: Container): net_info = container.attrs["NetworkSettings"]["Networks"] if "bridge" in net_info: return net_info["bridge"]["IPAddress"] + + # container is running in host network mode + if "host" in net_info: + return "127.0.0.1" # not default bridge network, fallback on first network defined network_name = list(net_info.keys())[0] @@ -173,6 +177,10 @@ def container_ipv6(container): net_info = container.attrs["NetworkSettings"]["Networks"] if "bridge" in net_info: return net_info["bridge"]["GlobalIPv6Address"] + + # container is running in host network mode + if "host" in net_info: + return "::1" # not default bridge network, fallback on first network defined network_name = list(net_info.keys())[0] diff --git a/test/test_host-network-mode/test_proxy-host-network-mode.py b/test/test_host-network-mode/test_proxy-host-network-mode.py new file mode 100644 index 0000000..330334b --- /dev/null +++ b/test/test_host-network-mode/test_proxy-host-network-mode.py @@ -0,0 +1,13 @@ +import pytest + + +def test_forwards_to_host_network_container_1(docker_compose, nginxproxy): + r = nginxproxy.get("http://host-network-1.nginx-proxy.tld:8888/port") + assert r.status_code == 200 + assert r.text == "answer from port 8080\n" + + +def test_forwards_to_host_network_container_2(docker_compose, nginxproxy): + r = nginxproxy.get("http://host-network-2.nginx-proxy.tld:8888/port") + assert r.status_code == 200 + assert r.text == "answer from port 8181\n" diff --git a/test/test_host-network-mode/test_proxy-host-network-mode.yml b/test/test_host-network-mode/test_proxy-host-network-mode.yml new file mode 100644 index 0000000..32106e2 --- /dev/null +++ b/test/test_host-network-mode/test_proxy-host-network-mode.yml @@ -0,0 +1,26 @@ +version: "2" + +services: + host-network-1: + image: web + environment: + WEB_PORTS: "8080" + VIRTUAL_HOST: "host-network-1.nginx-proxy.tld" + VIRTUAL_PORT: "8080" + network_mode: host + + host-network-2: + image: web + environment: + WEB_PORTS: "8181" + VIRTUAL_HOST: "host-network-2.nginx-proxy.tld" + VIRTUAL_PORT: "8181" + network_mode: host + + sut: + image: nginxproxy/nginx-proxy:test + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + environment: + HTTP_PORT: 8888 + network_mode: host From 27f6cebb05d1d86998b62bfd025670c738d63c6f Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Tue, 9 May 2023 21:08:10 +0200 Subject: [PATCH 5/6] docs: host networking support documentation --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 106a2df..edcb91a 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,12 @@ docker network connect my-other-network my-nginx-proxy In this example, the `my-nginx-proxy` container will be connected to `my-network` and `my-other-network` and will be able to proxy to other containers attached to those networks. +### Host networking + +`nginx-proxy` is compatible with containers using Docker's [host networking](https://docs.docker.com/network/host/), both with the proxy connected to one or more [bridge network](https://docs.docker.com/network/bridge/) (default or user created) or running in host network mode itself. + +Proxyed containers running in host network mode **must** use the [`VIRTUAL_PORT](#virtual-ports) environment variable, as this is the only way for `nginx-proxy` to get the correct port (or a port at all) for those containers running. + ### Custom external HTTP/HTTPS ports If you want to use `nginx-proxy` with different external ports that the default ones of `80` for `HTTP` traffic and `443` for `HTTPS` traffic, you'll have to use the environment variable(s) `HTTP_PORT` and/or `HTTPS_PORT` in addition to the changes to the Docker port mapping. If you change the `HTTPS` port, the redirect for `HTTPS` traffic will also be configured to redirect to the custom port. Typical usage, here with the custom ports `1080` and `10443`: From e22caf7df9717aa695cd859588a79f5a3e1f276b Mon Sep 17 00:00:00 2001 From: Nicolas Duchon Date: Wed, 7 Jun 2023 07:45:01 +0200 Subject: [PATCH 6/6] doc: typo in documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index edcb91a..9173339 100644 --- a/README.md +++ b/README.md @@ -186,7 +186,7 @@ In this example, the `my-nginx-proxy` container will be connected to `my-network `nginx-proxy` is compatible with containers using Docker's [host networking](https://docs.docker.com/network/host/), both with the proxy connected to one or more [bridge network](https://docs.docker.com/network/bridge/) (default or user created) or running in host network mode itself. -Proxyed containers running in host network mode **must** use the [`VIRTUAL_PORT](#virtual-ports) environment variable, as this is the only way for `nginx-proxy` to get the correct port (or a port at all) for those containers running. +Proxyed containers running in host network mode **must** use the [`VIRTUAL_PORT](#virtual-ports) environment variable, as this is the only way for `nginx-proxy` to get the correct port (or a port at all) for those containers. ### Custom external HTTP/HTTPS ports