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

View file

@ -20,7 +20,7 @@ jobs:
strategy: strategy:
matrix: matrix:
base_docker_image: [alpine, debian] flavor: [alpine, debian, dockergen]
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -43,8 +43,10 @@ jobs:
run: make build-webserver run: make build-webserver
- name: Build Docker nginx proxy test image - 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 - name: Run tests
run: pytest run: pytest
working-directory: test 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: build-nginx-proxy-test-alpine:
docker build --pull --build-arg NGINX_PROXY_VERSION="test" -f Dockerfile.alpine -t nginxproxy/nginx-proxy:test . 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-debian: build-webserver build-nginx-proxy-test-debian
test/pytest.sh test/pytest.sh
test-alpine: export COMPOSE_PROFILES = singleContainer
test-alpine: build-webserver build-nginx-proxy-test-alpine test-alpine: build-webserver build-nginx-proxy-test-alpine
test/pytest.sh 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 # 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 _print_version
_check_unix_socket _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". 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 EOT
fi 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 fi
exec "$@" exec "$@"

View file

@ -1,6 +1,7 @@
import contextlib import contextlib
import logging import logging
import os import os
import platform
import re import re
import shlex import shlex
import socket import socket
@ -9,12 +10,11 @@ import time
from typing import List from typing import List
import backoff import backoff
import docker import docker.errors
import pytest import pytest
import requests import requests
from _pytest._code.code import ReprExceptionInfo
from packaging.version import Version
from docker.models.containers import Container from docker.models.containers import Container
from packaging.version import Version
from requests.packages.urllib3.util.connection import HAS_IPV6 from requests.packages.urllib3.util.connection import HAS_IPV6
logging.basicConfig(level=logging.INFO) 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 FORCE_CONTAINER_IPV6 = False # ugly global state to consider containers' IPv6 address instead of IPv4
DOCKER_COMPOSE = os.environ.get('DOCKER_COMPOSE', 'docker compose') 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() docker_client = docker.from_env()
@ -70,16 +73,27 @@ class requests_for_docker(object):
if os.path.isfile(CA_ROOT_CERTIFICATE): if os.path.isfile(CA_ROOT_CERTIFICATE):
self.session.verify = 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 @staticmethod
def get_nginx_proxy_containers() -> List[Container]: def get_nginx_proxy_containers() -> List[Container]:
""" """
Return list of containers 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: 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: 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 return nginx_proxy_containers
def get_conf(self): def get_conf(self):
@ -97,43 +111,61 @@ class requests_for_docker(object):
return container_ip(nginx_proxy_containers[0]) return container_ip(nginx_proxy_containers[0])
def get(self, *args, **kwargs): 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)): 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): def _get(*args, **kwargs):
return self.session.get(*args, **kwargs) return self.session.get(*args, **kwargs)
return _get(*args, **kwargs) return _get(*args, **kwargs)
def post(self, *args, **kwargs): def post(self, *args, **kwargs):
_expected_status_code = kwargs.pop('expected_status_code', None)
with ipv6(kwargs.pop('ipv6', False)): 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): def _post(*args, **kwargs):
return self.session.post(*args, **kwargs) return self.session.post(*args, **kwargs)
return _post(*args, **kwargs) return _post(*args, **kwargs)
def put(self, *args, **kwargs): def put(self, *args, **kwargs):
_expected_status_code = kwargs.pop('expected_status_code', None)
with ipv6(kwargs.pop('ipv6', False)): 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): def _put(*args, **kwargs):
return self.session.put(*args, **kwargs) return self.session.put(*args, **kwargs)
return _put(*args, **kwargs) return _put(*args, **kwargs)
def head(self, *args, **kwargs): def head(self, *args, **kwargs):
_expected_status_code = kwargs.pop('expected_status_code', None)
with ipv6(kwargs.pop('ipv6', False)): 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): def _head(*args, **kwargs):
return self.session.head(*args, **kwargs) return self.session.head(*args, **kwargs)
return _head(*args, **kwargs) return _head(*args, **kwargs)
def delete(self, *args, **kwargs): def delete(self, *args, **kwargs):
_expected_status_code = kwargs.pop('expected_status_code', None)
with ipv6(kwargs.pop('ipv6', False)): 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): def _delete(*args, **kwargs):
return self.session.delete(*args, **kwargs) return self.session.delete(*args, **kwargs)
return _delete(*args, **kwargs) return _delete(*args, **kwargs)
def options(self, *args, **kwargs): def options(self, *args, **kwargs):
_expected_status_code = kwargs.pop('expected_status_code', None)
with ipv6(kwargs.pop('ipv6', False)): 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): def _options(*args, **kwargs):
return self.session.options(*args, **kwargs) return self.session.options(*args, **kwargs)
return _options(*args, **kwargs) return _options(*args, **kwargs)
@ -188,7 +220,7 @@ def container_ipv6(container):
return net_info[network_name]["GlobalIPv6Address"] 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 if "nginx-proxy" if found in host, return the ip address of the docker container
issued from the docker image nginxproxy/nginx-proxy:test. issued from the docker image nginxproxy/nginx-proxy:test.
@ -196,21 +228,44 @@ def nginx_proxy_dns_resolver(domain_name):
:return: IP or None :return: IP or None
""" """
log = logging.getLogger('DNS') 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: if 'nginx-proxy' in domain_name:
nginxproxy_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginxproxy/nginx-proxy:test"}) nginxproxy_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginxproxy/nginx-proxy:test"})
if len(nginxproxy_containers) == 0: 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"}) exited_nginxproxy_containers = docker_client.containers.list(filters={"status": "exited", "ancestor": "nginxproxy/nginx-proxy:test"})
if len(exited_nginxproxy_containers) > 0: if len(exited_nginxproxy_containers) > 0:
exited_nginxproxy_container_logs = exited_nginxproxy_containers[0].logs() 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 return
nginxproxy_container = nginxproxy_containers[0] nginxproxy_container = nginxproxy_containers[0]
ip = container_ip(nginxproxy_container) 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}") log.info(f"resolving domain name {domain_name!r} as IP address {ip} of nginx-proxy container {nginxproxy_container.name}")
return ip 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): 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 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: try:
container = docker_client.containers.get(container_name) container = docker_client.containers.get(container_name)
except docker.errors.NotFound: 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 return
log.debug(f"container {container.name!r} found ({container.short_id})") 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 Alter the behavior of the urllib DNS resolver so that any domain name
containing substring 'nginx-proxy' will resolve to the IP address 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 prv_getaddrinfo = socket.getaddrinfo
dns_cache = {} dns_cache = {}
@ -258,7 +314,13 @@ def monkey_patch_urllib_dns_resolver():
pytest.skip("This system does not support IPv6") pytest.skip("This system does not support IPv6")
# custom DNS resolvers # 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: if ip is None:
ip = docker_container_dns_resolver(args[0]) ip = docker_container_dns_resolver(args[0])
if ip is not None: if ip is not None:
@ -278,14 +340,6 @@ def restore_urllib_dns_resolver(getaddrinfo_func):
socket.getaddrinfo = 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): def get_nginx_conf_from_container(container):
""" """
return the nginx /etc/nginx/conf.d/default.conf file content from a 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() return conffile.read()
def docker_compose_up(compose_file='docker-compose.yml'): def docker_compose_up(project_name, compose_file='docker-compose.yml'):
logging.info(f'{DOCKER_COMPOSE} -f {compose_file} up -d') composeCmd = f'{DOCKER_COMPOSE} --project-name {project_name} --file {compose_file} up --remove-orphans --force-recreate --detach'
logging.info(composeCmd)
try: 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: 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'): def docker_compose_down(project_name, compose_file='docker-compose.yml'):
logging.info(f'{DOCKER_COMPOSE} -f {compose_file} down -v') composeCmd = f'{DOCKER_COMPOSE} --project-name {project_name} --file {compose_file} down --remove-orphans --volumes'
logging.info(composeCmd)
try: 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: 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(): def wait_for_nginxproxy_to_be_ready():
""" """
If one (and only one) container started from image nginxproxy/nginx-proxy:test is found, If one (and only one) container started from image nginxproxy/nginx-proxy:test
wait for its log to contain substring "Watching docker events" 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"}) timeout = time.time() + 10
if len(containers) != 1: while True:
return containers = docker_client.containers.list(
container = containers[0] filters={"status": "running", "ancestor": f"nginxproxy/nginx-proxy:{IMAGE_TAG}"}
for line in container.logs(stream=True): )
if b"Watching docker events" in line: if len(containers) == 1:
logging.debug("nginx-proxy ready")
break 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 @pytest.fixture
@ -357,8 +428,8 @@ def docker_compose_file(request):
if not os.path.isfile(docker_compose_file): 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.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}") logging.info(f"using docker compose file {docker_compose_file}")
return docker_compose_file yield docker_compose_file
def connect_to_network(network): def connect_to_network(network):
@ -371,7 +442,7 @@ def connect_to_network(network):
try: try:
my_container = docker_client.containers.get(test_container) my_container = docker_client.containers.get(test_container)
except docker.errors.NotFound: except docker.errors.NotFound:
logging.warn(f"container {test_container} not found") logging.warning(f"container {test_container} not found")
return return
# figure out our container networks # figure out our container networks
@ -399,7 +470,7 @@ def disconnect_from_network(network=None):
try: try:
my_container = docker_client.containers.get(test_container) my_container = docker_client.containers.get(test_container)
except docker.errors.NotFound: except docker.errors.NotFound:
logging.warn(f"container {test_container} not found") logging.warning(f"container {test_container} not found")
return return
# figure out our container networks # figure out our container networks
@ -427,7 +498,9 @@ def connect_to_all_networks():
class DockerComposer(contextlib.AbstractContextManager): class DockerComposer(contextlib.AbstractContextManager):
def __init__(self): def __init__(self):
self._networks = None
self._docker_compose_file = None self._docker_compose_file = None
self._project_name = None
def __exit__(self, *exc_info): def __exit__(self, *exc_info):
self._down() self._down()
@ -437,21 +510,20 @@ class DockerComposer(contextlib.AbstractContextManager):
return return
for network in self._networks: for network in self._networks:
disconnect_from_network(network) 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 self._docker_compose_file = None
def compose(self, docker_compose_file): def compose(self, project_name, docker_compose_file):
if docker_compose_file == self._docker_compose_file: if docker_compose_file == self._docker_compose_file and project_name == self._project_name:
return return
self._down() self._down()
if docker_compose_file is None: if docker_compose_file is None:
return return
remove_all_containers() docker_compose_up(project_name, docker_compose_file)
docker_compose_up(docker_compose_file)
self._networks = connect_to_all_networks() self._networks = connect_to_all_networks()
wait_for_nginxproxy_to_be_ready() wait_for_nginxproxy_to_be_ready()
time.sleep(3) # give time to containers to be ready
self._docker_compose_file = docker_compose_file self._docker_compose_file = docker_compose_file
self._project_name = project_name
############################################################################### ###############################################################################
@ -469,7 +541,7 @@ def docker_composer():
@pytest.fixture @pytest.fixture
def ca_root_certificate(): def ca_root_certificate():
return CA_ROOT_CERTIFICATE yield CA_ROOT_CERTIFICATE
@pytest.fixture @pytest.fixture
@ -480,7 +552,7 @@ def monkey_patched_dns():
@pytest.fixture @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. """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` 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 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. 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 yield docker_client
@ -515,7 +588,7 @@ def acme_challenge_path():
""" """
Provides fake Let's Encrypt ACME challenge path used in certain tests 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 # pytest hook to display additionnal stuff in test report
def pytest_runtest_logreport(report): def pytest_runtest_logreport(report):
if report.failed: if report.failed:
if isinstance(report.longrepr, ReprExceptionInfo): nginx_containers = docker_client.containers.list(all=True, filters={"label": "com.github.nginx-proxy.nginx-proxy.nginx"})
test_containers = docker_client.containers.list(all=True, filters={"ancestor": "nginxproxy/nginx-proxy:test"}) 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: for container in test_containers:
report.longrepr.addsection('nginx-proxy logs', container.logs()) report.longrepr.addsection('nginx-proxy logs', container.logs().decode())
report.longrepr.addsection('nginx-proxy conf', get_nginx_conf_from_container(container)) report.longrepr.addsection('nginx-proxy conf', get_nginx_conf_from_container(container).decode())
# Py.test `incremental` marker, see http://stackoverflow.com/a/12579625/107049 # Py.test `incremental` marker, see http://stackoverflow.com/a/12579625/107049
@ -553,9 +629,9 @@ def pytest_runtest_setup(item):
############################################################################### ###############################################################################
try: try:
docker_client.images.get('nginxproxy/nginx-proxy:test') docker_client.images.get(f"nginxproxy/nginx-proxy:{IMAGE_TAG}")
except docker.errors.ImageNotFound: 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"): 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") 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 docker==7.1.0
pytest==8.3.4 pytest==8.3.4
requests==2.32.3 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 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): def test_http_web_a_is_forwarded(docker_compose, nginxproxy):
r = nginxproxy.get("http://webA.nginx-proxy/port", allow_redirects=False) r = nginxproxy.get("http://webA.nginx-proxy/port", allow_redirects=False)
assert r.status_code == 200 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): 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 assert "<title>Welcome to nginx!</title>" not in r.text
with pytest.raises(requests.exceptions.HTTPError): with pytest.raises(requests.exceptions.HTTPError):
r.raise_for_status() 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): def test_reverseproxy_survive_restart(docker_compose):
docker_compose.containers.get("reverseproxy").restart() docker_compose.containers.get("reverseproxy").restart()
sleep(2) # give time for the container to initialize 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): def test_redirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get( r = nginxproxy.get(
f"http://web1.nginx-proxy.tld/{acme_challenge_path}", f"http://web1.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False allow_redirects=False,
expected_status_code=301
) )
assert r.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): def test_noredirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get( r = nginxproxy.get(
f"http://web3.nginx-proxy.tld/{acme_challenge_path}", f"http://web3.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False allow_redirects=False,
expected_status_code=404
) )
assert r.status_code == 404 assert r.status_code == 404

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web1: web1:
image: web image: web
@ -36,10 +40,34 @@ services:
ACME_HTTP_CHALLENGE_LOCATION: "true" ACME_HTTP_CHALLENGE_LOCATION: "true"
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
environment: environment: &nginxProxyEnv
ACME_HTTP_CHALLENGE_LOCATION: "false" ACME_HTTP_CHALLENGE_LOCATION: "false"
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro - &certs ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html: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): def test_redirect_acme_challenge_location_enabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get( r = nginxproxy.get(
f"http://web1.nginx-proxy.tld/{acme_challenge_path}", 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): def test_redirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get( r = nginxproxy.get(
f"http://web2.nginx-proxy.tld/{acme_challenge_path}", f"http://web2.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False allow_redirects=False,
expected_status_code=301
) )
assert r.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): def test_noredirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get( r = nginxproxy.get(
f"http://web4.nginx-proxy.tld/{acme_challenge_path}", f"http://web4.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False allow_redirects=False,
expected_status_code=404
) )
assert r.status_code == 404 assert r.status_code == 404

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web1: web1:
image: web image: web
@ -36,8 +40,31 @@ services:
ACME_HTTP_CHALLENGE_LOCATION: "false" ACME_HTTP_CHALLENGE_LOCATION: "false"
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro - &certs ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html: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): def test_redirect_acme_challenge_location_legacy(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get( r = nginxproxy.get(
f"http://web1.nginx-proxy.tld/{acme_challenge_path}", 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): def test_noredirect_acme_challenge_location_legacy(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get( r = nginxproxy.get(
f"http://web2.nginx-proxy.tld/{acme_challenge_path}", f"http://web2.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False allow_redirects=False,
expected_status_code=404
) )
assert r.status_code == 404 assert r.status_code == 404

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web1: web1:
image: web image: web
@ -17,10 +21,34 @@ services:
HTTPS_METHOD: noredirect HTTPS_METHOD: noredirect
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
environment: environment: &nginxProxyEnv
ACME_HTTP_CHALLENGE_LOCATION: "legacy" ACME_HTTP_CHALLENGE_LOCATION: "legacy"
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs:/etc/nginx/certs:ro - &certs ./certs:/etc/nginx/certs:ro
- ./acme_root:/usr/share/nginx/html: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 import re
def test_custom_error_page(docker_compose, nginxproxy): 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 r.status_code == 503
assert re.search(r"Damn, there's some maintenance in progress.", r.text) assert re.search(r"Damn, there's some maintenance in progress.", r.text)

View file

@ -1,6 +1,32 @@
volumes:
nginx_conf:
services: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./50x.html:/usr/share/nginx/html/errors/50x.html: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): def test_custom_default_conf_applies_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port") r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200 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 "X-test" in r.headers
assert "f00" == r.headers["X-test"] assert "f00" == r.headers["X-test"]
def test_custom_default_conf_is_overriden_for_web3(docker_compose, nginxproxy): def test_custom_default_conf_is_overriden_for_web3(docker_compose, nginxproxy):
r = nginxproxy.get("http://web3.nginx-proxy.example/port") r = nginxproxy.get("http://web3.nginx-proxy.example/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 83\n" assert r.text == "answer from port 83\n"
assert "X-test" in r.headers assert "X-test" in r.headers
assert "bar" == r.headers["X-test"] 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: services:
nginx-proxy: nginx-proxy:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/default_location:ro - &defaultLocation ./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 - &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: web1:
image: web 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): def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port") r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200 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 r.text == "answer from port 82\n"
assert "X-test" in r.headers assert "X-test" in r.headers
assert "f00" == r.headers["X-test"] 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: services:
nginx-proxy: nginx-proxy:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/proxy.conf: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: web1:
image: web 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): def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port") r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200 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 r.text == "answer from port 82\n"
assert "X-test" not in r.headers 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): 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() 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: services:
nginx-proxy: nginx-proxy:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example_location:ro - &vhostLocationConf ./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 - &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: web1:
image: web 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): def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port") r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200 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.status_code == 200
assert r.text == "answer from port 82\n" assert r.text == "answer from port 82\n"
assert "X-test" not in r.headers 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: services:
nginx-proxy: nginx-proxy:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example:ro - &vhostConf ./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 - &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: web1:
image: web 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): def test_custom_conf_applies_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port") r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200 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 r.text == "answer from port 82\n"
assert "X-test" in r.headers assert "X-test" in r.headers
assert "f00" == r.headers["X-test"] 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: services:
nginx-proxy: nginx-proxy:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /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 - &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: web1:
image: web 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): 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 assert r.status_code == 404

View file

@ -1,11 +1,36 @@
volumes:
nginx_conf:
services: services:
nginx-proxy: nginx-proxy:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
DEBUG_ENDPOINT: "true" 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: debug_enabled:
image: web image: web
expose: expose:

View file

@ -2,9 +2,9 @@ import json
import pytest import pytest
def test_debug_endpoint_is_disabled_globally(docker_compose, nginxproxy): 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 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 assert r.status_code == 404

View file

@ -1,8 +1,32 @@
volumes:
nginx_conf:
services: services:
nginx-proxy: nginx-proxy:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: 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: debug_disabled1:
image: web image: web
@ -20,7 +44,6 @@ services:
WEB_PORTS: 82 WEB_PORTS: 82
VIRTUAL_HOST: disabled2.debug.nginx-proxy.example VIRTUAL_HOST: disabled2.debug.nginx-proxy.example
debug_enabled: debug_enabled:
image: web image: web
expose: expose:

View file

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

View file

@ -1,5 +1,8 @@
volumes:
nginx_conf:
services: services:
# GIVEN a webserver with VIRTUAL_HOST set to web1.tld
web1: web1:
image: web image: web
expose: expose:
@ -8,10 +11,30 @@ services:
WEB_PORTS: 81 WEB_PORTS: 81
VIRTUAL_HOST: web1.tld VIRTUAL_HOST: web1.tld
# WHEN nginx-proxy runs with DEFAULT_HOST set to web1.tld
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
DEFAULT_HOST: web1.tld 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,9 +1,3 @@
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): def test_forwards_to_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.tld/port") r = nginxproxy.get("http://web1.nginx-proxy.tld/port")
assert r.status_code == 200 assert r.status_code == 200
@ -13,3 +7,7 @@ def test_forwards_to_web2(docker_compose, nginxproxy):
r = nginxproxy.get("http://web2.nginx-proxy.tld/port") r = nginxproxy.get("http://web2.nginx-proxy.tld/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 82\n" assert r.text == "answer from port 82\n"
def test_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 import pytest
from packaging.version import Version
raw_version = docker.from_env().version()["Version"]
pytestmark = pytest.mark.skipif( pytestmark = pytest.mark.skipif(
Version(raw_version) < Version("1.13"), True,
reason="Docker compose syntax v3 requires docker engine v1.13 or later (got {raw_version})" 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: services:
nginx: nginx:
image: nginx image: nginx
container_name: nginx container_name: nginx
volumes: volumes:
- nginx_conf:/etc/nginx/conf.d:ro - nginx_conf_dockergen:/etc/nginx/conf.d:ro
dockergen: dockergen:
image: nginxproxy/docker-gen image: nginxproxy/docker-gen
@ -11,7 +15,7 @@ services:
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - /var/run/docker.sock:/tmp/docker.sock:ro
- ../../nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl - ../../nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl
- nginx_conf:/etc/nginx/conf.d - nginx_conf_dockergen:/etc/nginx/conf.d
web: web:
image: web image: web
@ -21,6 +25,3 @@ services:
environment: environment:
WEB_PORTS: 80 WEB_PORTS: 80
VIRTUAL_HOST: whoami.nginx.container.docker 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): def test_nohttp_missing_cert_enabled(docker_compose, nginxproxy):
r = nginxproxy.get("http://nohttp-missing-cert-enabled.nginx-proxy.tld/", allow_redirects=False) r = nginxproxy.get("http://nohttp-missing-cert-enabled.nginx-proxy.tld/", allow_redirects=False)
assert r.status_code == 200 assert r.status_code == 200
def test_redirect_missing_cert_disabled(docker_compose, nginxproxy): def test_nohttp_missing_cert_disabled(docker_compose, nginxproxy):
r = nginxproxy.get("http://redirect-missing-cert-disabled.nginx-proxy.tld/", allow_redirects=False) r = nginxproxy.get(
assert r.status_code == 301 "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): def test_redirect_missing_cert_enabled(docker_compose, nginxproxy):
r = nginxproxy.get("http://redirect-missing-cert-enabled.nginx-proxy.tld/", allow_redirects=False) r = nginxproxy.get("http://redirect-missing-cert-enabled.nginx-proxy.tld/", allow_redirects=False)
assert r.status_code == 200 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: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro - &certs ./withdefault.certs:/etc/nginx/certs:ro
environment: environment: &nginxProxyEnv
ENABLE_HTTP_ON_MISSING_CERT: "false" 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: nohttp-missing-cert-disabled:
image: web image: web
expose: expose:

View file

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

View file

@ -1,5 +1,33 @@
networks:
default:
name: nginx-proxy-test-events
volumes:
nginx_conf:
services: services:
nginxproxy: nginxproxy:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: 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: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./custom-fallback.conf:/etc/nginx/conf.d/zzz-custom-fallback.conf: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: http-only:
image: web image: web

View file

@ -1,9 +1,35 @@
volumes:
nginx_conf:
services: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./nodefault.certs:/etc/nginx/certs: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: https-and-http:
image: web image: web

View file

@ -1,12 +1,39 @@
volumes:
nginx_conf:
services: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro - &certs ./withdefault.certs:/etc/nginx/certs:ro
environment: environment: &nginxProxyEnv
HTTPS_METHOD: redirect 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: https-only:
image: web image: web
expose: expose:

View file

@ -1,12 +1,39 @@
volumes:
nginx_conf:
services: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro - &certs ./withdefault.certs:/etc/nginx/certs:ro
environment: environment: &nginxProxyEnv
HTTPS_METHOD: nohttp 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: https-only:
image: web image: web
expose: expose:

View file

@ -1,12 +1,39 @@
volumes:
nginx_conf:
services: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro - &certs ./withdefault.certs:/etc/nginx/certs:ro
environment: environment: &nginxProxyEnv
HTTPS_METHOD: nohttp 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: https-only:
image: web image: web
expose: expose:

View file

@ -1,11 +1,36 @@
volumes:
nginx_conf:
services: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
HTTPS_METHOD: redirect 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: http-only:
image: web image: web
expose: expose:

View file

@ -1,11 +1,36 @@
volumes:
nginx_conf:
services: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
HTTPS_METHOD: nohttps 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: http-only:
image: web image: web
expose: expose:

View file

@ -1,12 +1,39 @@
volumes:
nginx_conf:
services: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro - &certs ./withdefault.certs:/etc/nginx/certs:ro
environment: environment: &nginxProxyEnv
TRUST_DEFAULT_CERT: "false" 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: https-and-http:
image: web image: web
expose: expose:

View file

@ -1,9 +1,35 @@
volumes:
nginx_conf:
services: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs: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: https-and-http:
image: web image: web

View file

@ -26,8 +26,11 @@ def get(docker_compose, nginxproxy, want_err_re):
interval=.3, interval=.3,
max_tries=30, max_tries=30,
jitter=None) jitter=None)
def _get(url): def _get(url, expected_status_code=None):
return nginxproxy.get(url, allow_redirects=False) 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 return _get
@ -110,7 +113,7 @@ INTERNAL_ERR_RE = re.compile("TLSV1_UNRECOGNIZED_NAME")
]) ])
def test_fallback(get, url, want_code, want_err_re): def test_fallback(get, url, want_code, want_err_re):
if want_err_re is None: if want_err_re is None:
r = get(url) r = get(url, want_code)
assert r.status_code == want_code assert r.status_code == want_code
else: else:
with pytest.raises(requests.exceptions.SSLError, match=want_err_re): 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): def test_arbitrary_headers_are_passed_on(docker_compose, nginxproxy):
r = nginxproxy.get("http://web.nginx-proxy.tld/headers", headers={'Foo': 'Bar'}) r = nginxproxy.get("http://web.nginx-proxy.tld/headers", headers={'Foo': 'Bar'})
assert r.status_code == 200 assert r.status_code == 200
@ -91,9 +95,13 @@ def test_httpoxy_safe(docker_compose, nginxproxy):
assert "Proxy:" not in r.text 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): def test_no_host_server_tokens_off(docker_compose, nginxproxy):
ip = nginxproxy.get_ip() 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.status_code == 503
assert r.headers["Server"] == "nginx" assert r.headers["Server"] == "nginx"

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web: web:
image: web image: web
@ -17,6 +21,26 @@ services:
SERVER_TOKENS: "off" SERVER_TOKENS: "off"
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: 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 import pytest
@ -94,10 +95,14 @@ def test_httpoxy_safe(docker_compose, nginxproxy):
assert "Proxy:" not in r.text 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') @pytest.mark.filterwarnings('ignore::urllib3.exceptions.InsecureRequestWarning')
def test_no_host_server_tokens_off(docker_compose, nginxproxy): def test_no_host_server_tokens_off(docker_compose, nginxproxy):
ip = nginxproxy.get_ip() 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.status_code == 503
assert r.headers["Server"] == "nginx" assert r.headers["Server"] == "nginx"

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web: web:
image: web image: web
@ -17,12 +21,29 @@ services:
SERVER_TOKENS: "off" SERVER_TOKENS: "off"
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/default.crt:ro - &certs ./certs:/etc/nginx/certs: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 sut-dockergen:
- ./certs/web.nginx-proxy.tld.key:/etc/nginx/certs/web.nginx-proxy.tld.key:ro profiles:
- ./certs/web-server-tokens-off.nginx-proxy.tld.crt:/etc/nginx/certs/web-server-tokens-off.nginx-proxy.tld.crt:ro - separateContainers
- ./certs/web-server-tokens-off.nginx-proxy.tld.key:/etc/nginx/certs/web-server-tokens-off.nginx-proxy.tld.key:ro 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): def test_forwards_to_bridge_network_container(docker_compose, nginxproxy):
r = nginxproxy.get("http://bridge-network.nginx-proxy.tld/port") r = nginxproxy.get("http://bridge-network.nginx-proxy.tld/port")
assert r.status_code == 200 assert r.status_code == 200

View file

@ -3,6 +3,11 @@ networks:
internal: true internal: true
net2: net2:
volumes:
nginx_conf:
services: services:
bridge-network: bridge-network:
image: web image: web
@ -21,9 +26,35 @@ services:
network_mode: host network_mode: host
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
networks: networks:
- net1 - net1
- net2 - 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): def test_forwards_to_host_network_container_1(docker_compose, nginxproxy):
r = nginxproxy.get("http://host-network-1.nginx-proxy.tld:8888/port") r = nginxproxy.get("http://host-network-1.nginx-proxy.tld:8888/port")
assert r.status_code == 200 assert r.status_code == 200

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
host-network-1: host-network-1:
image: web image: web
@ -16,9 +20,30 @@ services:
network_mode: host network_mode: host
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
HTTP_PORT: 8888 HTTP_PORT: 8888
network_mode: host 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): 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 r.status_code == 401
assert "WWW-Authenticate" in r.headers assert "WWW-Authenticate" in r.headers
assert r.headers["WWW-Authenticate"] == 'Basic realm="Restricted access"' assert r.headers["WWW-Authenticate"] == 'Basic realm="Restricted access"'

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
regex: regex:
image: web image: web
@ -8,8 +12,30 @@ services:
VIRTUAL_HOST: ~^regex.*\.nginx-proxy\.example$ VIRTUAL_HOST: ~^regex.*\.nginx-proxy\.example$
sut: sut:
profiles:
- singleContainer
container_name: sut container_name: sut
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./htpasswd:/etc/nginx/htpasswd: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): 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 r.status_code == 401
assert "WWW-Authenticate" in r.headers assert "WWW-Authenticate" in r.headers
assert r.headers["WWW-Authenticate"] == 'Basic realm="Restricted htpasswd.nginx-proxy.tld"' assert r.headers["WWW-Authenticate"] == 'Basic realm="Restricted htpasswd.nginx-proxy.tld"'

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web: web:
image: web image: web
@ -8,8 +12,30 @@ services:
VIRTUAL_HOST: htpasswd.nginx-proxy.tld VIRTUAL_HOST: htpasswd.nginx-proxy.tld
sut: sut:
profiles:
- singleContainer
container_name: sut container_name: sut
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./htpasswd:/etc/nginx/htpasswd: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): 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 r.status_code == 401
assert "WWW-Authenticate" in r.headers assert "WWW-Authenticate" in r.headers
assert r.headers["WWW-Authenticate"] == 'Basic realm="Restricted htpasswd.nginx-proxy.tld/foo/"' assert r.headers["WWW-Authenticate"] == 'Basic realm="Restricted htpasswd.nginx-proxy.tld/foo/"'

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web: web:
image: web image: web
@ -10,8 +14,30 @@ services:
VIRTUAL_DEST: / VIRTUAL_DEST: /
sut: sut:
profiles:
- singleContainer
container_name: sut container_name: sut
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./htpasswd:/etc/nginx/htpasswd: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 import re
def test_http2_global_disabled_config(docker_compose, nginxproxy): def test_http2_global_disabled_config(docker_compose, nginxproxy):

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
http2-global-disabled: http2-global-disabled:
image: web image: web
@ -8,8 +12,29 @@ services:
VIRTUAL_HOST: http2-global-disabled.nginx-proxy.tld VIRTUAL_HOST: http2-global-disabled.nginx-proxy.tld
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
ENABLE_HTTP2: "false" 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 import re
#Python Requests is not able to do native http3 requests. #Python Requests is not able to do native http3 requests.

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
http3-global-disabled: http3-global-disabled:
image: web image: web
@ -8,8 +12,30 @@ services:
VIRTUAL_HOST: http3-global-disabled.nginx-proxy.tld VIRTUAL_HOST: http3-global-disabled.nginx-proxy.tld
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
#environment: #environment:
#ENABLE_HTTP3: "false" #Disabled by default #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 import re
#Python Requests is not able to do native http3 requests. #Python Requests is not able to do native http3 requests.

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
http3-global-enabled: http3-global-enabled:
image: web image: web
@ -8,8 +12,29 @@ services:
VIRTUAL_HOST: http3-global-enabled.nginx-proxy.tld VIRTUAL_HOST: http3-global-enabled.nginx-proxy.tld
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
ENABLE_HTTP3: "true" 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 import re
#Python Requests is not able to do native http3 requests. #Python Requests is not able to do native http3 requests.

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
http3-vhost-enabled: http3-vhost-enabled:
image: web image: web
@ -28,6 +32,26 @@ services:
VIRTUAL_HOST: http3-vhost-default-disabled.nginx-proxy.tld VIRTUAL_HOST: http3-vhost-default-disabled.nginx-proxy.tld
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: 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: services:
web1: web1:
image: web image: web
@ -8,8 +12,29 @@ services:
VIRTUAL_HOST: "*.nginx-proxy.tld" VIRTUAL_HOST: "*.nginx-proxy.tld"
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
HTTP_PORT: 8080 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): def test_network_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.example/port") r = nginxproxy.get("http://web1.nginx-proxy.example/port")
assert r.status_code == 200 assert r.status_code == 200

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web1: web1:
image: web image: web
@ -17,7 +21,29 @@ services:
VIRTUAL_HOST: web2.nginx-proxy.example VIRTUAL_HOST: web2.nginx-proxy.example
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./network_internal.conf:/etc/nginx/network_internal.conf: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): def test_network_web1(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy.example/web1/port") r = nginxproxy.get("http://nginx-proxy.example/web1/port")
assert r.status_code == 200 assert r.status_code == 200

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web1: web1:
image: web image: web
@ -21,7 +25,29 @@ services:
VIRTUAL_DEST: / VIRTUAL_DEST: /
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./network_internal.conf:/etc/nginx/network_internal.conf: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,11 +1,3 @@
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): def test_forwards_to_web1_ipv4(docker_compose, nginxproxy):
r = nginxproxy.get("http://web1.nginx-proxy.tld/port") r = nginxproxy.get("http://web1.nginx-proxy.tld/port")
assert r.status_code == 200 assert r.status_code == 200
@ -18,8 +10,8 @@ def test_forwards_to_web2_ipv4(docker_compose, nginxproxy):
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): def test_unknown_virtual_host_ipv4(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/port", ipv6=True) r = nginxproxy.get("http://nginx-proxy/port", expected_status_code=503)
assert r.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) r = nginxproxy.get("http://web2.nginx-proxy.tld/port", ipv6=True)
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 82\n" assert r.text == "answer from port 82\n"
def test_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: config:
- subnet: fd00:1::/80 - subnet: fd00:1::/80
volumes:
nginx_conf:
services: services:
web1: web1:
image: web image: web
@ -27,10 +31,35 @@ services:
- net1 - net1
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
ENABLE_IPV6: "true" ENABLE_IPV6: "true"
networks: networks:
- net1 - 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): def test_forwards_to_ipv4_only_network(docker_compose, nginxproxy):
r = nginxproxy.get("http://ipv4only.nginx-proxy.tld/port") r = nginxproxy.get("http://ipv4only.nginx-proxy.tld/port")
assert r.status_code == 200 assert r.status_code == 200

View file

@ -10,6 +10,10 @@ networks:
- subnet: 172.16.20.0/24 - subnet: 172.16.20.0/24
- subnet: fd00:cafe:face:feed::/64 - subnet: fd00:cafe:face:feed::/64
volumes:
nginx_conf:
services: services:
ipv4only: ipv4only:
image: web image: web
@ -32,12 +36,39 @@ services:
ipv6_address: fd00:cafe:face:feed::2 ipv6_address: fd00:cafe:face:feed::2
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
networks: networks: &nginxProxyNetworks
ipv4net: ipv4net:
ipv4_address: 172.16.10.3 ipv4_address: 172.16.10.3
dualstacknet: dualstacknet:
ipv4_address: 172.16.20.3 ipv4_address: 172.16.20.3
ipv6_address: fd00:cafe:face:feed::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): def test_forwards_to_ipv4_only_network(docker_compose, nginxproxy):
r = nginxproxy.get("http://ipv4only.nginx-proxy.tld/port") r = nginxproxy.get("http://ipv4only.nginx-proxy.tld/port")
assert r.status_code == 200 assert r.status_code == 200

View file

@ -10,6 +10,10 @@ networks:
- subnet: 172.16.20.0/24 - subnet: 172.16.20.0/24
- subnet: fd00:cafe:face:feed::/64 - subnet: fd00:cafe:face:feed::/64
volumes:
nginx_conf:
services: services:
ipv4only: ipv4only:
image: web image: web
@ -32,14 +36,42 @@ services:
ipv6_address: fd00:cafe:face:feed::2 ipv6_address: fd00:cafe:face:feed::2
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
PREFER_IPV6_NETWORK: "true" PREFER_IPV6_NETWORK: "true"
networks: networks: &nginxProxyNetworks
ipv4net: ipv4net:
ipv4_address: 172.16.10.3 ipv4_address: 172.16.10.3
dualstacknet: dualstacknet:
ipv4_address: 172.16.20.3 ipv4_address: 172.16.20.3
ipv6_address: fd00:cafe:face:feed::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: services:
keepalive-disabled: keepalive-disabled:
image: web image: web
@ -31,8 +35,29 @@ services:
VIRTUAL_HOST: keepalive-auto.nginx-proxy.test VIRTUAL_HOST: keepalive-auto.nginx-proxy.test
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
HTTPS_METHOD: nohttps 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 import re
def test_loadbalance_hash(docker_compose, nginxproxy): def test_loadbalance_hash(docker_compose, nginxproxy):

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
loadbalance-hash: loadbalance-hash:
image: web image: web
@ -22,6 +26,26 @@ services:
replicas: 2 replicas: 2
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: 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): 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") r = nginxproxy.get("http://explicit-root-nohash.nginx-proxy.test/foo/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 82\n" assert r.text == "answer from port 82\n"
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): 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") r = nginxproxy.get("http://explicit-root-hash.nginx-proxy.test/foo/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 82\n" assert r.text == "answer from port 82\n"
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): 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") r = nginxproxy.get("http://explicit-root-hash-and-nohash.nginx-proxy.test/foo/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 82\n" assert r.text == "answer from port 82\n"
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): def test_explicit_nonroot(docker_compose, nginxproxy):
r = nginxproxy.get("http://explicit-nonroot.nginx-proxy.test/port") r = nginxproxy.get("http://explicit-nonroot.nginx-proxy.test/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 81\n" assert r.text == "answer from port 81\n"
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 assert r.status_code == 418
def test_implicit_root_nohash(docker_compose, nginxproxy): 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 assert r.status_code == 418
def test_implicit_root_hash(docker_compose, nginxproxy): 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 assert r.status_code == 418
def test_implicit_root_hash_and_nohash(docker_compose, nginxproxy): 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 assert r.status_code == 418

View file

@ -1,9 +1,35 @@
volumes:
nginx_conf:
services: services:
sut: sut:
profiles:
- singleContainer
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
- ./test_location-override.vhost.d:/etc/nginx/vhost.d: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: explicit-root:
image: web image: web

View file

@ -1,10 +1,13 @@
import time
import pytest import pytest
def test_log_disabled(docker_compose, nginxproxy): def test_log_disabled(docker_compose, nginxproxy):
time.sleep(3)
r = nginxproxy.get("http://nginx-proxy.test/port") r = nginxproxy.get("http://nginx-proxy.test/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 81\n" assert r.text == "answer from port 81\n"
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 = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
docker_logs = docker_logs.decode("utf-8").splitlines() docker_logs = docker_logs.decode("utf-8").splitlines()
docker_logs = [line for line in docker_logs if "GET /port" in line] docker_logs = [line for line in docker_logs if "GET /port" in line]

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web1: web1:
image: web image: web
@ -8,9 +12,30 @@ services:
VIRTUAL_HOST: nginx-proxy.test VIRTUAL_HOST: nginx-proxy.test
sut: sut:
container_name: sut profiles:
- singleContainer
container_name: nginx-proxy
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
DISABLE_ACCESS_LOGS: true 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 import pytest
def test_log_format(docker_compose, nginxproxy): def test_log_format(docker_compose, nginxproxy):
time.sleep(3)
r = nginxproxy.get("http://nginx-proxy.test/port") r = nginxproxy.get("http://nginx-proxy.test/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 81\n" assert r.text == "answer from port 81\n"
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 = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
docker_logs = docker_logs.decode("utf-8").splitlines() docker_logs = docker_logs.decode("utf-8").splitlines()
docker_logs = [line for line in docker_logs if "GET /port" in line] docker_logs = [line for line in docker_logs if "GET /port" in line]

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web1: web1:
image: web image: web
@ -8,9 +12,30 @@ services:
VIRTUAL_HOST: nginx-proxy.test VIRTUAL_HOST: nginx-proxy.test
sut: sut:
container_name: sut profiles:
- singleContainer
container_name: nginx-proxy
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: 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' 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") r = nginxproxy.get("http://nginx-proxy.test/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 81\n" assert r.text == "answer from port 81\n"
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 = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
docker_logs = docker_logs.decode("utf-8").splitlines() docker_logs = docker_logs.decode("utf-8").splitlines()
docker_logs = [line for line in docker_logs if "{\"time_local\":" in line] docker_logs = [line for line in docker_logs if "{\"time_local\":" in line]

View file

@ -1,3 +1,7 @@
volumes:
nginx_conf:
services: services:
web1: web1:
image: web image: web
@ -8,9 +12,30 @@ services:
VIRTUAL_HOST: nginx-proxy.test VIRTUAL_HOST: nginx-proxy.test
sut: sut:
container_name: sut profiles:
- singleContainer
container_name: nginx-proxy
image: nginxproxy/nginx-proxy:test image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - &dockerSocket /var/run/docker.sock:/tmp/docker.sock:ro
environment: environment: &nginxProxyEnv
LOG_JSON: 1 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") r = nginxproxy.get("http://nginx-proxy.test/port")
assert r.status_code == 200 assert r.status_code == 200
assert r.text == "answer from port 81\n" assert r.text == "answer from port 81\n"
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 = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False)
docker_logs = docker_logs.decode("utf-8").splitlines() docker_logs = docker_logs.decode("utf-8").splitlines()
docker_logs = [line for line in docker_logs if "{\"time_local\":" in line] 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