Compare commits

...

23 commits

Author SHA1 Message Date
Nicolas Duchon
a919c93455 tests: more robust tests 2024-12-24 12:02:50 +01:00
Nicolas Duchon
eb97a413c0 test: runtime backoff predicate 2024-12-23 23:06:26 +01:00
Nicolas Duchon
41d0e33966 test: update backoff 2024-12-23 22:19:22 +01:00
Nicolas Duchon
381293ad3f test: isolate in project 2024-12-23 21:37:40 +01:00
Nicolas Duchon
8fd179bf9f test: always down 2024-12-23 21:00:20 +01:00
Nicolas Duchon
2c595e09c9 test: force recreate 2024-12-23 20:53:09 +01:00
Nicolas Duchon
dab99aa3e3 test: 🤷 2024-12-23 20:48:00 +01:00
Nicolas Duchon
1c5a527cfc tests: yield 2024-12-23 02:29:33 +01:00
Nicolas Duchon
8493fc7aea test: separate containers (contd) 2024-12-23 02:03:31 +01:00
Nicolas Duchon
ce9e534ad0 test: separate containers (contd) 2024-12-22 23:35:12 +01:00
Nicolas Duchon
77978eab96 test: separate containers (contd) 2024-12-22 22:47:10 +01:00
Nicolas Duchon
c6987b3ea0 test: separate containers (contd) 2024-12-22 20:50:57 +01:00
Nicolas Duchon
5ef2e31687 test: separate containers (contd) 2024-12-22 20:27:24 +01:00
Nicolas Duchon
7acf4780d5 test: separate containers (contd) 2024-12-22 20:13:02 +01:00
Nicolas Duchon
9fd66de39d test: separate containers (contd) 2024-12-22 12:46:33 +01:00
Nicolas Duchon
209192e778 test: separate containers (contd) 2024-12-22 10:55:09 +01:00
Nicolas Duchon
1430f9fbff test: separate containers (contd) 2024-12-19 01:35:50 +01:00
Nicolas Duchon
19200326a3 test: separate containers (contd) 2024-12-18 23:27:30 +01:00
Nicolas Duchon
d3154bb8bc test: separate containers (contd) 2024-12-18 23:06:49 +01:00
Nicolas Duchon
b6f0556b70 test: separate containers (contd) 2024-12-18 22:46:05 +01:00
Nicolas Duchon
e0bbd59313 test: separate containers 2024-12-18 21:48:43 +01:00
Nicolas Duchon
e736f84b87 test: test_acme_http_challenge_location separate container 2024-12-18 21:48:43 +01:00
Nicolas Duchon
a67aff92e9 feat: pre bundled dockergen w/ nginx-proxy template image 2024-12-18 21:48:43 +01:00
163 changed files with 3067 additions and 683 deletions

View file

@ -23,7 +23,7 @@ jobs:
name: Build and publish image
strategy:
matrix:
base: [alpine, debian]
flavor: [alpine, debian, dockergen]
runs-on: ubuntu-latest
steps:
- name: Checkout
@ -37,7 +37,7 @@ jobs:
- name: Retrieve docker-gen version
id: docker-gen_version
run: sed -n -e 's;^FROM nginxproxy/docker-gen:\([0-9.]*\).*;VERSION=\1;p' Dockerfile.${{ matrix.base }} >> "$GITHUB_OUTPUT"
run: sed -n -e 's;^FROM docker.io/nginxproxy/docker-gen:\([0-9.]*\).*;VERSION=\1;p' Dockerfile.${{ matrix.flavor }} >> "$GITHUB_OUTPUT"
- name: Get Docker tags
id: docker_meta
@ -48,12 +48,15 @@ jobs:
nginxproxy/nginx-proxy
jwilder/nginx-proxy
tags: |
type=semver,pattern={{version}},enable=${{ matrix.base == 'debian' }}
type=semver,pattern={{major}}.{{minor}},enable=${{ matrix.base == 'debian' }}
type=semver,suffix=-alpine,pattern={{version}},enable=${{ matrix.base == 'alpine' }}
type=semver,suffix=-alpine,pattern={{major}}.{{minor}},enable=${{ matrix.base == 'alpine' }}
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' && matrix.base == 'debian' }}
type=raw,value=alpine,enable=${{ github.ref == 'refs/heads/main' && matrix.base == 'alpine' }}
type=semver,pattern={{version}},enable=${{ matrix.flavor == 'debian' }}
type=semver,pattern={{major}}.{{minor}},enable=${{ matrix.flavor == 'debian' }}
type=semver,suffix=-alpine,pattern={{version}},enable=${{ matrix.flavor == 'alpine' }}
type=semver,suffix=-alpine,pattern={{major}}.{{minor}},enable=${{ matrix.flavor == 'alpine' }}
type=semver,suffix=-dockergen,pattern={{version}},enable=${{ matrix.flavor == 'dockergen' }}
type=semver,suffix=-dockergen,pattern={{major}}.{{minor}},enable=${{ matrix.flavor == 'dockergen' }}
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' && matrix.flavor == 'debian' }}
type=raw,value=alpine,enable=${{ github.ref == 'refs/heads/main' && matrix.flavor == 'alpine' }}
type=raw,value=dockergen,enable=${{ github.ref == 'refs/heads/main' && matrix.flavor == 'dockergen' }}
labels: |
org.opencontainers.image.authors=Nicolas Duchon <nicolas.duchon@gmail.com> (@buchdag), Jason Wilder
org.opencontainers.image.version=${{ steps.nginx-proxy_version.outputs.VERSION }}
@ -84,7 +87,7 @@ jobs:
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile.${{ matrix.base }}
file: Dockerfile.${{ matrix.flavor }}
build-args: |
NGINX_PROXY_VERSION=${{ steps.nginx-proxy_version.outputs.VERSION }}
DOCKER_GEN_VERSION=${{ steps.docker-gen_version.outputs.VERSION }}

View file

@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
base_docker_image: [alpine, debian]
flavor: [alpine, debian, dockergen]
steps:
- uses: actions/checkout@v4
@ -43,8 +43,10 @@ jobs:
run: make build-webserver
- name: Build Docker nginx proxy test image
run: make build-nginx-proxy-test-${{ matrix.base_docker_image }}
run: make build-nginx-proxy-test-${{ matrix.flavor }}
- name: Run tests
run: pytest
working-directory: test
env:
COMPOSE_PROFILES: ${{ matrix.flavor == 'dockergen' && 'separateContainers' || 'singleContainer' }}

18
Dockerfile.dockergen Normal file
View file

@ -0,0 +1,18 @@
FROM docker.io/nginxproxy/docker-gen:0.14.4
ARG NGINX_PROXY_VERSION
ENV NGINX_PROXY_VERSION=${NGINX_PROXY_VERSION} \
DOCKER_HOST=unix:///tmp/docker.sock \
DHPARAM_SKIP=true \
NGINX_CONTAINER_NAME=nginx-proxy
# Install dependencies
RUN apk add --no-cache --virtual .run-deps bash
RUN mkdir -p '/etc/nginx/conf.d'
COPY app nginx.tmpl LICENSE /app/
WORKDIR /app/
ENTRYPOINT ["/app/docker-entrypoint.sh"]
CMD ["docker-gen", "-notify-sighup", "$NGINX_CONTAINER_NAME", "-watch", "/app/nginx.tmpl", "/etc/nginx/conf.d/default.conf"]

View file

@ -11,10 +11,19 @@ build-nginx-proxy-test-debian:
build-nginx-proxy-test-alpine:
docker build --pull --build-arg NGINX_PROXY_VERSION="test" -f Dockerfile.alpine -t nginxproxy/nginx-proxy:test .
build-nginx-proxy-test-dockergen:
docker build --pull --build-arg NGINX_PROXY_VERSION="test" -f Dockerfile.dockergen -t nginxproxy/nginx-proxy:test-dockergen .
test-debian: export COMPOSE_PROFILES = singleContainer
test-debian: build-webserver build-nginx-proxy-test-debian
test/pytest.sh
test-alpine: export COMPOSE_PROFILES = singleContainer
test-alpine: build-webserver build-nginx-proxy-test-alpine
test/pytest.sh
test: test-debian test-alpine
test-dockergen: export COMPOSE_PROFILES = separateContainers
test-dockergen: build-webserver build-nginx-proxy-test-docker-gen
test/pytest.sh
test: test-debian test-alpine test-dockergen

View file

