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

Merge pull request #2570 from nginx-proxy/test/refactor-darwin

tests: factor out base nginx-proxy config and enable local testing on macOS / Darwin
This commit is contained in:
Nicolas Duchon 2025-01-05 11:37:45 +01:00 committed by GitHub
commit 691724c81f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
116 changed files with 564 additions and 616 deletions

View File

@ -57,13 +57,39 @@ This test suite uses [pytest](http://doc.pytest.org/en/latest/). The [conftest.p
### docker_compose fixture
When using the `docker_compose` fixture in a test, pytest will try to find a yml file named after your test module filename. For instance, if your test module is `test_example.py`, then the `docker_compose` fixture will try to load a `test_example.yml` [docker compose file](https://docs.docker.com/compose/compose-file/).
When using the `docker_compose` fixture in a test, pytest will try to start the [Docker Compose](https://docs.docker.com/compose/) services corresponding to the current test module, based on the test module filename.
Once the docker compose file found, the fixture will remove all containers, run `docker compose up`, and finally your test will be executed.
By default, if your test module file is `test/test_subdir/test_example.py`, then the `docker_compose` fixture will try to load the following files, [merging them](https://docs.docker.com/reference/compose-file/merge/) in this order:
The fixture will run the _docker compose_ command with the `-f` option to load the given compose file. So you can test your docker compose file syntax by running it yourself with:
1. `test/compose.base.yml`
2. `test/test_subdir/compose.base.override.yml` (if it exists)
3. `test/test_subdir/test_example.yml`
docker compose -f test_example.yml up -d
The fixture will run the _docker compose_ command with the `-f` option to load the given compose files. So you can test your docker compose file syntax by running it yourself with:
docker compose -f test/compose.base.yml -f test/test_subdir/test_example.yml up -d
The first file contains the base configuration of the nginx-proxy container common to most tests:
```yaml
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
container_name: nginx-proxy
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
ports:
- "80:80"
- "443:443"
```
The second optional file allow you to override this base configuration for all test modules in a subfolder.
The third file contains the services and overrides specific to a given test module.
This automatic merge can be bypassed by using a file named `test_example.base.yml` (instead of `test_example.yml`). When this file exist, it will be the only one used by the test and no merge with other compose files will automatically occur.
The `docker_compose` fixture also set the `PYTEST_MODULE_PATH` environment variable to the absolute path of the current test module directory, so it can be used to mount files or directory relatives to the current test.
In the case you are running pytest from within a docker container, the `docker_compose` fixture will make sure the container running pytest is attached to all docker networks. That way, your test will be able to reach any of them.
@ -71,7 +97,10 @@ In your tests, you can use the `docker_compose` variable to query and command th
Also this fixture alters the way the python interpreter resolves domain names to IP addresses in the following ways:
Any domain name containing the substring `nginx-proxy` will resolve to the IP address of the container that was created from the `nginxproxy/nginx-proxy:test` image. So all the following domain names will resolve to the nginx-proxy container in tests:
Any domain name containing the substring `nginx-proxy` will resolve to `127.0.0.1` if the tests are executed on a Darwin (macOS) system, otherwise the IP address of the container that was created from the `nginxproxy/nginx-proxy:test` image.
So, in tests, all the following domain names will resolve to either localhost or the nginx-proxy container's IP:
- `nginx-proxy`
- `nginx-proxy.com`
- `www.nginx-proxy.com`
@ -80,14 +109,16 @@ Any domain name containing the substring `nginx-proxy` will resolve to the IP ad
- `whatever.nginx-proxyooooooo`
- ...
Any domain name ending with `XXX.container.docker` will resolve to the IP address of the XXX container.
Any domain name ending with `XXX.container.docker` will resolve to `127.0.0.1` if the tests are executed on a Darwin (macOS) system, otherwise the IP address of the container named `XXX`.
So, on a non-Darwin system:
- `web1.container.docker` will resolve to the IP address of the `web1` container
- `f00.web1.container.docker` will resolve to the IP address of the `web1` container
- `anything.whatever.web2.container.docker` will resolve to the IP address of the `web2` container
Otherwise, domain names are resoved as usual using your system DNS resolver.
### nginxproxy fixture
The `nginxproxy` fixture will provide you with a replacement for the python [requests](https://pypi.python.org/pypi/requests/) module. This replacement will just repeat up to 30 times a requests if it receives the HTTP error 404 or 502. This error occurs when you try to send queries to nginx-proxy too early after the container creation.

9
test/compose.base.yml Normal file
View File

@ -0,0 +1,9 @@
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
container_name: nginx-proxy
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
ports:
- "80:80"
- "443:443"

View File

@ -1,11 +1,14 @@
import contextlib
import logging
import os
import pathlib
import platform
import re
import shlex
import socket
import subprocess
import time
from io import StringIO
from typing import Iterator, List, Optional
import backoff
@ -20,12 +23,13 @@ from packaging.version import Version
from requests import Response
from urllib3.util.connection import HAS_IPV6
logging.basicConfig(level=logging.INFO)
logging.getLogger('backoff').setLevel(logging.INFO)
logging.getLogger('DNS').setLevel(logging.DEBUG)
logging.getLogger('requests.packages.urllib3.connectionpool').setLevel(logging.WARN)
CA_ROOT_CERTIFICATE = os.path.join(os.path.dirname(__file__), 'certs/ca-root.crt')
CA_ROOT_CERTIFICATE = pathlib.Path(__file__).parent.joinpath("certs/ca-root.crt")
PYTEST_RUNNING_IN_CONTAINER = os.environ.get('PYTEST_RUNNING_IN_CONTAINER') == "1"
FORCE_CONTAINER_IPV6 = False # ugly global state to consider containers' IPv6 address instead of IPv4
@ -71,8 +75,8 @@ class RequestsForDocker:
"""
def __init__(self):
self.session = requests.Session()
if os.path.isfile(CA_ROOT_CERTIFICATE):
self.session.verify = CA_ROOT_CERTIFICATE
if CA_ROOT_CERTIFICATE.is_file():
self.session.verify = CA_ROOT_CERTIFICATE.as_posix()
@staticmethod
def get_nginx_proxy_container() -> Container:
@ -217,8 +221,8 @@ def nginx_proxy_dns_resolver(domain_name: str) -> Optional[str]:
def docker_container_dns_resolver(domain_name: str) -> Optional[str]:
"""
if domain name is of the form "XXX.container.docker" or "anything.XXX.container.docker", return the ip address of the docker container
named XXX.
if domain name is of the form "XXX.container.docker" or "anything.XXX.container.docker",
return the ip address of the docker container named XXX.
:return: IP or None
"""
@ -248,7 +252,10 @@ def monkey_patch_urllib_dns_resolver():
"""
Alter the behavior of the urllib DNS resolver so that any domain name
containing substring 'nginx-proxy' will resolve to the IP address
of the container created from image 'nginxproxy/nginx-proxy:test'.
of the container created from image 'nginxproxy/nginx-proxy:test',
or to 127.0.0.1 on Darwin.
see https://docs.docker.com/desktop/features/networking/#i-want-to-connect-to-a-container-from-the-host
"""
prv_getaddrinfo = socket.getaddrinfo
dns_cache = {}
@ -262,7 +269,12 @@ def monkey_patch_urllib_dns_resolver():
pytest.skip("This system does not support IPv6")
# custom DNS resolvers
ip = nginx_proxy_dns_resolver(args[0])
ip = None
# Docker Desktop can't route traffic directly to Linux containers.
if platform.system() == "Darwin":
ip = "127.0.0.1"
if ip is None:
ip = nginx_proxy_dns_resolver(args[0])
if ip is None:
ip = docker_container_dns_resolver(args[0])
if ip is not None:
@ -298,20 +310,40 @@ def get_nginx_conf_from_container(container: Container) -> bytes:
return conffile.read()
def docker_compose_up(compose_file: str):
logging.info(f'{DOCKER_COMPOSE} -f {compose_file} up -d')
def __prepare_and_execute_compose_cmd(compose_files: List[str], project_name: str, cmd: str):
"""
Prepare and execute the Docker Compose command with the provided compose files and project name.
"""
compose_cmd = StringIO()
compose_cmd.write(DOCKER_COMPOSE)
compose_cmd.write(f" --project-name {project_name}")
for compose_file in compose_files:
compose_cmd.write(f" --file {compose_file}")
compose_cmd.write(f" {cmd}")
logging.info(compose_cmd.getvalue())
try:
subprocess.check_output(shlex.split(f'{DOCKER_COMPOSE} -f {compose_file} up -d'), stderr=subprocess.STDOUT)
subprocess.check_output(shlex.split(compose_cmd.getvalue()), stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
pytest.fail(f"Error while running '{DOCKER_COMPOSE} -f {compose_file} up -d':\n{e.output}", pytrace=False)
pytest.fail(f"Error while running '{compose_cmd.getvalue()}':\n{e.output}", pytrace=False)
def docker_compose_down(compose_file: str):
logging.info(f'{DOCKER_COMPOSE} -f {compose_file} down -v')
try:
subprocess.check_output(shlex.split(f'{DOCKER_COMPOSE} -f {compose_file} down -v'), stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
pytest.fail(f"Error while running '{DOCKER_COMPOSE} -f {compose_file} down -v':\n{e.output}", pytrace=False)
def docker_compose_up(compose_files: List[str], project_name: str):
"""
Execute compose up --detach with the provided compose files and project name.
"""
if compose_files is None or len(compose_files) == 0:
pytest.fail(f"No compose file passed to docker_compose_up", pytrace=False)
__prepare_and_execute_compose_cmd(compose_files, project_name, cmd="up --detach")
def docker_compose_down(compose_files: List[str], project_name: str):
"""
Execute compose down --volumes with the provided compose files and project name.
"""
if compose_files is None or len(compose_files) == 0:
pytest.fail(f"No compose file passed to docker_compose_up", pytrace=False)
__prepare_and_execute_compose_cmd(compose_files, project_name, cmd="down --volumes")
def wait_for_nginxproxy_to_be_ready():
@ -330,35 +362,47 @@ def wait_for_nginxproxy_to_be_ready():
@pytest.fixture
def docker_compose_file(request: FixtureRequest) -> Iterator[Optional[str]]:
"""Fixture naming the docker compose file to consider.
def docker_compose_files(request: FixtureRequest) -> List[str]:
"""Fixture returning the docker compose files to consider:
If a YAML file exists with the same name as the test module (with the `.py` extension replaced
with `.yml` or `.yaml`), use that. Otherwise, use `docker-compose.yml` in the same directory
as the test module.
If a YAML file exists with the same name as the test module (with the `.py` extension
replaced with `.base.yml`, ie `test_foo.py`-> `test_foo.base.yml`) and in the same
directory as the test module, use only that file.
Otherwise, merge the following files in this order:
- the `compose.base.yml` file in the parent `test` directory.
- if present in the same directory as the test module, the `compose.base.override.yml` file.
- the YAML file named after the current test module (ie `test_foo.py`-> `test_foo.yml`)
Tests can override this fixture to specify a custom location.
"""
test_module_dir = os.path.dirname(request.module.__file__)
yml_file = os.path.join(test_module_dir, f"{request.module.__name__}.yml")
yaml_file = os.path.join(test_module_dir, f"{request.module.__name__}.yaml")
default_file = os.path.join(test_module_dir, 'docker-compose.yml')
compose_files: List[str] = []
test_module_path = pathlib.Path(request.module.__file__).parent
docker_compose_file = None
module_base_file = test_module_path.joinpath(f"{request.module.__name__}.base.yml")
if module_base_file.is_file():
return [module_base_file.as_posix()]
if os.path.isfile(yml_file):
docker_compose_file = yml_file
elif os.path.isfile(yaml_file):
docker_compose_file = yaml_file
elif os.path.isfile(default_file):
docker_compose_file = default_file
global_base_file = test_module_path.parent.joinpath("compose.base.yml")
if global_base_file.is_file():
compose_files.append(global_base_file.as_posix())
if docker_compose_file is None:
logging.error("Could not find any docker compose file named either '{0}.yml', '{0}.yaml' or 'docker-compose.yml'".format(request.module.__name__))
else:
logging.debug(f"using docker compose file {docker_compose_file}")
module_base_override_file = test_module_path.joinpath("compose.base.override.yml")
if module_base_override_file.is_file():
compose_files.append(module_base_override_file.as_posix())
yield docker_compose_file
module_compose_file = test_module_path.joinpath(f"{request.module.__name__}.yml")
if module_compose_file.is_file():
compose_files.append(module_compose_file.as_posix())
if not module_base_file.is_file() and not module_compose_file.is_file():
logging.error(
f"Could not find any docker compose file named '{module_base_file.name}' or '{module_compose_file.name}'"
)
logging.debug(f"using docker compose files {compose_files}")
return compose_files
def connect_to_network(network: Network) -> Optional[Network]:
@ -428,30 +472,33 @@ def connect_to_all_networks() -> List[Network]:
class DockerComposer(contextlib.AbstractContextManager):
def __init__(self):
self._networks = None
self._docker_compose_file = None
self._docker_compose_files = None
self._project_name = None
def __exit__(self, *exc_info):
self._down()
def _down(self):
if self._docker_compose_file is None:
if self._docker_compose_files is None:
return
for network in self._networks:
disconnect_from_network(network)
docker_compose_down(self._docker_compose_file)
docker_compose_down(self._docker_compose_files, self._project_name)
self._docker_compose_file = None
self._project_name = None
def compose(self, docker_compose_file: Optional[str]):
if docker_compose_file == self._docker_compose_file:
def compose(self, docker_compose_files: List[str], project_name: str):
if docker_compose_files == self._docker_compose_files and project_name == self._project_name:
return
self._down()
if docker_compose_file is None:
if docker_compose_files is None or project_name is None:
return
docker_compose_up(docker_compose_file)
docker_compose_up(docker_compose_files, project_name)
self._networks = connect_to_all_networks()
wait_for_nginxproxy_to_be_ready()
time.sleep(3) # give time to containers to be ready
self._docker_compose_file = docker_compose_file
self._docker_compose_files = docker_compose_files
self._project_name = project_name
###############################################################################
@ -462,14 +509,14 @@ class DockerComposer(contextlib.AbstractContextManager):
@pytest.fixture(scope="module")
def docker_composer() -> Iterator[DockerComposer]:
def docker_composer() -> Iterator[DockerComposer]:
with DockerComposer() as d:
yield d
@pytest.fixture
def ca_root_certificate() -> Iterator[str]:
yield CA_ROOT_CERTIFICATE
def ca_root_certificate() -> str:
return CA_ROOT_CERTIFICATE.as_posix()
@pytest.fixture
@ -480,16 +527,29 @@ def monkey_patched_dns():
@pytest.fixture
def docker_compose(monkey_patched_dns, docker_composer, docker_compose_file) -> Iterator[DockerClient]:
"""Ensures containers described in a docker compose file are started.
A custom docker compose file name can be specified by overriding the `docker_compose_file`
fixture.
Also, in the case where pytest is running from a docker container, this fixture makes sure
our container will be attached to all the docker networks.
def docker_compose(
request: FixtureRequest,
monkeypatch,
monkey_patched_dns,
docker_composer,
docker_compose_files
) -> Iterator[DockerClient]:
"""
docker_composer.compose(docker_compose_file)
Ensures containers necessary for the test module are started in a compose project,
and set the environment variable `PYTEST_MODULE_PATH` to the test module's parent folder.
A list of custom docker compose files path can be specified by overriding
the `docker_compose_file` fixture.
Also, in the case where pytest is running from a docker container, this fixture
makes sure our container will be attached to all the docker networks.
"""
pytest_module_path = pathlib.Path(request.module.__file__).parent
monkeypatch.setenv("PYTEST_MODULE_PATH", pytest_module_path.as_posix())
project_name = request.module.__name__
docker_composer.compose(docker_compose_files, project_name)
yield docker_client
@ -511,11 +571,11 @@ def nginxproxy() -> Iterator[RequestsForDocker]:
@pytest.fixture
def acme_challenge_path() -> Iterator[str]:
def acme_challenge_path() -> str:
"""
Provides fake Let's Encrypt ACME challenge path used in certain tests
"""
yield ".well-known/acme-challenge/test-filename"
return ".well-known/acme-challenge/test-filename"
###############################################################################
#

View File

@ -0,0 +1,6 @@
services:
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ${PYTEST_MODULE_PATH}/certs:/etc/nginx/certs:ro
- ${PYTEST_MODULE_PATH}/acme_root:/usr/share/nginx/html:ro

View File

@ -1,4 +1,8 @@
services:
nginx-proxy:
environment:
ACME_HTTP_CHALLENGE_LOCATION: "false"
web1:
image: web
expose:
@ -34,12 +38,3 @@ services:
VIRTUAL_HOST: "web4.nginx-proxy.tld"
HTTPS_METHOD: noredirect
ACME_HTTP_CHALLENGE_LOCATION: "true"
sut:
image: nginxproxy/nginx-proxy:test
environment:
ACME_HTTP_CHALLENGE_LOCATION: "false"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html:ro

View File

@ -34,10 +34,3 @@ services:
VIRTUAL_HOST: "web4.nginx-proxy.tld"
HTTPS_METHOD: noredirect
ACME_HTTP_CHALLENGE_LOCATION: "false"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html:ro

View File

@ -1,4 +1,8 @@
services:
nginx-proxy:
environment:
ACME_HTTP_CHALLENGE_LOCATION: "legacy"
web1:
image: web
expose:
@ -15,12 +19,3 @@ services:
WEB_PORTS: "82"
VIRTUAL_HOST: "web2.nginx-proxy.tld"
HTTPS_METHOD: noredirect
sut:
image: nginxproxy/nginx-proxy:test
environment:
ACME_HTTP_CHALLENGE_LOCATION: "legacy"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html:ro

View File

@ -1,6 +1,5 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./50x.html:/usr/share/nginx/html/errors/50x.html:ro
- ${PYTEST_MODULE_PATH}/50x.html:/usr/share/nginx/html/errors/50x.html:ro

View File

@ -1,10 +1,9 @@
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/default_location:ro
- ./my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/web3.nginx-proxy.example_location:ro
- ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/default_location:ro
- ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/web3.nginx-proxy.example_location:ro
web1:
image: web

View File

@ -1,9 +1,8 @@
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/proxy.conf:ro
- ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/proxy.conf:ro
web1:
image: web

View File

@ -1,10 +1,9 @@
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example_location:ro
- ./my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430_location:ro
- ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example_location:ro
- ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430_location:ro
web1:
image: web

View File

@ -1,10 +1,9 @@
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example:ro
- ./my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430:ro
- ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example:ro
- ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430:ro
web1:
image: web

View File

@ -1,9 +1,8 @@
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/conf.d/my_custom_proxy_settings_f00.conf:ro
- ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/conf.d/my_custom_proxy_settings_f00.conf:ro
web1:
image: web

View File

@ -1,8 +1,5 @@
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
DEBUG_ENDPOINT: "true"

View File

@ -1,9 +1,4 @@
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
debug_disabled1:
image: web
expose:

View File

@ -1,5 +1,8 @@
services:
# GIVEN a webserver with VIRTUAL_HOST set to web1.tld
nginx-proxy:
environment:
DEFAULT_HOST: web1.tld
web1:
image: web
expose:
@ -7,11 +10,3 @@ services:
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: web1.tld
# WHEN nginx-proxy runs with DEFAULT_HOST set to web1.tld
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
DEFAULT_HOST: web1.tld

View File

@ -1,4 +1,10 @@
services:
nginx-proxy:
volumes:
- /var/run/docker.sock:/f00.sock:ro
environment:
DOCKER_HOST: unix:///f00.sock
web1:
image: web
expose:
@ -14,10 +20,3 @@ services:
environment:
WEB_PORTS: "82"
VIRTUAL_HOST: web2.nginx-proxy.tld
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/f00.sock:ro
environment:
DOCKER_HOST: unix:///f00.sock

View File

@ -1,11 +1,18 @@
volumes:
nginx_conf:
services:
nginx:
nginx-proxy-nginx:
image: nginx
container_name: nginx
volumes:
- nginx_conf:/etc/nginx/conf.d:ro
ports:
- "80:80"
- "443:443"
dockergen:
nginx-proxy-dockergen:
image: nginxproxy/docker-gen
command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
volumes:
@ -21,6 +28,3 @@ services:
environment:
WEB_PORTS: "80"
VIRTUAL_HOST: whoami.nginx.container.docker
volumes:
nginx_conf:

View File

@ -1,9 +1,5 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
nginx-proxy:
environment:
ENABLE_HTTP_ON_MISSING_CERT: "false"

View File

@ -1,9 +1,3 @@
networks:
default:
name: test_events-net
services:
nginxproxy:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -0,0 +1,9 @@
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
container_name: nginx-proxy
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
ports:
- "80:80"
- "443:443"

View File

@ -1,9 +1,8 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./custom-fallback.conf:/etc/nginx/conf.d/zzz-custom-fallback.conf:ro
- ${PYTEST_MODULE_PATH}/test_fallback.data/custom-fallback.conf:/etc/nginx/conf.d/zzz-custom-fallback.conf:ro
http-only:
image: web

View File

@ -1,9 +1,8 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nodefault.certs:/etc/nginx/certs:ro
- ${PYTEST_MODULE_PATH}/test_fallback.data/nodefault.certs:/etc/nginx/certs:ro
https-and-http:
image: web

View File

@ -1,9 +1,8 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
- ${PYTEST_MODULE_PATH}/test_fallback.data/withdefault.certs:/etc/nginx/certs:ro
environment:
HTTPS_METHOD: redirect

View File

@ -1,9 +1,8 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
- ${PYTEST_MODULE_PATH}/test_fallback.data/withdefault.certs:/etc/nginx/certs:ro
environment:
HTTPS_METHOD: nohttp

View File

@ -1,9 +1,8 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
- ${PYTEST_MODULE_PATH}/test_fallback.data/withdefault.certs:/etc/nginx/certs:ro
environment:
HTTPS_METHOD: nohttp

View File

@ -1,8 +1,5 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
nginx-proxy:
environment:
HTTPS_METHOD: redirect

View File

@ -1,8 +1,5 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
nginx-proxy:
environment:
HTTPS_METHOD: nohttps

View File

@ -1,9 +1,8 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
- ${PYTEST_MODULE_PATH}/test_fallback.data/withdefault.certs:/etc/nginx/certs:ro
environment:
TRUST_DEFAULT_CERT: "false"

View File

@ -1,9 +1,8 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
- ${PYTEST_MODULE_PATH}/test_fallback.data/withdefault.certs:/etc/nginx/certs:ro
https-and-http:
image: web

View File

@ -1,32 +1,32 @@
import os.path
import pathlib
import re
from typing import List, Callable
import backoff
import pytest
import requests
from requests import Response
@pytest.fixture
def data_dir():
return f"{os.path.splitext(__file__)[0]}.data"
def docker_compose_files(compose_file) -> List[str]:
data_dir = pathlib.Path(__file__).parent.joinpath("test_fallback.data")
return [
data_dir.joinpath("compose.base.yml"),
data_dir.joinpath(compose_file).as_posix()
]
@pytest.fixture
def docker_compose_file(data_dir, compose_file):
return os.path.join(data_dir, compose_file)
@pytest.fixture
def get(docker_compose, nginxproxy, want_err_re):
def get(docker_compose, nginxproxy, want_err_re: re.Pattern[str]) -> Callable[[str], Response]:
@backoff.on_exception(
backoff.constant,
requests.exceptions.SSLError,
giveup=lambda e: want_err_re and want_err_re.search(str(e)),
giveup=lambda e: want_err_re and bool(want_err_re.search(str(e))),
interval=.3,
max_tries=30,
jitter=None)
def _get(url):
def _get(url) -> Response:
return nginxproxy.get(url, allow_redirects=False)
return _get
@ -108,7 +108,7 @@ INTERNAL_ERR_RE = re.compile("TLSV1_UNRECOGNIZED_NAME")
# should prefer that server for handling requests for unknown vhosts.
("custom-fallback.yml", "http://unknown.nginx-proxy.test/", 418, None),
])
def test_fallback(get, url, want_code, want_err_re):
def test_fallback(get, compose_file, url, want_code, want_err_re):
if want_err_re is None:
r = get(url)
assert r.status_code == want_code

View File

@ -0,0 +1,70 @@
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 4096 (0x1000)
Signature Algorithm: sha256WithRSAEncryption
Issuer: O=nginx-proxy test suite, CN=www.nginx-proxy.tld
Validity
Not Before: Jan 13 03:06:39 2017 GMT
Not After : May 31 03:06:39 2044 GMT
Subject: CN=web.nginx-proxy.tld
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:95:56:c7:0d:48:a5:2b:3c:65:49:3f:26:e1:38:
2b:61:30:56:e4:92:d7:63:e0:eb:ad:ac:f9:33:9b:
b2:31:f1:39:13:0b:e5:43:7b:c5:bd:8a:85:c8:d9:
3d:d8:ac:71:ba:16:e7:81:96:b2:ab:ae:c6:c0:bd:
be:a7:d1:96:8f:b2:9b:df:ba:f9:4d:a1:3b:7e:21:
4a:cd:b6:45:f9:6d:79:50:bf:24:8f:c1:6b:c1:09:
19:5b:62:cb:96:e8:04:14:20:e8:d4:16:62:6a:f2:
37:c1:96:e2:9d:53:05:0b:52:1d:e7:68:92:db:8b:
36:68:cd:8d:5b:02:ff:12:f0:ac:5d:0c:c4:e0:7a:
55:a2:49:60:9f:ff:47:1f:52:73:55:4d:d4:f2:d1:
62:a2:f4:50:9d:c9:f6:f1:43:b3:dc:57:e1:31:76:
b4:e0:a4:69:7e:f2:6d:34:ae:b9:8d:74:26:7b:d9:
f6:07:00:ef:4b:36:61:b3:ef:7a:a1:36:3a:b6:d0:
9e:f8:b8:a9:0d:4c:30:a2:ed:eb:ab:6b:eb:2e:e2:
0b:28:be:f7:04:b1:e9:e0:84:d6:5d:31:77:7c:dc:
d2:1f:d4:1d:71:6f:6f:6c:6d:1b:bf:31:e2:5b:c3:
52:d0:14:fc:8b:fb:45:ea:41:ec:ca:c7:3b:67:12:
c4:df
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:web.nginx-proxy.tld
Signature Algorithm: sha256WithRSAEncryption
4e:48:7d:81:66:ba:2f:50:3d:24:42:61:3f:1f:de:cf:ec:1b:
1b:bd:0a:67:b6:62:c8:79:9d:31:a0:fd:a9:61:ce:ff:69:bf:
0e:f4:f7:e6:15:2b:b0:f0:e4:f2:f4:d2:8f:74:02:b1:1e:4a:
a8:6f:26:0a:77:32:29:cf:dc:b5:61:82:3e:58:47:61:92:f0:
0c:20:25:f8:41:4d:34:09:44:bc:39:9e:aa:82:06:83:13:8b:
1e:2c:3d:cf:cd:1a:f7:77:39:38:e0:a3:a7:f3:09:da:02:8d:
73:75:38:b4:dd:24:a7:f9:03:db:98:c6:88:54:87:dc:e0:65:
4c:95:c5:39:9c:00:30:dc:f0:d3:2c:19:ca:f1:f4:6c:c6:d9:
b5:c4:4a:c7:bc:a1:2e:88:7b:b5:33:d0:ff:fb:48:5e:3e:29:
fa:58:e5:03:de:d8:17:de:ed:96:fc:7e:1f:fe:98:f6:be:99:
38:87:51:c0:d3:b7:9a:0f:26:92:e5:53:1b:d6:25:4c:ac:48:
f3:29:fc:74:64:9d:07:6a:25:57:24:aa:a7:70:fa:8f:6c:a7:
2b:b7:9d:81:46:10:32:93:b9:45:6d:0f:16:18:b2:21:1f:f3:
30:24:62:3f:e1:6c:07:1d:71:28:cb:4c:bb:f5:39:05:f9:b2:
5b:a0:05:1b
-----BEGIN CERTIFICATE-----
MIIC+zCCAeOgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwPzEfMB0GA1UECgwWbmdp
bngtcHJveHkgdGVzdCBzdWl0ZTEcMBoGA1UEAwwTd3d3Lm5naW54LXByb3h5LnRs
ZDAeFw0xNzAxMTMwMzA2MzlaFw00NDA1MzEwMzA2MzlaMB4xHDAaBgNVBAMME3dl
Yi5uZ2lueC1wcm94eS50bGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQCVVscNSKUrPGVJPybhOCthMFbkktdj4OutrPkzm7Ix8TkTC+VDe8W9ioXI2T3Y
rHG6FueBlrKrrsbAvb6n0ZaPspvfuvlNoTt+IUrNtkX5bXlQvySPwWvBCRlbYsuW
6AQUIOjUFmJq8jfBluKdUwULUh3naJLbizZozY1bAv8S8KxdDMTgelWiSWCf/0cf
UnNVTdTy0WKi9FCdyfbxQ7PcV+ExdrTgpGl+8m00rrmNdCZ72fYHAO9LNmGz73qh
Njq20J74uKkNTDCi7eura+su4gsovvcEsenghNZdMXd83NIf1B1xb29sbRu/MeJb
w1LQFPyL+0XqQezKxztnEsTfAgMBAAGjIjAgMB4GA1UdEQQXMBWCE3dlYi5uZ2lu
eC1wcm94eS50bGQwDQYJKoZIhvcNAQELBQADggEBAE5IfYFmui9QPSRCYT8f3s/s
Gxu9Cme2Ysh5nTGg/alhzv9pvw709+YVK7Dw5PL00o90ArEeSqhvJgp3MinP3LVh
gj5YR2GS8AwgJfhBTTQJRLw5nqqCBoMTix4sPc/NGvd3OTjgo6fzCdoCjXN1OLTd
JKf5A9uYxohUh9zgZUyVxTmcADDc8NMsGcrx9GzG2bXESse8oS6Ie7Uz0P/7SF4+
KfpY5QPe2Bfe7Zb8fh/+mPa+mTiHUcDTt5oPJpLlUxvWJUysSPMp/HRknQdqJVck
qqdw+o9spyu3nYFGEDKTuUVtDxYYsiEf8zAkYj/hbAcdcSjLTLv1OQX5slugBRs=
-----END CERTIFICATE-----

View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEogIBAAKCAQEAlVbHDUilKzxlST8m4TgrYTBW5JLXY+Drraz5M5uyMfE5Ewvl
Q3vFvYqFyNk92KxxuhbngZayq67GwL2+p9GWj7Kb37r5TaE7fiFKzbZF+W15UL8k
j8FrwQkZW2LLlugEFCDo1BZiavI3wZbinVMFC1Id52iS24s2aM2NWwL/EvCsXQzE
4HpVoklgn/9HH1JzVU3U8tFiovRQncn28UOz3FfhMXa04KRpfvJtNK65jXQme9n2
BwDvSzZhs+96oTY6ttCe+LipDUwwou3rq2vrLuILKL73BLHp4ITWXTF3fNzSH9Qd
cW9vbG0bvzHiW8NS0BT8i/tF6kHsysc7ZxLE3wIDAQABAoIBAEmK7IecKMq7+V0y
3mC3GpXICmKR9cRX9XgX4LkLiZuSoXrBtuuevmhzGSMp6I0VjwQHV4a3wdFORs6Q
Ip3eVvj5Ck4Jc9BJAFVC6+WWR6tnwACFwOmSZRAw/O3GH2B3bdrDwiT/yQPFuLN7
LKoxQiCrFdLp6rh3PBosb9pMBXU7k/HUazIdgmSKg6/JIoo/4Gwyid04TF/4MI2l
RscxtP5/ANtS8VgwBEqhgdafRJ4KnLEpgvswgIQvUKmduVhZQlzd0LMY8FbhKVqz
Utg8gsXaTyH6df/nmgUIInxLMz/MKPnMkv99fS6Sp/hvYlGpLZFWBJ6unMq3lKEr
LMbHfIECgYEAxB+5QWdVqG2r9loJlf8eeuNeMPml4P8Jmi5RKyJC7Cww6DMlMxOS
78ZJfl4b3ZrWuyvhjOfX/aTq7kQaF1BI9o3KJBH8k6EtO4gI8KeNmDONyQk9zsrn
ru8Zwr7hVbAo8fCXxCnmPzhDLsYg6f3BVOsQWoX2SFYKZ1GvkPfIReECgYEAwu6G
qtgFb57Vim10ecfWGM6vrPxvyfqP+zlH/p4nR+aQ+2sFbt27D0B1byWBRZe4KQyw
Vq6XiQ09Fk6MJr8E8iAr9GXPPHcqlYI6bbNc6YOP3jVSKut0tQdTUOHll4kYIY+h
RS3VA3+BA//ADpWpywu+7RZRbaIECA+U2a224r8CgYB5PCMIixgoRaNHZeEHF+1/
iY1wOOKRcxY8eOU0BLnZxHd3EiasrCzoi2pi80nGczDKAxYqRCcAZDHVl8OJJdf0
kTGjmnrHx5pucmkUWn7s1vGOlGfgrQ0K1kLWX6hrj7m/1Tn7yOrLqbvd7hvqiTI5
jBVP3/+eN5G2zIf61TC4AQKBgCX2Q92jojNhsF58AHHy+/vqzIWYx8CC/mVDe4TX
kfjLqzJ7XhyAK/zFZdlWaX1/FYtRAEpxR+uV226rr1mgW7s3jrfS1/ADmRRyvyQ8
CP0k9PCmW7EmF51lptEanRbMyRlIGnUZfuFmhF6eAO4WMXHsgKs1bHg4VCapuihG
T1aLAoGACRGn1UxFuBGqtsh2zhhsBZE7GvXKJSk/eP7QJeEXUNpNjCpgm8kIZM5K
GorpL7PSB8mwVlDl18TpMm3P7nz6YkJYte+HdjO7pg59H39Uvtg3tZnIrFxNxVNb
YF62/yHfk2AyTgjQZQUSmDS84jq1zUK4oS90lxr+u8qwELTniMs=
-----END RSA PRIVATE KEY-----

View File

@ -15,8 +15,3 @@ services:
WEB_PORTS: "80"
VIRTUAL_HOST: web-server-tokens-off.nginx-proxy.tld
SERVER_TOKENS: "off"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -1,4 +1,9 @@
services:
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ${PYTEST_MODULE_PATH}/certs:/etc/nginx/certs:ro
web:
image: web
expose:
@ -15,14 +20,3 @@ services:
WEB_PORTS: "80"
VIRTUAL_HOST: web-server-tokens-off.nginx-proxy.tld
SERVER_TOKENS: "off"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/default.crt:ro
- ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/default.key:ro
- ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro
- ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro
- ./certs/web-server-tokens-off.nginx-proxy.tld.crt:/etc/nginx/certs/web-server-tokens-off.nginx-proxy.tld.crt:ro
- ./certs/web-server-tokens-off.nginx-proxy.tld.key:/etc/nginx/certs/web-server-tokens-off.nginx-proxy.tld.key:ro

View File

@ -4,6 +4,11 @@ networks:
net2:
services:
nginx-proxy:
networks:
- net1
- net2
bridge-network:
image: web
environment:
@ -19,11 +24,3 @@ services:
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
- net2

View File

@ -1,3 +1,6 @@
# Note: on Docker Desktop, host networking must be manually enabled.
# See https://docs.docker.com/engine/network/drivers/host/
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

View File

@ -1,4 +1,9 @@
services:
nginx-proxy:
environment:
HTTP_PORT: 8888
network_mode: host
host-network-1:
image: web
environment:
@ -14,11 +19,3 @@ services:
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

View File

@ -0,0 +1,5 @@
services:
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ${PYTEST_MODULE_PATH}/htpasswd:/etc/nginx/htpasswd:ro

View File

@ -6,10 +6,3 @@ services:
environment:
WEB_PORTS: "80"
VIRTUAL_HOST: ~^regex.*\.nginx-proxy\.example$
sut:
container_name: sut
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./htpasswd:/etc/nginx/htpasswd:ro

View File

@ -6,10 +6,3 @@ services:
environment:
WEB_PORTS: "80"
VIRTUAL_HOST: htpasswd.nginx-proxy.tld
sut:
container_name: sut
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./htpasswd:/etc/nginx/htpasswd:ro

View File

@ -8,10 +8,3 @@ services:
VIRTUAL_HOST: htpasswd.nginx-proxy.tld
VIRTUAL_PATH: /foo/
VIRTUAL_DEST: /
sut:
container_name: sut
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./htpasswd:/etc/nginx/htpasswd:ro

View File

@ -1,4 +1,10 @@
services:
nginx-proxy:
environment:
HTTP_PORT: 8080
ports:
- "8080:8080"
web1:
image: web
expose:
@ -6,10 +12,3 @@ services:
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: "*.nginx-proxy.tld"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
HTTP_PORT: 8080

View File

@ -1,4 +1,8 @@
services:
nginx-proxy:
environment:
ENABLE_HTTP2: "false"
http2-global-disabled:
image: web
expose:
@ -6,10 +10,3 @@ services:
environment:
WEB_PORTS: "80"
VIRTUAL_HOST: http2-global-disabled.nginx-proxy.tld
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
ENABLE_HTTP2: "false"

View File

@ -1,4 +1,8 @@
services:
# nginx-proxy:
# environment:
# ENABLE_HTTP3: "false" #Disabled by default
http3-global-disabled:
image: web
expose:
@ -6,10 +10,3 @@ services:
environment:
WEB_PORTS: "80"
VIRTUAL_HOST: http3-global-disabled.nginx-proxy.tld
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
#environment:
#ENABLE_HTTP3: "false" #Disabled by default

View File

@ -1,4 +1,8 @@
services:
nginx-proxy:
environment:
ENABLE_HTTP3: "true"
http3-global-enabled:
image: web
expose:
@ -6,10 +10,3 @@ services:
environment:
WEB_PORTS: "80"
VIRTUAL_HOST: http3-global-enabled.nginx-proxy.tld
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
ENABLE_HTTP3: "true"

View File

@ -1,4 +1,8 @@
services:
# nginx-proxy:
# environment:
# ENABLE_HTTP3: "false" #Disabled by default
http3-vhost-enabled:
image: web
expose:
@ -26,8 +30,3 @@ services:
environment:
WEB_PORTS: "80"
VIRTUAL_HOST: http3-vhost-default-disabled.nginx-proxy.tld
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -0,0 +1,5 @@
services:
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ${PYTEST_MODULE_PATH}/network_internal.conf:/etc/nginx/network_internal.conf:ro

View File

@ -15,9 +15,3 @@ services:
environment:
WEB_PORTS: "82"
VIRTUAL_HOST: web2.nginx-proxy.example
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./network_internal.conf:/etc/nginx/network_internal.conf:ro

View File

@ -20,8 +20,3 @@ services:
VIRTUAL_PATH: /web2/
VIRTUAL_DEST: /
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./network_internal.conf:/etc/nginx/network_internal.conf:ro

View File

@ -11,6 +11,14 @@ networks:
- subnet: fd00:cafe:face:feed::/64
services:
nginx-proxy:
networks:
ipv4net:
ipv4_address: 172.16.10.3
dualstacknet:
ipv4_address: 172.16.20.3
ipv6_address: fd00:cafe:face:feed::3
ipv4only:
image: web
expose:
@ -31,13 +39,3 @@ services:
ipv4_address: 172.16.20.2
ipv6_address: fd00:cafe:face:feed::2
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
ipv4net:
ipv4_address: 172.16.10.3
dualstacknet:
ipv4_address: 172.16.20.3
ipv6_address: fd00:cafe:face:feed::3

View File

@ -11,6 +11,16 @@ networks:
- subnet: fd00:cafe:face:feed::/64
services:
nginx-proxy:
environment:
PREFER_IPV6_NETWORK: "true"
networks:
ipv4net:
ipv4_address: 172.16.10.3
dualstacknet:
ipv4_address: 172.16.20.3
ipv6_address: fd00:cafe:face:feed::3
ipv4only:
image: web
expose:
@ -31,15 +41,3 @@ services:
ipv4_address: 172.16.20.2
ipv6_address: fd00:cafe:face:feed::2
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
PREFER_IPV6_NETWORK: "true"
networks:
ipv4net:
ipv4_address: 172.16.10.3
dualstacknet:
ipv4_address: 172.16.20.3
ipv6_address: fd00:cafe:face:feed::3

View File

@ -1,3 +1,13 @@
import platform
import pytest
pytestmark = pytest.mark.skipif(
platform.system() == "Darwin",
reason="Those tests rely entirely on being able to directly contact the container's IP"
)
def test_unknown_virtual_host_ipv4(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/port")
assert r.status_code == 503

View File

@ -6,6 +6,12 @@ networks:
- subnet: fd00:1::/80
services:
nginx-proxy:
environment:
ENABLE_IPV6: "true"
networks:
- net1
web1:
image: web
expose:
@ -26,11 +32,3 @@ services:
networks:
- net1
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
ENABLE_IPV6: "true"
networks:
- net1

View File

@ -1,4 +1,8 @@
services:
nginx-proxy:
environment:
HTTPS_METHOD: nohttps
keepalive-disabled:
image: web
expose:
@ -18,7 +22,7 @@ services:
VIRTUAL_HOST: keepalive-enabled.nginx-proxy.test
labels:
com.github.nginx-proxy.nginx-proxy.keepalive: "64"
keepalive-auto:
image: web
deploy:
@ -30,9 +34,3 @@ services:
WEB_PORTS: "80"
VIRTUAL_HOST: keepalive-auto.nginx-proxy.test
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
HTTPS_METHOD: nohttps

View File

@ -20,8 +20,3 @@ services:
VIRTUAL_HOST: loadbalance-disabled.nginx-proxy.tld
deploy:
replicas: 2
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -1,9 +1,8 @@
services:
sut:
image: nginxproxy/nginx-proxy:test
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./vhost.d:/etc/nginx/vhost.d:ro
- ${PYTEST_MODULE_PATH}/vhost.d:/etc/nginx/vhost.d:ro
explicit-root:
image: web

View File

@ -2,7 +2,7 @@ def test_log_disabled(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy.test/port")
assert r.status_code == 200
assert r.text == "answer from port 81\n"
sut_container = docker_compose.containers.get("sut")
sut_container = docker_compose.containers.get("nginx-proxy")
docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
docker_logs = docker_logs.decode("utf-8").splitlines()
docker_logs = [line for line in docker_logs if "GET /port" in line]

View File

@ -1,4 +1,8 @@
services:
nginx-proxy:
environment:
DISABLE_ACCESS_LOGS: true
web1:
image: web
expose:
@ -6,11 +10,3 @@ services:
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: nginx-proxy.test
sut:
container_name: sut
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
DISABLE_ACCESS_LOGS: true

View File

@ -2,7 +2,7 @@ def test_log_format(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy.test/port")
assert r.status_code == 200
assert r.text == "answer from port 81\n"
sut_container = docker_compose.containers.get("sut")
sut_container = docker_compose.containers.get("nginx-proxy")
docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
docker_logs = docker_logs.decode("utf-8").splitlines()
docker_logs = [line for line in docker_logs if "GET /port" in line]

View File

@ -1,4 +1,8 @@
services:
nginx-proxy:
environment:
LOG_FORMAT: '$$remote_addr - $$remote_user [$$time_local] "$$request" $$status $$body_bytes_sent "$$http_referer" "$$http_user_agent" request_time=$$request_time $$upstream_response_time'
web1:
image: web
expose:
@ -6,11 +10,3 @@ services:
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: nginx-proxy.test
sut:
container_name: sut
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
LOG_FORMAT: '$$remote_addr - $$remote_user [$$time_local] "$$request" $$status $$body_bytes_sent "$$http_referer" "$$http_user_agent" request_time=$$request_time $$upstream_response_time'

View File

@ -5,7 +5,7 @@ def test_log_json_format(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy.test/port")
assert r.status_code == 200
assert r.text == "answer from port 81\n"
sut_container = docker_compose.containers.get("sut")
sut_container = docker_compose.containers.get("nginx-proxy")
docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
docker_logs = docker_logs.decode("utf-8").splitlines()
docker_logs = [line for line in docker_logs if "{\"time_local\":" in line]

View File

@ -1,4 +1,8 @@
services:
nginx-proxy:
environment:
LOG_FORMAT: '{"time_local":"$$time_iso8601","remote_addr":"$$remote_addr","request":"$$request","upstream_addr":"$$upstream_addr"}'
web1:
image: web
expose:
@ -6,11 +10,3 @@ services:
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: nginx-proxy.test
sut:
container_name: sut
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
LOG_FORMAT: '{"time_local":"$$time_iso8601","remote_addr":"$$remote_addr","request":"$$request","upstream_addr":"$$upstream_addr"}'

View File

@ -5,7 +5,7 @@ def test_log_json(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy.test/port")
assert r.status_code == 200
assert r.text == "answer from port 81\n"
sut_container = docker_compose.containers.get("sut")
sut_container = docker_compose.containers.get("nginx-proxy")
docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
docker_logs = docker_logs.decode("utf-8").splitlines()
docker_logs = [line for line in docker_logs if "{\"time_local\":" in line]

View File

@ -1,4 +1,8 @@
services:
nginx-proxy:
environment:
LOG_JSON: 1
web1:
image: web
expose:
@ -6,11 +10,3 @@ services:
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: nginx-proxy.test
sut:
container_name: sut
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
LOG_JSON: 1

View File

@ -6,8 +6,3 @@ services:
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: webA.nginx-proxy.tld,webB.nginx-proxy.tld
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -6,9 +6,6 @@ networks:
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
- net1
- net2

View File

@ -68,8 +68,3 @@ services:
}
}
}
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -52,8 +52,3 @@ services:
"/customdest":
port: 10002
dest: "/port"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -35,8 +35,3 @@ services:
port: 8080
"/":
port: 9000
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -32,8 +32,3 @@ services:
"/foo":
port: 9191
dest: "/"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -1,3 +1,5 @@
import platform
import pytest
from requests import ConnectionError
@ -19,6 +21,10 @@ def test_forwards_to_web2(docker_compose, nginxproxy):
assert r.text == "answer from port 82\n"
@pytest.mark.skipif(
platform.system() == "Darwin",
reason="This test depends on direct communication with the container's IP"
)
def test_ipv6_is_disabled_by_default(docker_compose, nginxproxy):
with pytest.raises(ConnectionError):
nginxproxy.get("http://nginx-proxy/port", ipv6=True)

View File

@ -6,6 +6,10 @@ networks:
- subnet: fd00:1::/80
services:
nginx-proxy:
networks:
- net1
web1:
image: web
expose:
@ -25,10 +29,3 @@ services:
VIRTUAL_HOST: web2.nginx-proxy.tld
networks:
- net1
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
- net1

View File

@ -7,8 +7,3 @@ services:
environment:
WEB_PORTS: "80 81"
VIRTUAL_HOST: "web.nginx-proxy.tld"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -6,8 +6,3 @@ services:
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: "web.nginx-proxy.tld"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -7,8 +7,3 @@ services:
WEB_PORTS: "81"
VIRTUAL_HOST: "web.nginx-proxy.tld"
VIRTUAL_PORT: "90"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -8,8 +8,3 @@ services:
WEB_PORTS: "80 90"
VIRTUAL_HOST: "web.nginx-proxy.tld"
VIRTUAL_PORT: 90
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -1,12 +1,12 @@
def test_raw_ipv4_vhost_forwards_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://172.20.0.4")
r = nginxproxy.get("http://172.20.0.1")
assert r.status_code == 200
web1_container = docker_compose.containers.get("web1")
assert r.text == f"I'm {web1_container.id[:12]}\n"
def test_raw_ipv6_vhost_forwards_to_web2(docker_compose, nginxproxy):
r = nginxproxy.get("http://[fd00::4]", ipv6=True)
r = nginxproxy.get("http://[fd00::1]")
assert r.status_code == 200
web2_container = docker_compose.containers.get("web2")
assert r.text == f"I'm {web2_container.id[:12]}\n"

View File

@ -7,6 +7,14 @@ networks:
- subnet: fd00::/80
services:
nginx-proxy:
environment:
ENABLE_IPV6: "true"
networks:
net1:
ipv4_address: 172.20.0.4
ipv6_address: fd00::4
web1:
container_name: web1
image: web
@ -14,7 +22,7 @@ services:
- "81"
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: "172.20.0.4"
VIRTUAL_HOST: "172.20.0.1"
networks:
net1:
ipv4_address: 172.20.0.2
@ -27,19 +35,9 @@ services:
- "82"
environment:
WEB_PORTS: "82"
VIRTUAL_HOST: "[fd00::4]"
VIRTUAL_HOST: "[fd00::1]"
networks:
net1:
ipv4_address: 172.20.0.3
ipv6_address: fd00::3
sut:
image: nginxproxy/nginx-proxy:test
environment:
ENABLE_IPV6: "true"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
net1:
ipv4_address: 172.20.0.4
ipv6_address: fd00::4

View File

@ -23,8 +23,3 @@ services:
WEB_PORTS: "83"
VIRTUAL_HOST: web.nginx-proxy.tld
network_mode: "none"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -6,8 +6,3 @@ services:
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: web.nginx-proxy.tld
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -7,8 +7,3 @@ services:
WEB_PORTS: "81"
VIRTUAL_HOST: web.nginx-proxy.tld
network_mode: "none"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro

View File

@ -0,0 +1,6 @@
services:
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ${PYTEST_MODULE_PATH}/certs:/etc/nginx/certs:ro
- ${PYTEST_MODULE_PATH}/acme_root:/usr/share/nginx/html:ro

View File

@ -1,5 +1,13 @@
services:
base:
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ${PYTEST_MODULE_PATH}/cert_selection:/etc/nginx/certs:ro
- ${PYTEST_MODULE_PATH}/acme_root:/usr/share/nginx/html:ro
environment:
DEBUG_ENDPOINT: "true"
base:
image: web
environment:
WEB_PORTS: "80"
@ -10,7 +18,7 @@ services:
environment:
WEB_PORTS: "80"
VIRTUAL_HOST: "www.nginx-proxy.tld"
sub-www:
image: web
environment:
@ -22,12 +30,3 @@ services:
environment:
WEB_PORTS: "80"
VIRTUAL_HOST: "web1.nginx-proxy.tld"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./cert_selection:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html:ro
environment:
DEBUG_ENDPOINT: "true"

View File

@ -1,3 +1,7 @@
networks:
default:
name: test_dhparam-net
services:
web5:
image: web

View File

@ -1,3 +1,4 @@
import platform
import re
import subprocess
@ -7,6 +8,10 @@ import pytest
docker_client = docker.from_env()
pytestmark = pytest.mark.skipif(
platform.system() == "Darwin",
reason="Those tests rely entirely on being able to directly contact container's IP"
)
###############################################################################
#
@ -61,7 +66,7 @@ def require_openssl(required_version):
@require_openssl("1.0.2")
def negotiate_cipher(sut_container, additional_params='', grep='Cipher is'):
sut_container.reload()
host = f"{sut_container.attrs['NetworkSettings']['Networks']['test_ssl_default']['IPAddress']}:443"
host = f"{sut_container.attrs['NetworkSettings']['Networks']['test_dhparam-net']['IPAddress']}:443"
try:
# Enforce TLS 1.2 as newer versions don't support custom dhparam or ciphersuite preference.

View File

@ -44,9 +44,3 @@ services:
VIRTUAL_HOST: http3-vhost-enabled.nginx-proxy.tld
labels:
com.github.nginx-proxy.nginx-proxy.http3.enable: "true"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro

View File

@ -1,4 +1,12 @@
services:
nginx-proxy:
environment:
HTTP_PORT: 8080
HTTPS_PORT: 8443
ports:
- "8080:8080"
- "8443:8443"
web1:
image: web
expose:
@ -6,13 +14,3 @@ services:
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: "*.nginx-proxy.tld"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html:ro
environment:
HTTP_PORT: 8080
HTTPS_PORT: 8443

View File

@ -7,10 +7,3 @@ services:
WEB_PORTS: "82"
VIRTUAL_HOST: "web2.nginx-proxy.tld"
HTTPS_METHOD: nohttp
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html:ro

View File

@ -7,9 +7,3 @@ services:
WEB_PORTS: "83"
VIRTUAL_HOST: "web.nginx-proxy.tld"
HTTPS_METHOD: nohttps
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./acme_root:/usr/share/nginx/html:ro

View File

@ -7,10 +7,3 @@ services:
WEB_PORTS: "83"
VIRTUAL_HOST: "web3.nginx-proxy.tld"
HTTPS_METHOD: noredirect
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html:ro

View File

@ -18,10 +18,3 @@ services:
VIRTUAL_HOST: "www.nginx-proxy.tld"
VIRTUAL_PATH: "/web2/"
VIRTUAL_DEST: "/"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html:ro

View File

@ -1,13 +1,16 @@
version: "3"
# In this scenario, we have a wildcard certificate for `*.web.nginx-proxy.tld` and 3 web containers:
# - 1.web.nginx-proxy.tld
# - 2.web.nginx-proxy.tld
# - 3.web.nginx-proxy.tld
#
# We want web containers 1 and 2 to support SSL, but 3 should not (using `HTTPS_METHOD=nohttps`)
services:
proxy:
image: nginxproxy/nginx-proxy:test
nginx-proxy:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html:ro
- ${PYTEST_MODULE_PATH}/certs_wildcard_nohttps:/etc/nginx/certs:ro
- ${PYTEST_MODULE_PATH}/acme_root:/usr/share/nginx/html:ro
web1:
image: web

View File

@ -6,10 +6,3 @@ services:
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: "*.nginx-proxy.tld"
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html:ro

View File

@ -1,6 +0,0 @@
In this scenario, we have a wildcard certificate for `*.web.nginx-proxy.tld` and 3 web containers:
- 1.web.nginx-proxy.tld
- 2.web.nginx-proxy.tld
- 3.web.nginx-proxy.tld
We want web containers 1 and 2 to support SSL, but 3 should not (using `HTTPS_METHOD=nohttps`)

Some files were not shown because too many files have changed in this diff Show More