@ -101,7 +101,7 @@ function _setup_dhparam() {
}
# Run the init logic if the default CMD was provided
if [[ $* == 'forego start -r' ]]; then
if [[ $* == "forego start -r" ]] || [[ $* =~ "docker-gen -notify-sighup" ]]; then
_print_version
_check_unix_socket
@ -116,6 +116,11 @@ if [[ $* == 'forego start -r' ]]; then
Warning: The default value of TRUST_DOWNSTREAM_PROXY might change to "false" in a future version of nginx-proxy. If you require TRUST_DOWNSTREAM_PROXY to be enabled, explicitly set it to "true".
EOT
fi
if [[ $3 == "\$NGINX_CONTAINER_NAME" && -n "$NGINX_CONTAINER_NAME" ]]; then
# change the value of $3 to the expanded $NGINX_CONTAINER_NAME variable
set -- "${@:1:2}" "$NGINX_CONTAINER_NAME" "${@:4}"
fi
fi
exec "$@"

View file

@ -1,6 +1,7 @@
import contextlib
import logging
import os
import platform
import re
import shlex
import socket
@ -9,12 +10,11 @@ import time
from typing import List
import backoff
import docker
import docker.errors
import pytest
import requests
from _pytest._code.code import ReprExceptionInfo
from packaging.version import Version
from docker.models.containers import Container
from packaging.version import Version
from requests.packages.urllib3.util.connection import HAS_IPV6
logging.basicConfig(level=logging.INFO)
@ -27,6 +27,9 @@ PYTEST_RUNNING_IN_CONTAINER = os.environ.get('PYTEST_RUNNING_IN_CONTAINER') == "
FORCE_CONTAINER_IPV6 = False # ugly global state to consider containers' IPv6 address instead of IPv4
DOCKER_COMPOSE = os.environ.get('DOCKER_COMPOSE', 'docker compose')
COMPOSE_PROFILES = os.environ.get('COMPOSE_PROFILES', 'singleContainer')
IMAGE_TAG = "test-dockergen" if COMPOSE_PROFILES == "separateContainers" else "test"
docker_client = docker.from_env()
@ -70,16 +73,27 @@ class requests_for_docker(object):
if os.path.isfile(CA_ROOT_CERTIFICATE):
self.session.verify = CA_ROOT_CERTIFICATE
@staticmethod
def __backoff_predicate(expected_status_codes=None):
if expected_status_codes is not None:
if isinstance(expected_status_codes, int):
expected_status_codes = [expected_status_codes]
return lambda r: r.status_code not in expected_status_codes
else:
return lambda r: r.status_code not in (200, 301)
__backed_off_exceptions = (requests.exceptions.SSLError, requests.exceptions.ConnectionError)
@staticmethod
def get_nginx_proxy_containers() -> List[Container]:
"""
Return list of containers
"""
nginx_proxy_containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/nginx-proxy:test"})
nginx_proxy_containers = docker_client.containers.list(filters={"ancestor": f"nginxproxy/nginx-proxy:{IMAGE_TAG}"})
if len(nginx_proxy_containers) > 1:
pytest.fail("Too many running nginxproxy/nginx-proxy:test containers", pytrace=False)
pytest.fail(f"Too many running nginxproxy/nginx-proxy:{IMAGE_TAG} containers", pytrace=False)
elif len(nginx_proxy_containers) == 0:
pytest.fail("No running nginxproxy/nginx-proxy:test container", pytrace=False)
pytest.fail(f"No running nginxproxy/nginx-proxy:{IMAGE_TAG} container", pytrace=False)
return nginx_proxy_containers
def get_conf(self):
@ -97,43 +111,61 @@ class requests_for_docker(object):
return container_ip(nginx_proxy_containers[0])
def get(self, *args, **kwargs):
_expected_status_code = kwargs.pop('expected_status_code', None)
with ipv6(kwargs.pop('ipv6', False)):
@backoff.on_exception(backoff.constant, self.__backed_off_exceptions, interval=.3, max_tries=30, jitter=None)
@backoff.on_predicate(backoff.constant, self.__backoff_predicate(_expected_status_code), interval=.3, max_tries=30, jitter=None)
def _get(*args, **kwargs):
return self.session.get(*args, **kwargs)
return _get(*args, **kwargs)
def get_without_backoff(self, *args, **kwargs):
with ipv6(kwargs.pop('ipv6', False)):
@backoff.on_predicate(backoff.constant, lambda r: r.status_code in (404, 502), interval=.3, max_tries=30, jitter=None)
def _get(*args, **kwargs):
return self.session.get(*args, **kwargs)
return _get(*args, **kwargs)
def post(self, *args, **kwargs):
_expected_status_code = kwargs.pop('expected_status_code', None)
with ipv6(kwargs.pop('ipv6', False)):
@backoff.on_predicate(backoff.constant, lambda r: r.status_code in (404, 502), interval=.3, max_tries=30, jitter=None)
@backoff.on_exception(backoff.constant, requests.exceptions.SSLError, interval=.3, max_tries=30, jitter=None)
@backoff.on_predicate(backoff.constant, self.__backoff_predicate(_expected_status_code), interval=.3, max_tries=30, jitter=None)
def _post(*args, **kwargs):
return self.session.post(*args, **kwargs)
return _post(*args, **kwargs)
def put(self, *args, **kwargs):
_expected_status_code = kwargs.pop('expected_status_code', None)
with ipv6(kwargs.pop('ipv6', False)):
@backoff.on_predicate(backoff.constant, lambda r: r.status_code in (404, 502), interval=.3, max_tries=30, jitter=None)
@backoff.on_exception(backoff.constant, requests.exceptions.SSLError, interval=.3, max_tries=30, jitter=None)
@backoff.on_predicate(backoff.constant, self.__backoff_predicate(_expected_status_code), interval=.3, max_tries=30, jitter=None)
def _put(*args, **kwargs):
return self.session.put(*args, **kwargs)
return _put(*args, **kwargs)
def head(self, *args, **kwargs):
_expected_status_code = kwargs.pop('expected_status_code', None)
with ipv6(kwargs.pop('ipv6', False)):
@backoff.on_predicate(backoff.constant, lambda r: r.status_code in (404, 502), interval=.3, max_tries=30, jitter=None)
@backoff.on_exception(backoff.constant, requests.exceptions.SSLError, interval=.3, max_tries=30, jitter=None)
@backoff.on_predicate(backoff.constant, self.__backoff_predicate(_expected_status_code), interval=.3, max_tries=30, jitter=None)
def _head(*args, **kwargs):
return self.session.head(*args, **kwargs)
return _head(*args, **kwargs)
def delete(self, *args, **kwargs):
_expected_status_code = kwargs.pop('expected_status_code', None)
with ipv6(kwargs.pop('ipv6', False)):
@backoff.on_predicate(backoff.constant, lambda r: r.status_code in (404, 502), interval=.3, max_tries=30, jitter=None)
@backoff.on_exception(backoff.constant, requests.exceptions.SSLError, interval=.3, max_tries=30, jitter=None)
@backoff.on_predicate(backoff.constant, self.__backoff_predicate(_expected_status_code), interval=.3, max_tries=30, jitter=None)
def _delete(*args, **kwargs):
return self.session.delete(*args, **kwargs)
return _delete(*args, **kwargs)
def options(self, *args, **kwargs):
_expected_status_code = kwargs.pop('expected_status_code', None)
with ipv6(kwargs.pop('ipv6', False)):
@backoff.on_predicate(backoff.constant, lambda r: r.status_code in (404, 502), interval=.3, max_tries=30, jitter=None)
@backoff.on_exception(backoff.constant, requests.exceptions.SSLError, interval=.3, max_tries=30, jitter=None)
@backoff.on_predicate(backoff.constant, self.__backoff_predicate(_expected_status_code), interval=.3, max_tries=30, jitter=None)
def _options(*args, **kwargs):
return self.session.options(*args, **kwargs)
return _options(*args, **kwargs)
@ -188,7 +220,7 @@ def container_ipv6(container):
return net_info[network_name]["GlobalIPv6Address"]
def nginx_proxy_dns_resolver(domain_name):
def nginx_proxy_single_container_dns_resolver(domain_name):
"""
if "nginx-proxy" if found in host, return the ip address of the docker container
issued from the docker image nginxproxy/nginx-proxy:test.
@ -196,21 +228,44 @@ def nginx_proxy_dns_resolver(domain_name):
:return: IP or None
"""
log = logging.getLogger('DNS')
log.debug(f"nginx_proxy_dns_resolver({domain_name!r})")
log.debug(f"nginx_proxy_single_container_dns_resolver({domain_name!r})")
if 'nginx-proxy' in domain_name:
nginxproxy_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginxproxy/nginx-proxy:test"})
if len(nginxproxy_containers) == 0:
log.warn(f"no container found from image nginxproxy/nginx-proxy:test while resolving {domain_name!r}")
log.info(f"no container found from image nginxproxy/nginx-proxy:test while resolving {domain_name!r}")
exited_nginxproxy_containers = docker_client.containers.list(filters={"status": "exited", "ancestor": "nginxproxy/nginx-proxy:test"})
if len(exited_nginxproxy_containers) > 0:
exited_nginxproxy_container_logs = exited_nginxproxy_containers[0].logs()
log.warn(f"nginxproxy/nginx-proxy:test container might have exited unexpectedly. Container logs: " + "\n" + exited_nginxproxy_container_logs.decode())
log.warning(f"nginxproxy/nginx-proxy:test container might have exited unexpectedly. Container logs: " + "\n" + exited_nginxproxy_container_logs.decode())
return
nginxproxy_container = nginxproxy_containers[0]
ip = container_ip(nginxproxy_container)
log.info(f"resolving domain name {domain_name!r} as IP address {ip} of nginx-proxy container {nginxproxy_container.name}")
return ip
def nginx_proxy_separate_containers_dns_resolver(domain_name):
"""
if "nginx-proxy" if found in host, return the ip address of the docker container
labeled with "com.github.nginx-proxy.nginx-proxy.nginx".
:return: IP or None
"""
log = logging.getLogger('DNS')
log.debug(f"nginx_proxy_separate_containers_dns_resolver({domain_name!r})")
if 'nginx-proxy' in domain_name:
nginx_containers = docker_client.containers.list(filters={"status": "running", "label": "com.github.nginx-proxy.nginx-proxy.nginx"})
if len(nginx_containers) == 0:
log.info(f"no container labeled with com.github.nginx-proxy.nginx-proxy.nginx found while resolving {domain_name!r}")
exited_nginx_containers = docker_client.containers.list(filters={"status": "exited", "label": "com.github.nginx-proxy.nginx-proxy.nginx"})
if len(exited_nginx_containers) > 0:
exited_nginx_container_logs = exited_nginx_containers[0].logs()
log.warning(f"nginx container might have exited unexpectedly. Container logs: " + "\n" + exited_nginx_container_logs.decode())
return
nginx_container = nginx_containers[0]
ip = container_ip(nginx_container)
log.info(f"resolving domain name {domain_name!r} as IP address {ip} of nginx container {nginx_container.name}")
return ip
def docker_container_dns_resolver(domain_name):
"""
if domain name is of the form "XXX.container.docker" or "anything.XXX.container.docker", return the ip address of the docker container
@ -231,7 +286,7 @@ def docker_container_dns_resolver(domain_name):
try:
container = docker_client.containers.get(container_name)
except docker.errors.NotFound:
log.warn(f"container named {container_name!r} not found while resolving {domain_name!r}")
log.warning(f"container named {container_name!r} not found while resolving {domain_name!r}")
return
log.debug(f"container {container.name!r} found ({container.short_id})")
@ -244,7 +299,8 @@ 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
labeled with 'com.github.nginx-proxy.nginx-proxy.nginx'.
"""
prv_getaddrinfo = socket.getaddrinfo
dns_cache = {}
@ -258,7 +314,13 @@ 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
if platform.system() == "Darwin":
ip = "127.0.0.1"
if ip is None:
ip = nginx_proxy_single_container_dns_resolver(args[0])
if ip is None:
ip = nginx_proxy_separate_containers_dns_resolver(args[0])
if ip is None:
ip = docker_container_dns_resolver(args[0])
if ip is not None:
@ -278,14 +340,6 @@ def restore_urllib_dns_resolver(getaddrinfo_func):
socket.getaddrinfo = getaddrinfo_func
def remove_all_containers():
for container in docker_client.containers.list(all=True):
if PYTEST_RUNNING_IN_CONTAINER and container.name == test_container:
continue # pytest is running within a Docker container, so we do not want to remove that particular container
logging.info(f"removing container {container.name}")
container.remove(v=True, force=True)
def get_nginx_conf_from_container(container):
"""
return the nginx /etc/nginx/conf.d/default.conf file content from a container
@ -301,35 +355,52 @@ def get_nginx_conf_from_container(container):
return conffile.read()
def docker_compose_up(compose_file='docker-compose.yml'):
logging.info(f'{DOCKER_COMPOSE} -f {compose_file} up -d')
def docker_compose_up(project_name, compose_file='docker-compose.yml'):
composeCmd = f'{DOCKER_COMPOSE} --project-name {project_name} --file {compose_file} up --remove-orphans --force-recreate --detach'
logging.info(composeCmd)
try:
subprocess.check_output(shlex.split(f'{DOCKER_COMPOSE} -f {compose_file} up -d'), stderr=subprocess.STDOUT)
subprocess.check_output(shlex.split(composeCmd), stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
pytest.fail(f"Error while runninng '{DOCKER_COMPOSE} -f {compose_file} up -d':\n{e.output}", pytrace=False)
pytest.fail(f"Error while runninng '{composeCmd}:\n{e.output}", pytrace=False)
def docker_compose_down(compose_file='docker-compose.yml'):
logging.info(f'{DOCKER_COMPOSE} -f {compose_file} down -v')
def docker_compose_down(project_name, compose_file='docker-compose.yml'):
composeCmd = f'{DOCKER_COMPOSE} --project-name {project_name} --file {compose_file} down --remove-orphans --volumes'
logging.info(composeCmd)
try:
subprocess.check_output(shlex.split(f'{DOCKER_COMPOSE} -f {compose_file} down -v'), stderr=subprocess.STDOUT)
subprocess.check_output(shlex.split(composeCmd), stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e:
pytest.fail(f"Error while runninng '{DOCKER_COMPOSE} -f {compose_file} down -v':\n{e.output}", pytrace=False)
pytest.fail(f"Error while runninng '{composeCmd}':\n{e.output}", pytrace=False)
def wait_for_nginxproxy_to_be_ready():
"""
If one (and only one) container started from image nginxproxy/nginx-proxy:test is found,
wait for its log to contain substring "Watching docker events"
If one (and only one) container started from image nginxproxy/nginx-proxy:test
or nginxproxy/nginx-proxy:test-dockergen is found, wait for its log to contain
substring "Watching docker events"
"""
containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/nginx-proxy:test"})
if len(containers) != 1:
return
container = containers[0]
for line in container.logs(stream=True):
if b"Watching docker events" in line:
logging.debug("nginx-proxy ready")
timeout = time.time() + 10
while True:
containers = docker_client.containers.list(
filters={"status": "running", "ancestor": f"nginxproxy/nginx-proxy:{IMAGE_TAG}"}
)
if len(containers) == 1:
break
if time.time() > timeout:
pytest.fail(f"Got {len(containers)} nginxproxy/nginx-proxy:{IMAGE_TAG} containers after 10s", pytrace=False)
time.sleep(1)
container = containers
conf_generated = False
while True:
for line in container[0].logs(stream=True, follow=True):
if b"Generated '/etc/nginx/conf.d/default.conf'" in line:
return
if time.time() > timeout:
pytest.fail(f"nginxproxy/nginx-proxy:{IMAGE_TAG} container not ready after 10s", pytrace=False)
time.sleep(1)
@pytest.fixture
@ -357,8 +428,8 @@ def docker_compose_file(request):
if not os.path.isfile(docker_compose_file):
logging.error("Could not find any docker compose file named either '{0}.yml', '{0}.yaml' or 'docker-compose.yml'".format(request.module.__name__))
logging.debug(f"using docker compose file {docker_compose_file}")
return docker_compose_file
logging.info(f"using docker compose file {docker_compose_file}")
yield docker_compose_file
def connect_to_network(network):
@ -371,7 +442,7 @@ def connect_to_network(network):
try:
my_container = docker_client.containers.get(test_container)
except docker.errors.NotFound:
logging.warn(f"container {test_container} not found")
logging.warning(f"container {test_container} not found")
return
# figure out our container networks
@ -399,7 +470,7 @@ def disconnect_from_network(network=None):
try:
my_container = docker_client.containers.get(test_container)
except docker.errors.NotFound:
logging.warn(f"container {test_container} not found")
logging.warning(f"container {test_container} not found")
return
# figure out our container networks
@ -427,7 +498,9 @@ def connect_to_all_networks():
class DockerComposer(contextlib.AbstractContextManager):
def __init__(self):
self._networks = None
self._docker_compose_file = None
self._project_name = None
def __exit__(self, *exc_info):
self._down()
@ -437,21 +510,20 @@ class DockerComposer(contextlib.AbstractContextManager):
return
for network in self._networks:
disconnect_from_network(network)
docker_compose_down(self._docker_compose_file)
docker_compose_down(self._project_name, self._docker_compose_file)
self._docker_compose_file = None
def compose(self, docker_compose_file):
if docker_compose_file == self._docker_compose_file:
def compose(self, project_name, docker_compose_file):
if docker_compose_file == self._docker_compose_file and project_name == self._project_name:
return
self._down()
if docker_compose_file is None:
return
remove_all_containers()
docker_compose_up(docker_compose_file)
docker_compose_up(project_name, docker_compose_file)
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._project_name = project_name
###############################################################################
@ -469,7 +541,7 @@ def docker_composer():
@pytest.fixture
def ca_root_certificate():
return CA_ROOT_CERTIFICATE
yield CA_ROOT_CERTIFICATE
@pytest.fixture
@ -480,7 +552,7 @@ def monkey_patched_dns():
@pytest.fixture
def docker_compose(monkey_patched_dns, docker_composer, docker_compose_file):
def docker_compose(request, monkey_patched_dns, docker_composer, docker_compose_file):
"""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`
@ -489,7 +561,8 @@ def docker_compose(monkey_patched_dns, docker_composer, docker_compose_file):
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.
"""
docker_composer.compose(docker_compose_file)
project_name = request.module.__name__
docker_composer.compose(project_name, docker_compose_file)
yield docker_client
@ -515,7 +588,7 @@ def acme_challenge_path():
"""
Provides fake Let's Encrypt ACME challenge path used in certain tests
"""
return ".well-known/acme-challenge/test-filename"
yield ".well-known/acme-challenge/test-filename"
###############################################################################
#
@ -526,11 +599,14 @@ def acme_challenge_path():
# pytest hook to display additionnal stuff in test report
def pytest_runtest_logreport(report):
if report.failed:
if isinstance(report.longrepr, ReprExceptionInfo):
test_containers = docker_client.containers.list(all=True, filters={"ancestor": "nginxproxy/nginx-proxy:test"})
for container in test_containers:
report.longrepr.addsection('nginx-proxy logs', container.logs())
report.longrepr.addsection('nginx-proxy conf', get_nginx_conf_from_container(container))
nginx_containers = docker_client.containers.list(all=True, filters={"label": "com.github.nginx-proxy.nginx-proxy.nginx"})
for container in nginx_containers:
report.longrepr.addsection('nginx container logs', container.logs().decode())
test_containers = docker_client.containers.list(all=True, filters={"ancestor": f"nginxproxy/nginx-proxy:{IMAGE_TAG}"})
for container in test_containers:
report.longrepr.addsection('nginx-proxy logs', container.logs().decode())
report.longrepr.addsection('nginx-proxy conf', get_nginx_conf_from_container(container).decode())
# Py.test `incremental` marker, see http://stackoverflow.com/a/12579625/107049
@ -553,9 +629,9 @@ def pytest_runtest_setup(item):
###############################################################################
try:
docker_client.images.get('nginxproxy/nginx-proxy:test')
docker_client.images.get(f"nginxproxy/nginx-proxy:{IMAGE_TAG}")
except docker.errors.ImageNotFound:
pytest.exit("The docker image 'nginxproxy/nginx-proxy:test' is missing")
pytest.exit(f"The docker image 'nginxproxy/nginx-proxy:{IMAGE_TAG}' is missing")
if Version(docker.__version__) < Version("7.0.0"):
pytest.exit("This test suite is meant to work with the python docker module v7.0.0 or later")

View file

@ -2,3 +2,4 @@ backoff==2.2.1
docker==7.1.0
pytest==8.3.4
requests==2.32.3
packaging==24.2

View file

@ -1,32 +0,0 @@
networks:
netA:
netB:
services:
reverseproxy:
container_name: reverseproxy
networks:
- netA
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
webA:
networks:
- netA
image: web
expose:
- 81
environment:
WEB_PORTS: 81
VIRTUAL_HOST: webA.nginx-proxy
webB:
networks:
- netB
image: web
expose:
- 82
environment:
WEB_PORTS: 82
VIRTUAL_HOST: webB.nginx-proxy

View file

@ -4,16 +4,6 @@ import pytest
import requests
def test_default_nginx_welcome_page_should_not_be_served(docker_compose, nginxproxy):
r = nginxproxy.get("http://whatever.nginx-proxy/", allow_redirects=False)
assert "<title>Welcome to nginx!</title>" not in r.text
def test_unknown_virtual_host_is_503(docker_compose, nginxproxy):
r = nginxproxy.get("http://unknown.nginx-proxy/", allow_redirects=False)
assert r.status_code == 503
def test_http_web_a_is_forwarded(docker_compose, nginxproxy):
r = nginxproxy.get("http://webA.nginx-proxy/port", allow_redirects=False)
assert r.status_code == 200
@ -21,12 +11,22 @@ def test_http_web_a_is_forwarded(docker_compose, nginxproxy):
def test_http_web_b_gets_an_error(docker_compose, nginxproxy):
r = nginxproxy.get("http://webB.nginx-proxy/", allow_redirects=False)
r = nginxproxy.get("http://webB.nginx-proxy/", allow_redirects=False, expected_status_code=502)
assert "<title>Welcome to nginx!</title>" not in r.text
with pytest.raises(requests.exceptions.HTTPError):
r.raise_for_status()
def test_default_nginx_welcome_page_should_not_be_served(docker_compose, nginxproxy):
r = nginxproxy.get("http://whatever.nginx-proxy/", allow_redirects=False, expected_status_code=503)
assert "<title>Welcome to nginx!</title>" not in r.text
def test_unknown_virtual_host_is_503(docker_compose, nginxproxy):
r = nginxproxy.get("http://unknown.nginx-proxy/", allow_redirects=False, expected_status_code=503)
assert r.status_code == 503
def test_reverseproxy_survive_restart(docker_compose):
docker_compose.containers.get("reverseproxy").restart()
sleep(2) # give time for the container to initialize

View file

@ -0,0 +1,63 @@
networks:
netA:
netB:
volumes:
nginx_conf:
services:
reverseproxy:
profiles:
- singleContainer
container_name: reverseproxy
networks:
- netA
image: nginxproxy/nginx-proxy:test
volumes:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
docker-gen:
profiles:
- separateContainers
networks:
- netA
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment:
NGINX_CONTAINER_NAME: reverseproxy
reverseproxynginx:
profiles:
- separateContainers
container_name: reverseproxy
networks:
- netA
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
webA:
networks:
- netA
image: web
expose:
- 81
environment:
WEB_PORTS: 81
VIRTUAL_HOST: webA.nginx-proxy
webB:
networks:
- netB
image: web
expose:
- 82
environment:
WEB_PORTS: 82
VIRTUAL_HOST: webB.nginx-proxy

View file

@ -1,23 +0,0 @@
services:
web1:
image: web
expose:
- "81"
environment:
WEB_PORTS: 81
VIRTUAL_HOST: web1.nginx-proxy.tld
web2:
image: web
expose:
- "82"
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,10 +1,8 @@
import pytest
def test_redirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web1.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
allow_redirects=False,
expected_status_code=301
)
assert r.status_code == 301
@ -18,7 +16,8 @@ def test_redirect_acme_challenge_location_enabled(docker_compose, nginxproxy, ac
def test_noredirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web3.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
allow_redirects=False,
expected_status_code=404
)
assert r.status_code == 404

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
web1:
image: web
@ -36,10 +40,34 @@ services:
ACME_HTTP_CHALLENGE_LOCATION: "true"
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
environment:
environment: &nginxProxyEnv
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
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &certs ./certs:/etc/nginx/certs:ro
- &acmeRoot ./acme_root:/usr/share/nginx/html:ro
sutdockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
environment: *nginxProxyEnv
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *certs
sutnginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *certs
- *acmeRoot
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,6 +1,3 @@
import pytest
def test_redirect_acme_challenge_location_enabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web1.nginx-proxy.tld/{acme_challenge_path}",
@ -11,7 +8,8 @@ def test_redirect_acme_challenge_location_enabled(docker_compose, nginxproxy, ac
def test_redirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web2.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
allow_redirects=False,
expected_status_code=301
)
assert r.status_code == 301
@ -25,6 +23,7 @@ def test_noredirect_acme_challenge_location_enabled(docker_compose, nginxproxy,
def test_noredirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web4.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
allow_redirects=False,
expected_status_code=404
)
assert r.status_code == 404

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
web1:
image: web
@ -36,8 +40,31 @@ services:
ACME_HTTP_CHALLENGE_LOCATION: "false"
sut:
profiles:
- singleContainer
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
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &certs ./certs:/etc/nginx/certs:ro
- &acmeRoot ./acme_root:/usr/share/nginx/html:ro
sutdockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *certs
sutnginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *certs
- *acmeRoot
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,6 +1,3 @@
import pytest
def test_redirect_acme_challenge_location_legacy(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web1.nginx-proxy.tld/{acme_challenge_path}",
@ -11,6 +8,7 @@ def test_redirect_acme_challenge_location_legacy(docker_compose, nginxproxy, acm
def test_noredirect_acme_challenge_location_legacy(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web2.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
allow_redirects=False,
expected_status_code=404
)
assert r.status_code == 404

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
web1:
image: web
@ -17,10 +21,34 @@ services:
HTTPS_METHOD: noredirect
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
environment:
environment: &nginxProxyEnv
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
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &certs ./certs:/etc/nginx/certs:ro
- &acmeRoot ./acme_root:/usr/share/nginx/html:ro
sutdockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
environment: *nginxProxyEnv
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *certs
sutnginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *certs
- *acmeRoot
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,8 +1,7 @@
import pytest
import re
def test_custom_error_page(docker_compose, nginxproxy):
r = nginxproxy.get("http://unknown.nginx-proxy.tld")
r = nginxproxy.get("http://unknown.nginx-proxy.tld", expected_status_code=503)
assert r.status_code == 503
assert re.search(r"Damn, there's some maintenance in progress.", r.text)

View file

@ -1,6 +1,32 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./50x.html:/usr/share/nginx/html/errors/50x.html:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &customErrorPage ./50x.html:/usr/share/nginx/html/errors/50x.html:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *customErrorPage
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *customErrorPage
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,10 +1,3 @@
import pytest
def test_custom_default_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503
assert "X-test" not in r.headers
def test_custom_default_conf_applies_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200
@ -19,10 +12,14 @@ def test_custom_default_conf_applies_to_web2(docker_compose, nginxproxy):
assert "X-test" in r.headers
assert "f00" == r.headers["X-test"]
def test_custom_default_conf_is_overriden_for_web3(docker_compose, nginxproxy):
r = nginxproxy.get("http://web3.nginx-proxy.example/port")
assert r.status_code == 200
assert r.text == "answer from port 83\n"
assert "X-test" in r.headers
assert "bar" == r.headers["X-test"]
def test_custom_default_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/", expected_status_code=503)
assert r.status_code == 503
assert "X-test" not in r.headers

View file

@ -1,10 +1,38 @@
volumes:
nginx_conf:
services:
nginx-proxy:
profiles:
- singleContainer
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
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &defaultLocation ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/default_location:ro
- &vhostLocation ./my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/web3.nginx-proxy.example_location:ro
nginx-proxy-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *defaultLocation
- *vhostLocation
nginx-proxy-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *defaultLocation
- *vhostLocation
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
web1:
image: web

View file

@ -1,10 +1,3 @@
import pytest
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503
assert "X-test" not in r.headers
def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200
@ -18,3 +11,8 @@ def test_custom_conf_applies_to_web2(docker_compose, nginxproxy):
assert r.text == "answer from port 82\n"
assert "X-test" in r.headers
assert "f00" == r.headers["X-test"]
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/", expected_status_code=503)
assert r.status_code == 503
assert "X-test" not in r.headers

View file

@ -1,9 +1,35 @@
volumes:
nginx_conf:
services:
nginx-proxy:
profiles:
- singleContainer
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
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &defaultConf ./my_custom_proxy_settings_f00.conf:/etc/nginx/proxy.conf:ro
nginx-proxy-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *defaultConf
nginx-proxy-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *defaultConf
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
web1:
image: web

View file

@ -1,10 +1,3 @@
import pytest
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503
assert "X-test" not in r.headers
def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200
@ -25,5 +18,10 @@ def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy):
assert r.text == "answer from port 82\n"
assert "X-test" not in r.headers
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/", expected_status_code=503)
assert r.status_code == 503
assert "X-test" not in r.headers
def test_custom_block_is_present_in_nginx_generated_conf(docker_compose, nginxproxy):
assert b"include /etc/nginx/vhost.d/web1.nginx-proxy.example_location;" in nginxproxy.get_conf()

View file

@ -1,10 +1,38 @@
volumes:
nginx_conf:
services:
nginx-proxy:
profiles:
- singleContainer
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
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &vhostLocationConf ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example_location:ro
- &regexLocationConf ./my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430_location:ro
nginx-proxy-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *vhostLocationConf
- *regexLocationConf
nginx-proxy-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *vhostLocationConf
- *regexLocationConf
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
web1:
image: web
@ -21,7 +49,7 @@ services:
environment:
WEB_PORTS: 82
VIRTUAL_HOST: web2.nginx-proxy.example
regex:
image: web
expose:

View file

@ -1,10 +1,3 @@
import pytest
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503
assert "X-test" not in r.headers
def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200
@ -24,3 +17,8 @@ def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy):
assert r.status_code == 200
assert r.text == "answer from port 82\n"
assert "X-test" not in r.headers
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/", expected_status_code=503)
assert r.status_code == 503
assert "X-test" not in r.headers

View file

@ -1,10 +1,38 @@
volumes:
nginx_conf:
services:
nginx-proxy:
profiles:
- singleContainer
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
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &vhostConf ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example:ro
- &regexConf ./my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430:ro
nginx-proxy-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *vhostConf
- *regexConf
nginx-proxy-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *vhostConf
- *regexConf
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
web1:
image: web
@ -21,7 +49,7 @@ services:
environment:
WEB_PORTS: 82
VIRTUAL_HOST: web2.nginx-proxy.example
regex:
image: web
expose:

View file

@ -1,10 +1,3 @@
import pytest
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503
assert "X-test" not in r.headers
def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200
@ -18,3 +11,8 @@ def test_custom_conf_applies_to_web2(docker_compose, nginxproxy):
assert r.text == "answer from port 82\n"
assert "X-test" in r.headers
assert "f00" == r.headers["X-test"]
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/", expected_status_code=503)
assert r.status_code == 503
assert "X-test" not in r.headers

View file

@ -1,9 +1,35 @@
volumes:
nginx_conf:
services:
nginx-proxy:
profiles:
- singleContainer
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
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &proxyConf ./my_custom_proxy_settings_f00.conf:/etc/nginx/conf.d/my_custom_proxy_settings_f00.conf:ro
nginx-proxy-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *proxyConf
nginx-proxy-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *proxyConf
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
web1:
image: web

View file

@ -42,5 +42,5 @@ def test_debug_endpoint_hostname_replaced_by_warning_if_regexp(docker_compose, n
def test_debug_endpoint_is_disabled_per_container(docker_compose, nginxproxy):
r = nginxproxy.get("http://disabled.debug.nginx-proxy.example/nginx-proxy-debug")
r = nginxproxy.get("http://disabled.debug.nginx-proxy.example/nginx-proxy-debug", expected_status_code=404)
assert r.status_code == 404

View file

@ -1,11 +1,36 @@
volumes:
nginx_conf:
services:
nginx-proxy:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
DEBUG_ENDPOINT: "true"
nginx-proxy-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
nginx-proxy-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
debug_enabled:
image: web
expose:
@ -13,7 +38,7 @@ services:
environment:
WEB_PORTS: 81
VIRTUAL_HOST: enabled.debug.nginx-proxy.example
debug_stripped:
image: web
expose:
@ -42,7 +67,7 @@ services:
"/18":
"/19":
"/20":
debug_regexp:
image: web
expose:

View file

@ -2,9 +2,9 @@ import json
import pytest
def test_debug_endpoint_is_disabled_globally(docker_compose, nginxproxy):
r = nginxproxy.get("http://disabled1.debug.nginx-proxy.example/nginx-proxy-debug")
r = nginxproxy.get("http://disabled1.debug.nginx-proxy.example/nginx-proxy-debug", expected_status_code=404)
assert r.status_code == 404
r = nginxproxy.get("http://disabled2.debug.nginx-proxy.example/nginx-proxy-debug")
r = nginxproxy.get("http://disabled2.debug.nginx-proxy.example/nginx-proxy-debug", expected_status_code=404)
assert r.status_code == 404

View file

@ -1,8 +1,32 @@
volumes:
nginx_conf:
services:
nginx-proxy:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
nginx-proxy-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
nginx-proxy-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
debug_disabled1:
image: web
@ -11,7 +35,7 @@ services:
environment:
WEB_PORTS: 81
VIRTUAL_HOST: disabled1.debug.nginx-proxy.example
debug_disabled2:
image: web
expose:
@ -20,7 +44,6 @@ services:
WEB_PORTS: 82
VIRTUAL_HOST: disabled2.debug.nginx-proxy.example
debug_enabled:
image: web
expose:

View file

@ -1,6 +1,3 @@
import pytest
def test_fallback_on_default(docker_compose, nginxproxy):
r = nginxproxy.get("http://unknown.nginx-proxy.tld/port")
assert r.status_code == 200

View file

@ -1,5 +1,8 @@
volumes:
nginx_conf:
services:
# GIVEN a webserver with VIRTUAL_HOST set to web1.tld
web1:
image: web
expose:
@ -8,10 +11,30 @@ services:
WEB_PORTS: 81
VIRTUAL_HOST: web1.tld
# WHEN nginx-proxy runs with DEFAULT_HOST set to web1.tld
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
DEFAULT_HOST: web1.tld
sutdockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
environment: *nginxProxyEnv
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
sutnginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,15 +1,13 @@
import pytest
def test_unknown_virtual_host(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/port")
assert r.status_code == 503
def test_forwards_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.tld/port")
assert r.status_code == 200
assert r.status_code == 200
assert r.text == "answer from port 81\n"
def test_forwards_to_web2(docker_compose, nginxproxy):
r = nginxproxy.get("http://web2.nginx-proxy.tld/port")
assert r.status_code == 200
assert r.text == "answer from port 82\n"
assert r.text == "answer from port 82\n"
def test_unknown_virtual_host(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/port", expected_status_code=503)
assert r.status_code == 503

View file

@ -0,0 +1,48 @@
volumes:
nginx_conf:
services:
web1:
image: web
expose:
- "81"
environment:
WEB_PORTS: 81
VIRTUAL_HOST: web1.nginx-proxy.tld
web2:
image: web
expose:
- "82"
environment:
WEB_PORTS: 82
VIRTUAL_HOST: web2.nginx-proxy.tld
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- &dockerSocket /var/run/docker.sock:/f00.sock:ro
environment: &nginxProxyEnv
DOCKER_HOST: unix:///f00.sock
sutdockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
sutnginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,12 +1,10 @@
import docker
import os
import pytest
from packaging.version import Version
raw_version = docker.from_env().version()["Version"]
pytestmark = pytest.mark.skipif(
Version(raw_version) < Version("1.13"),
reason="Docker compose syntax v3 requires docker engine v1.13 or later (got {raw_version})"
True,
reason="This test intefers with the other tests, and might no longer be needed."
)

View file

@ -1,9 +1,13 @@
volumes:
nginx_conf_dockergen:
services:
nginx:
image: nginx
container_name: nginx
volumes:
- nginx_conf:/etc/nginx/conf.d:ro
- nginx_conf_dockergen:/etc/nginx/conf.d:ro
dockergen:
image: nginxproxy/docker-gen
@ -11,7 +15,7 @@ services:
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ../../nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl
- nginx_conf:/etc/nginx/conf.d
- nginx_conf_dockergen:/etc/nginx/conf.d
web:
image: web
@ -21,6 +25,3 @@ services:
environment:
WEB_PORTS: 80
VIRTUAL_HOST: whoami.nginx.container.docker
volumes:
nginx_conf:

View file

@ -1,18 +1,23 @@
import pytest
def test_nohttp_missing_cert_disabled(docker_compose, nginxproxy):
r = nginxproxy.get("http://nohttp-missing-cert-disabled.nginx-proxy.tld/", allow_redirects=False)
assert r.status_code == 503
def test_nohttp_missing_cert_enabled(docker_compose, nginxproxy):
r = nginxproxy.get("http://nohttp-missing-cert-enabled.nginx-proxy.tld/", allow_redirects=False)
assert r.status_code == 200
def test_redirect_missing_cert_disabled(docker_compose, nginxproxy):
r = nginxproxy.get("http://redirect-missing-cert-disabled.nginx-proxy.tld/", allow_redirects=False)
assert r.status_code == 301
def test_nohttp_missing_cert_disabled(docker_compose, nginxproxy):
r = nginxproxy.get(
"http://nohttp-missing-cert-disabled.nginx-proxy.tld/",
allow_redirects=False,
expected_status_code=503
)
assert r.status_code == 503
def test_redirect_missing_cert_enabled(docker_compose, nginxproxy):
r = nginxproxy.get("http://redirect-missing-cert-enabled.nginx-proxy.tld/", allow_redirects=False)
assert r.status_code == 200
def test_redirect_missing_cert_disabled(docker_compose, nginxproxy):
r = nginxproxy.get(
"http://redirect-missing-cert-disabled.nginx-proxy.tld/",
allow_redirects=False,
expected_status_code=301
)
assert r.status_code == 301

View file

@ -1,12 +1,39 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &certs ./withdefault.certs:/etc/nginx/certs:ro
environment: &nginxProxyEnv
ENABLE_HTTP_ON_MISSING_CERT: "false"
sutdockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
environment: *nginxProxyEnv
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *certs
sutnginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *certs
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
nohttp-missing-cert-disabled:
image: web
expose:

View file

@ -22,7 +22,7 @@ def web1(docker_compose):
},
ports={"81/tcp": None}
)
docker_compose.networks.get("test_default").connect(container)
docker_compose.networks.get("nginx-proxy-test-events").connect(container)
sleep(2) # give it some time to initialize and for docker-gen to detect it
yield container
try:
@ -47,7 +47,7 @@ def web2(docker_compose):
},
ports={"82/tcp": None}
)
docker_compose.networks.get("test_default").connect(container)
docker_compose.networks.get("nginx-proxy-test-events").connect(container)
sleep(2) # give it some time to initialize and for docker-gen to detect it
yield container
try:
@ -56,7 +56,7 @@ def web2(docker_compose):
pass
def test_nginx_proxy_behavior_when_alone(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/")
r = nginxproxy.get("http://nginx-proxy/", expected_status_code=503)
assert r.status_code == 503
@ -67,18 +67,18 @@ def test_new_container_is_detected_vhost(web1, nginxproxy):
web1.remove(force=True)
sleep(2)
r = nginxproxy.get("http://web1.nginx-proxy/port")
r = nginxproxy.get("http://web1.nginx-proxy/port", expected_status_code=503)
assert r.status_code == 503
def test_new_container_is_detected_vpath(web2, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/web2/port")
assert r.status_code == 200
assert "answer from port 82\n" == r.text
r = nginxproxy.get("http://nginx-proxy/port")
r = nginxproxy.get("http://nginx-proxy/port", expected_status_code=[404, 503])
assert r.status_code in [404, 503]
web2.remove(force=True)
sleep(2)
r = nginxproxy.get("http://nginx-proxy/web2/port")
r = nginxproxy.get("http://nginx-proxy/web2/port", expected_status_code=503)
assert r.status_code == 503

View file

@ -1,5 +1,33 @@
networks:
default:
name: nginx-proxy-test-events
volumes:
nginx_conf:
services:
nginxproxy:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
nginxproxy-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
nginxproxy-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,9 +1,35 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./custom-fallback.conf:/etc/nginx/conf.d/zzz-custom-fallback.conf:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &customFallback ./custom-fallback.conf:/etc/nginx/conf.d/zzz-custom-fallback.conf:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *customFallback
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *customFallback
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
http-only:
image: web

View file

@ -1,9 +1,35 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nodefault.certs:/etc/nginx/certs:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &certs ./nodefault.certs:/etc/nginx/certs:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *certs
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *certs
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
https-and-http:
image: web

View file

@ -1,12 +1,39 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &certs ./withdefault.certs:/etc/nginx/certs:ro
environment: &nginxProxyEnv
HTTPS_METHOD: redirect
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *certs
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *certs
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
https-only:
image: web
expose:

View file

@ -1,12 +1,39 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &certs ./withdefault.certs:/etc/nginx/certs:ro
environment: &nginxProxyEnv
HTTPS_METHOD: nohttp
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *certs
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *certs
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
https-only:
image: web
expose:

View file

@ -1,12 +1,39 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &certs ./withdefault.certs:/etc/nginx/certs:ro
environment: &nginxProxyEnv
HTTPS_METHOD: nohttp
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *certs
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *certs
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
https-only:
image: web
expose:

View file

@ -1,11 +1,36 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
HTTPS_METHOD: redirect
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
http-only:
image: web
expose:

View file

@ -1,11 +1,36 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
HTTPS_METHOD: nohttps
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
http-only:
image: web
expose:

View file

@ -1,12 +1,39 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &certs ./withdefault.certs:/etc/nginx/certs:ro
environment: &nginxProxyEnv
TRUST_DEFAULT_CERT: "false"
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *certs
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *certs
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
https-and-http:
image: web
expose:

View file

@ -1,9 +1,35 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &certs ./withdefault.certs:/etc/nginx/certs:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *certs
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *certs
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
https-and-http:
image: web
@ -38,7 +64,7 @@ services:
environment:
WEB_PORTS: "84"
VIRTUAL_HOST: missing-cert.nginx-proxy.test
missing-cert-default-untrusted:
image: web
expose:

View file

@ -26,8 +26,11 @@ def get(docker_compose, nginxproxy, want_err_re):
interval=.3,
max_tries=30,
jitter=None)
def _get(url):
return nginxproxy.get(url, allow_redirects=False)
def _get(url, expected_status_code=None):
if expected_status_code is None:
return nginxproxy.get_without_backoff(url, allow_redirects=False)
else:
return nginxproxy.get(url, allow_redirects=False, expected_status_code=expected_status_code)
return _get
@ -110,7 +113,7 @@ INTERNAL_ERR_RE = re.compile("TLSV1_UNRECOGNIZED_NAME")
])
def test_fallback(get, url, want_code, want_err_re):
if want_err_re is None:
r = get(url)
r = get(url, want_code)
assert r.status_code == want_code
else:
with pytest.raises(requests.exceptions.SSLError, match=want_err_re):

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

@ -1,3 +1,7 @@
import os
import pytest
def test_arbitrary_headers_are_passed_on(docker_compose, nginxproxy):
r = nginxproxy.get("http://web.nginx-proxy.tld/headers", headers={'Foo': 'Bar'})
assert r.status_code == 200
@ -91,9 +95,13 @@ def test_httpoxy_safe(docker_compose, nginxproxy):
assert "Proxy:" not in r.text
@pytest.mark.xfail(
condition = os.environ.get("COMPOSE_PROFILES") == "separateContainers",
reason = "This test is expected to fail when using separate containers",
)
def test_no_host_server_tokens_off(docker_compose, nginxproxy):
ip = nginxproxy.get_ip()
r = nginxproxy.get(f"http://{ip}/headers")
r = nginxproxy.get(f"http://{ip}/headers", expected_status_code=503)
assert r.status_code == 503
assert r.headers["Server"] == "nginx"

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
web:
image: web
@ -17,6 +21,26 @@ services:
SERVER_TOKENS: "off"
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,3 +1,4 @@
import os
import pytest
@ -94,10 +95,14 @@ def test_httpoxy_safe(docker_compose, nginxproxy):
assert "Proxy:" not in r.text
@pytest.mark.xfail(
condition = os.environ.get("COMPOSE_PROFILES") == "separateContainers",
reason = "This test is expected to fail when using separate containers",
)
@pytest.mark.filterwarnings('ignore::urllib3.exceptions.InsecureRequestWarning')
def test_no_host_server_tokens_off(docker_compose, nginxproxy):
ip = nginxproxy.get_ip()
r = nginxproxy.get(f"https://{ip}/headers", verify=False)
r = nginxproxy.get(f"https://{ip}/headers", verify=False, expected_status_code=503)
assert r.status_code == 503
assert r.headers["Server"] == "nginx"

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
web:
image: web
@ -17,12 +21,29 @@ services:
SERVER_TOKENS: "off"
sut:
profiles:
- singleContainer
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
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &certs ./certs:/etc/nginx/certs:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *certs
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *certs
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,6 +1,3 @@
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

View file

@ -3,6 +3,11 @@ networks:
internal: true
net2:
volumes:
nginx_conf:
services:
bridge-network:
image: web
@ -21,9 +26,35 @@ services:
network_mode: host
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
networks:
- net1
- net2
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
networks:
- net1
- net2
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
networks:
- net1
- net2
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,6 +1,3 @@
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

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
host-network-1:
image: web
@ -16,9 +20,30 @@ services:
network_mode: host
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
HTTP_PORT: 8888
network_mode: host
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,7 +1,5 @@
import pytest
def test_htpasswd_regex_virtual_host_is_restricted(docker_compose, nginxproxy):
r = nginxproxy.get("http://regex.htpasswd.nginx-proxy.example/port")
r = nginxproxy.get("http://regex.htpasswd.nginx-proxy.example/port", expected_status_code=401)
assert r.status_code == 401
assert "WWW-Authenticate" in r.headers
assert r.headers["WWW-Authenticate"] == 'Basic realm="Restricted access"'

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
regex:
image: web
@ -8,8 +12,30 @@ services:
VIRTUAL_HOST: ~^regex.*\.nginx-proxy\.example$
sut:
profiles:
- singleContainer
container_name: sut
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./htpasswd:/etc/nginx/htpasswd:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &htpasswd ./htpasswd:/etc/nginx/htpasswd:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *htpasswd
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *htpasswd
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,7 +1,5 @@
import pytest
def test_htpasswd_virtual_host_is_restricted(docker_compose, nginxproxy):
r = nginxproxy.get("http://htpasswd.nginx-proxy.tld/port")
r = nginxproxy.get("http://htpasswd.nginx-proxy.tld/port", expected_status_code=401)
assert r.status_code == 401
assert "WWW-Authenticate" in r.headers
assert r.headers["WWW-Authenticate"] == 'Basic realm="Restricted htpasswd.nginx-proxy.tld"'

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
web:
image: web
@ -8,8 +12,30 @@ services:
VIRTUAL_HOST: htpasswd.nginx-proxy.tld
sut:
profiles:
- singleContainer
container_name: sut
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./htpasswd:/etc/nginx/htpasswd:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &htpasswd ./htpasswd:/etc/nginx/htpasswd:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *htpasswd
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *htpasswd
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,7 +1,5 @@
import pytest
def test_htpasswd_virtual_path_is_restricted(docker_compose, nginxproxy):
r = nginxproxy.get("http://htpasswd.nginx-proxy.tld/foo/port")
r = nginxproxy.get("http://htpasswd.nginx-proxy.tld/foo/port", expected_status_code=401)
assert r.status_code == 401
assert "WWW-Authenticate" in r.headers
assert r.headers["WWW-Authenticate"] == 'Basic realm="Restricted htpasswd.nginx-proxy.tld/foo/"'

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
web:
image: web
@ -10,8 +14,30 @@ services:
VIRTUAL_DEST: /
sut:
profiles:
- singleContainer
container_name: sut
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./htpasswd:/etc/nginx/htpasswd:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &htpasswd ./htpasswd:/etc/nginx/htpasswd:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *htpasswd
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *htpasswd
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,4 +1,3 @@
import pytest
import re
def test_http2_global_disabled_config(docker_compose, nginxproxy):

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
http2-global-disabled:
image: web
@ -8,8 +12,29 @@ services:
VIRTUAL_HOST: http2-global-disabled.nginx-proxy.tld
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
ENABLE_HTTP2: "false"
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,4 +1,3 @@
import pytest
import re
#Python Requests is not able to do native http3 requests.

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
http3-global-disabled:
image: web
@ -8,8 +12,30 @@ services:
VIRTUAL_HOST: http3-global-disabled.nginx-proxy.tld
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
#environment:
#ENABLE_HTTP3: "false" #Disabled by default
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
#environment:
#ENABLE_HTTP3: "false" #Disabled by default
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,4 +1,3 @@
import pytest
import re
#Python Requests is not able to do native http3 requests.

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
http3-global-enabled:
image: web
@ -8,8 +12,29 @@ services:
VIRTUAL_HOST: http3-global-enabled.nginx-proxy.tld
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
ENABLE_HTTP3: "true"
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,4 +1,3 @@
import pytest
import re
#Python Requests is not able to do native http3 requests.

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
http3-vhost-enabled:
image: web
@ -28,6 +32,26 @@ services:
VIRTUAL_HOST: http3-vhost-default-disabled.nginx-proxy.tld
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
web1:
image: web
@ -8,8 +12,29 @@ services:
VIRTUAL_HOST: "*.nginx-proxy.tld"
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
HTTP_PORT: 8080
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,5 +1,3 @@
import pytest
def test_network_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
web1:
image: web
@ -17,7 +21,29 @@ services:
VIRTUAL_HOST: web2.nginx-proxy.example
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./network_internal.conf:/etc/nginx/network_internal.conf:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &networkInternal ./network_internal.conf:/etc/nginx/network_internal.conf:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *networkInternal
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *networkInternal
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,5 +1,3 @@
import pytest
def test_network_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy.example/web1/port")
assert r.status_code == 200

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
web1:
image: web
@ -21,7 +25,29 @@ services:
VIRTUAL_DEST: /
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./network_internal.conf:/etc/nginx/network_internal.conf:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &networkInternal ./network_internal.conf:/etc/nginx/network_internal.conf:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *networkInternal
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *networkInternal
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,25 +1,17 @@
import pytest
def test_unknown_virtual_host_ipv4(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/port")
assert r.status_code == 503
def test_forwards_to_web1_ipv4(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.tld/port")
assert r.status_code == 200
assert r.status_code == 200
assert r.text == "answer from port 81\n"
def test_forwards_to_web2_ipv4(docker_compose, nginxproxy):
r = nginxproxy.get("http://web2.nginx-proxy.tld/port")
assert r.status_code == 200
assert r.text == "answer from port 82\n"
assert r.text == "answer from port 82\n"
def test_unknown_virtual_host_ipv6(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/port", ipv6=True)
def test_unknown_virtual_host_ipv4(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/port", expected_status_code=503)
assert r.status_code == 503
@ -33,3 +25,8 @@ def test_forwards_to_web2_ipv6(docker_compose, nginxproxy):
r = nginxproxy.get("http://web2.nginx-proxy.tld/port", ipv6=True)
assert r.status_code == 200
assert r.text == "answer from port 82\n"
def test_unknown_virtual_host_ipv6(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/port", ipv6=True, expected_status_code=503)
assert r.status_code == 503

View file

@ -5,6 +5,10 @@ networks:
config:
- subnet: fd00:1::/80
volumes:
nginx_conf:
services:
web1:
image: web
@ -27,10 +31,35 @@ services:
- net1
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
ENABLE_IPV6: "true"
networks:
- net1
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
networks:
- net1
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
networks:
- net1

View file

@ -1,6 +1,3 @@
import pytest
def test_forwards_to_ipv4_only_network(docker_compose, nginxproxy):
r = nginxproxy.get("http://ipv4only.nginx-proxy.tld/port")
assert r.status_code == 200

View file

@ -10,6 +10,10 @@ networks:
- subnet: 172.16.20.0/24
- subnet: fd00:cafe:face:feed::/64
volumes:
nginx_conf:
services:
ipv4only:
image: web
@ -32,12 +36,39 @@ services:
ipv6_address: fd00:cafe:face:feed::2
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
networks:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
networks: &nginxProxyNetworks
ipv4net:
ipv4_address: 172.16.10.3
dualstacknet:
ipv4_address: 172.16.20.3
ipv6_address: fd00:cafe:face:feed::3
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
networks: *nginxProxyNetworks
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
networks:
ipv4net:
ipv4_address: 172.16.10.4
dualstacknet:
ipv4_address: 172.16.20.4
ipv6_address: fd00:cafe:face:feed::4

View file

@ -1,6 +1,3 @@
import pytest
def test_forwards_to_ipv4_only_network(docker_compose, nginxproxy):
r = nginxproxy.get("http://ipv4only.nginx-proxy.tld/port")
assert r.status_code == 200

View file

@ -10,6 +10,10 @@ networks:
- subnet: 172.16.20.0/24
- subnet: fd00:cafe:face:feed::/64
volumes:
nginx_conf:
services:
ipv4only:
image: web
@ -32,14 +36,42 @@ services:
ipv6_address: fd00:cafe:face:feed::2
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
PREFER_IPV6_NETWORK: "true"
networks:
networks: &nginxProxyNetworks
ipv4net:
ipv4_address: 172.16.10.3
dualstacknet:
ipv4_address: 172.16.20.3
ipv6_address: fd00:cafe:face:feed::3
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
networks: *nginxProxyNetworks
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
networks:
ipv4net:
ipv4_address: 172.16.10.4
dualstacknet:
ipv4_address: 172.16.20.4
ipv6_address: fd00:cafe:face:feed::4

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
keepalive-disabled:
image: web
@ -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:
@ -31,8 +35,29 @@ services:
VIRTUAL_HOST: keepalive-auto.nginx-proxy.test
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
HTTPS_METHOD: nohttps
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,4 +1,3 @@
import pytest
import re
def test_loadbalance_hash(docker_compose, nginxproxy):

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services:
loadbalance-hash:
image: web
@ -22,6 +26,26 @@ services:
replicas: 2
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,39 +1,39 @@
def test_explicit_root_nohash(docker_compose, nginxproxy):
r = nginxproxy.get("http://explicit-root-nohash.nginx-proxy.test/port")
assert r.status_code == 418
r = nginxproxy.get("http://explicit-root-nohash.nginx-proxy.test/foo/port")
assert r.status_code == 200
assert r.text == "answer from port 82\n"
r = nginxproxy.get("http://explicit-root-nohash.nginx-proxy.test/port", expected_status_code=418)
assert r.status_code == 418
def test_explicit_root_hash(docker_compose, nginxproxy):
r = nginxproxy.get("http://explicit-root-hash.nginx-proxy.test/port")
assert r.status_code == 418
r = nginxproxy.get("http://explicit-root-hash.nginx-proxy.test/foo/port")
assert r.status_code == 200
assert r.text == "answer from port 82\n"
r = nginxproxy.get("http://explicit-root-hash.nginx-proxy.test/port", expected_status_code=418)
assert r.status_code == 418
def test_explicit_root_hash_and_nohash(docker_compose, nginxproxy):
r = nginxproxy.get("http://explicit-root-hash-and-nohash.nginx-proxy.test/port")
assert r.status_code == 418
r = nginxproxy.get("http://explicit-root-hash-and-nohash.nginx-proxy.test/foo/port")
assert r.status_code == 200
assert r.text == "answer from port 82\n"
r = nginxproxy.get("http://explicit-root-hash-and-nohash.nginx-proxy.test/port", expected_status_code=418)
assert r.status_code == 418
def test_explicit_nonroot(docker_compose, nginxproxy):
r = nginxproxy.get("http://explicit-nonroot.nginx-proxy.test/port")
assert r.status_code == 200
assert r.text == "answer from port 81\n"
r = nginxproxy.get("http://explicit-nonroot.nginx-proxy.test/foo/port")
r = nginxproxy.get("http://explicit-nonroot.nginx-proxy.test/foo/port", expected_status_code=418)
assert r.status_code == 418
def test_implicit_root_nohash(docker_compose, nginxproxy):
r = nginxproxy.get("http://implicit-root-nohash.nginx-proxy.test/port")
r = nginxproxy.get("http://implicit-root-nohash.nginx-proxy.test/port", expected_status_code=418)
assert r.status_code == 418
def test_implicit_root_hash(docker_compose, nginxproxy):
r = nginxproxy.get("http://implicit-root-hash.nginx-proxy.test/port")
r = nginxproxy.get("http://implicit-root-hash.nginx-proxy.test/port", expected_status_code=418)
assert r.status_code == 418
def test_implicit_root_hash_and_nohash(docker_compose, nginxproxy):
r = nginxproxy.get("http://implicit-root-hash-and-nohash.nginx-proxy.test/port")
r = nginxproxy.get("http://implicit-root-hash-and-nohash.nginx-proxy.test/port", expected_status_code=418)
assert r.status_code == 418

View file

@ -1,9 +1,35 @@
volumes:
nginx_conf:
services:
sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./test_location-override.vhost.d:/etc/nginx/vhost.d:ro
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- &locationOverride ./test_location-override.vhost.d:/etc/nginx/vhost.d:ro
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
- *locationOverride
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
- *locationOverride
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"
explicit-root:
image: web

View file

@ -1,10 +1,13 @@
import time
import pytest
def test_log_disabled(docker_compose, nginxproxy):
time.sleep(3)
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,3 +1,7 @@
volumes:
nginx_conf:
services:
web1:
image: web
@ -8,9 +12,30 @@ services:
VIRTUAL_HOST: nginx-proxy.test
sut:
container_name: sut
profiles:
- singleContainer
container_name: nginx-proxy
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
DISABLE_ACCESS_LOGS: true
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -1,10 +1,13 @@
import time
import pytest
def test_log_format(docker_compose, nginxproxy):
time.sleep(3)
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,3 +1,7 @@
volumes:
nginx_conf:
services:
web1:
image: web
@ -8,9 +12,30 @@ services:
VIRTUAL_HOST: nginx-proxy.test
sut:
container_name: sut
profiles:
- singleContainer
container_name: nginx-proxy
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
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'
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -7,7 +7,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,3 +1,7 @@
volumes:
nginx_conf:
services:
web1:
image: web
@ -8,9 +12,30 @@ services:
VIRTUAL_HOST: nginx-proxy.test
sut:
container_name: sut
profiles:
- singleContainer
container_name: nginx-proxy
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
environment:
- &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: &nginxProxyEnv
LOG_JSON: 1
sut-dockergen:
profiles:
- separateContainers
image: nginxproxy/nginx-proxy:test-dockergen
volumes:
- &confVolume nginx_conf:/etc/nginx/conf.d
- *dockerSocket
environment: *nginxProxyEnv
sut-nginx:
profiles:
- separateContainers
container_name: nginx-proxy
image: nginx:alpine
volumes:
- *confVolume
labels:
- "com.github.nginx-proxy.nginx-proxy.nginx"

View file

@ -7,7 +7,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]

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