Compare commits

..

311 commits

Author SHA1 Message Date
4856fbe7eb Aggiorna README.md
Some checks failed
Update Docker Hub Description / Update Docker Hub Description (push) Has been cancelled
2025-02-05 21:22:14 +08:00
23d56b2185 Aggiorna README.md
Some checks are pending
Update Docker Hub Description / Update Docker Hub Description (push) Waiting to run
2025-02-05 21:20:42 +08:00
Nicolas Duchon
1da623019f
Merge pull request #2576 from nginx-proxy/dependabot/docker/nginxproxy/docker-gen-0.14.5-debian
build: bump nginxproxy/docker-gen from 0.14.4 to 0.14.5
2025-01-19 23:03:10 +01:00
dependabot[bot]
e234ffba20
build: bump nginxproxy/docker-gen from 0.14.4-debian to 0.14.5-debian
Bumps nginxproxy/docker-gen from 0.14.4-debian to 0.14.5-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-01-19 20:34:13 +00:00
Nicolas Duchon
18030a7896
Merge pull request #1737 from junderw/fix-redirect
feat: redirect non-GET methods using 308 instead of 301
2025-01-18 22:03:27 +01:00
Nicolas Duchon
dfbff1eb9c
Merge pull request #2561 from nginx-proxy/fix/proto-with-multiports
fix: add proto to VIRTUAL_HOST_MULTIPORTS
2025-01-18 22:01:09 +01:00
Nicolas Duchon
34a33a2255 tests: virtual proto 2025-01-18 21:50:41 +01:00
Nicolas Duchon
a61e485410 tests: refactor due to rebase 2025-01-18 20:41:17 +01:00
Nicolas Duchon
9312d5239a docs: typo 2025-01-18 20:25:01 +01:00
Nicolas Duchon
9fc7cec15c feat: customizable non get redirect code 2025-01-18 20:25:01 +01:00
Nicolas Duchon
8447a36046 tests: parameterize test 2025-01-18 20:25:01 +01:00
Nicolas Duchon
923f05032f tests: fix tests & test compose file 2025-01-18 20:25:01 +01:00
junderw
820d4a29ac tests: redirects 2025-01-18 20:25:01 +01:00
junderw
1859811311 feat: redirect using 308 for non-GET requests 2025-01-18 20:25:01 +01:00
Nicolas Duchon
691724c81f
Merge pull request #2570 from nginx-proxy/test/refactor-darwin
tests: factor out base nginx-proxy config and enable local testing on macOS / Darwin
2025-01-05 11:37:45 +01:00
Nicolas Duchon
aa8145b62d tests: review changes
Co-authored-by: Niek <100143256+SchoNie@users.noreply.github.com>
2025-01-05 00:05:30 +01:00
Nicolas Duchon
836012cad6 docs: update test README 2025-01-03 16:00:36 +01:00
Nicolas Duchon
005377c6e5 tests: remove remaining unneeded container config 2024-12-30 20:45:08 +01:00
Nicolas Duchon
bfdd72fe95 tests: type hints and linting 2024-12-30 14:17:03 +01:00
Nicolas Duchon
40309e2441 tests: enable local testing on macOS / Darwin 2024-12-30 13:41:47 +01:00
Nicolas Duchon
daa9449176 tests: factor out base nginx-proxy config 2024-12-30 12:07:30 +01:00
Nicolas Duchon
4ccbc3edec
Merge pull request #2569 from nginx-proxy/test/cleanup
tests: fix, cleanup and restructure test code
2024-12-27 21:47:56 +01:00
Nicolas Duchon
1f732a54c6 tests: missing doubles quotes on WEB_PORTS 2024-12-27 21:36:39 +01:00
Nicolas Duchon
ae0c9a8e96 tests: fixture type hints and style standardization 2024-12-27 21:36:07 +01:00
Nicolas Duchon
ea99c1a6f9 tests: review comments 2024-12-27 16:16:55 +01:00
Nicolas Duchon
1e9745f604 tests: complete typing, minor fixes 2024-12-26 16:21:30 +01:00
Nicolas Duchon
7b6baa43cd tests: remove custom system_has_ipv6() method 2024-12-26 01:13:29 +01:00
Nicolas Duchon
a2c316a876
docs: add powered by section with relevant JetBains IDEs
JetBrains is providing a license for GoLang and PyCharm to the
maintainer of this project as part of their open source program.
2024-12-25 15:39:00 +01:00
Nicolas Duchon
fb0fc331c0 tests: minor typos and code style 2024-12-24 16:26:23 +01:00
Nicolas Duchon
eb09876f97 tests: standardize file structure & naming 2024-12-24 16:22:20 +01:00
Nicolas Duchon
35e2d21527 tests: do not remove containers on host 2024-12-24 14:05:42 +01:00
Nicolas Duchon
b5dea1cf50 tests: cleanup test code
- remove unused imports in test cases
- fix code smells and code style in conftest.py
2024-12-24 13:53:09 +01:00
Nicolas Duchon
c60eff5d16
Merge pull request #2566 from SchoNie/python3.12+
ci: python 3.12+ compatibility
2024-12-18 17:29:28 +01:00
Niek
142a159d56 ci: bump python module docker version check
ci: bump python module docker version check
2024-12-18 11:35:01 +01:00
Niek
92eb45f0ec ci: python 3.12+ compatibility
ci: python 3.12+ compatibility
2024-12-18 11:34:19 +01:00
Nicolas Duchon
2bb0bbe5c9
Merge pull request #2565 from nginx-proxy/chore/compose-version-obsolete
chore: docker compose version is obsolete
2024-12-18 02:39:23 +01:00
Nicolas Duchon
fbad3ac3fc chore: docker compose version is obsolete 2024-12-18 02:08:46 +01:00
Nicolas Duchon
0c4be4e90f
docs: better custom config examples
plus a few minor fixes and some linting
2024-12-09 00:17:48 +01:00
Nicolas Duchon
b9657874b9
Merge pull request #2563 from nginx-proxy/tests/cert-select
tests: supplemental test for certificate selection
2024-12-08 21:55:27 +01:00
Nicolas Duchon
56a4bb8601 tests: supplemental test for certificate selection 2024-12-08 21:30:47 +01:00
Nicolas Duchon
c67739f1cc
ci: remove dockerhub login for tests
This break tests on forked repositories.
2024-12-08 18:23:57 +01:00
Nicolas Duchon
a25b7ea1ef docs: add proto to VIRTUAL_HOST_MULTIPORTS 2024-12-08 14:06:38 +01:00
Nicolas Duchon
22e6e59034
Merge pull request #2558 from nginx-proxy/fix/wildcard-cert-select
fix: wildcard certificates should only work one level deep
2024-12-08 13:25:57 +01:00
Nicolas Duchon
0c141e64ba
ci: only push on demand images to nginxproxy/nginx-proxy 2024-12-08 13:15:38 +01:00
Nicolas Duchon
3c5bbcf029 docs: clarify certificate selection 2024-12-08 13:11:50 +01:00
Nicolas Duchon
9bd84fc95e fix: add proto to VIRTUAL_HOST_MULTIPORTS 2024-12-08 11:59:48 +01:00
Nicolas Duchon
b6c8851794
Merge pull request #2499 from nginx-proxy/ipv6
feat: basic implementation of IPv6 for IPv6 docker networks
2024-12-08 11:58:12 +01:00
Nicolas Duchon
30299e69bc tests: certificate selection 2024-12-07 20:15:44 +01:00
Nicolas Duchon
271e31dec4 fix: wildcard certificates should only work one level deep 2024-12-07 19:33:53 +01:00
Nicolas Duchon
559ddc7d13
Merge pull request #2535 from nginx-proxy/restore-default-certificate
feat: trust default certificate
2024-12-07 18:04:16 +01:00
Nicolas Duchon
e96a3ddec2 ci: build/publish on demand workflow 2024-12-03 08:31:08 +01:00
Nicolas Duchon
f0034c661a
Merge pull request #2554 from nginx-proxy/dependabot/pip/test/requirements/pytest-8.3.4
ci: bump pytest from 8.3.3 to 8.3.4 in /test/requirements
2024-12-02 09:22:36 +01:00
Nicolas Duchon
7c003a4aa4 docs: markdown linting 2024-12-02 09:21:03 +01:00
dependabot[bot]
ac4ce5b775
ci: bump pytest from 8.3.3 to 8.3.4 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.3 to 8.3.4.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.3...8.3.4)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-12-02 04:39:24 +00:00
Nicolas Duchon
baa2ce5e8b docs: IPv6 support for docker networks 2024-12-01 22:41:09 +01:00
Nicolas Duchon
993bcc07c0 test: globally untrusted default cert 2024-12-01 20:24:53 +01:00
Nicolas Duchon
07b469d8ac docs: default certificate optional trust 2024-12-01 19:58:30 +01:00
Nicolas Duchon
ce2e076d65 chore: add wip folder to .gitignore 2024-12-01 19:35:06 +01:00
Nicolas Duchon
d4b1925624
Merge pull request #2548 from nginx-proxy/dependabot/docker/library/nginx-1.27.3
build: bump library/nginx from 1.27.2 to 1.27.3
2024-11-30 15:11:07 +01:00
Nicolas Duchon
d433b3bee6
Merge pull request #2550 from nginx-proxy/refactor-template
refactor: nginx template
2024-11-30 14:48:17 +01:00
Nicolas Duchon
7fee758a70
Merge pull request #2551 from SchoNie/docker-upstream-changes
chore: changes from upstream docker install
2024-11-30 14:36:42 +01:00
Niek
d30b573b2c chore: changes from upstream docker install 2024-11-28 14:11:50 +01:00
Nicolas Duchon
f600ce3e11
Merge pull request #2549 from SchoNie/readme-tweaks
docs: alerts markdown
2024-11-27 20:30:36 +01:00
Niek
b4c2b0dd5e Extra newline for readability 2024-11-27 20:17:00 +01:00
Niek
12b482a7ea Change regular expression tip to note 2024-11-27 20:15:08 +01:00
Niek
c6664335b7 Alerts Markdown
Use [Alerts Markdown extension](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) available since [December 2023](https://github.blog/changelog/2023-12-14-new-markdown-extension-alerts-provide-distinctive-styling-for-significant-content/) to better indicate the significance of the content for some documentation.
2024-11-27 09:19:25 +01:00
Nicolas Duchon
f54f89a5f3
Merge pull request #2547 from SchoNie/loadbalance-readme
docs: remove experimental label for http loadbalance
2024-11-27 08:37:53 +01:00
dependabot[bot]
760c891a0c build: bump library/nginx from 1.27.2 to 1.27.3
Bumps library/nginx from 1.27.2 to 1.27.3.

---
updated-dependencies:
- dependency-name: library/nginx
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-27 04:11:14 +00:00
Niek
627b6ad75f Remove experimental label
Remove experimental label.
2024-11-26 10:34:28 +01:00
Nicolas Duchon
b0efe80f05 fix: debug endpoint formatting 2024-11-26 01:06:51 +01:00
Nicolas Duchon
90e9308f87 refactor: better virtual hosts merging 2024-11-26 01:06:01 +01:00
Nicolas Duchon
f325dadd6a refactor: enhance readability 2024-11-26 01:05:08 +01:00
Nicolas Duchon
4d03645200 refactor: deduplicate upstream_name definition 2024-11-26 01:01:55 +01:00
Nicolas Duchon
57016e43f3
Merge pull request #2546 from nginx-proxy/keepalive-auto-by-default
feat: enable keepalive by default
2024-11-25 18:01:21 +01:00
Nicolas Duchon
c944877b70
Merge pull request #2545 from nginx-proxy/dependabot/docker/nginxproxy/docker-gen-0.14.4-debian
build: bump nginxproxy/docker-gen from 0.14.3-debian to 0.14.4
2024-11-25 18:00:19 +01:00
Nicolas Duchon
52ffab1ce6 feat: enable keepalive by default 2024-11-25 09:16:57 +01:00
dependabot[bot]
7bd26d624d
build: bump nginxproxy/docker-gen from 0.14.3-debian to 0.14.4-debian
Bumps nginxproxy/docker-gen from 0.14.3-debian to 0.14.4-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-25 04:11:50 +00:00
Nicolas Duchon
d7acd931a3
Merge pull request #2538 from SchoNie/test-access-log-disabled
test: add test for DISABLE_ACCESS_LOGS
2024-11-05 20:19:07 +01:00
Niek
d4d6567bd3 Test for DISABLE_ACCESS_LOGS 2024-11-05 14:05:53 +01:00
Nicolas Duchon
9ca7d26821
Merge pull request #2537 from nginx-proxy/debug-endpoint-regexp
fix: do not render regexp hostname in debug endpoint response
2024-11-04 23:21:44 +01:00
Nicolas Duchon
fdb7310cda fix: do not render regexp hostname in debug endpoint response 2024-11-04 23:03:01 +01:00
Nicolas Duchon
40c153e8b0 test: default cert optional trust 2024-11-04 10:19:09 +01:00
Nicolas Duchon
a79445feef
Merge pull request #2534 from nginx-proxy/refactor-globals
refactor: move $globals.ENV to $globals.config
2024-11-04 09:17:56 +01:00
Nicolas Duchon
80474e37e8
Merge pull request #2536 from nginx-proxy/dependabot/docker/nginxproxy/docker-gen-0.14.3-debian
build: bump nginxproxy/docker-gen from 0.14.2-debian to 0.14.3-debian
2024-11-04 08:15:19 +01:00
dependabot[bot]
523112d205
build: bump nginxproxy/docker-gen from 0.14.2-debian to 0.14.3-debian
Bumps nginxproxy/docker-gen from 0.14.2-debian to 0.14.3-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-11-04 04:17:03 +00:00
Nicolas Duchon
469765bbb7 feat: default certificate optional trust 2024-11-03 23:56:39 +01:00
Nicolas Duchon
023a3d17da fix: force enable HTTP when both vhost and default cert are missing 2024-11-03 21:06:23 +01:00
Nicolas Duchon
57e503c830 feat: trust default certificate 2024-11-03 20:10:32 +01:00
Nicolas Duchon
fbf3e2f458 docs: complete debug endpoint docs 2024-11-03 11:44:50 +01:00
Nicolas Duchon
7d909782f9 refactor: move debug's hostname into vhost 2024-11-03 11:28:39 +01:00
Nicolas Duchon
72bb8a66d8 refactor: further align template syntax 2024-11-02 23:45:31 +01:00
Nicolas Duchon
01d14f0942 refactor: align global config template syntax 2024-11-02 23:11:39 +01:00
Nicolas Duchon
cab2a2d151 refactor: move log configs to $globals.config 2024-11-02 22:05:58 +01:00
Nicolas Duchon
a06cd1ae9a refactor: move resolvers to $globals.config 2024-11-02 21:58:37 +01:00
Nicolas Duchon
946485e0b8 refactor: move default host to $globals.config 2024-11-02 21:52:27 +01:00
Nicolas Duchon
db0421eb4a refactor: move https method to $globals.config 2024-11-02 21:46:56 +01:00
Nicolas Duchon
30b909de8e refactor: move https enforcing to $globals.config 2024-11-02 21:32:41 +01:00
Nicolas Duchon
dcbb695a4b refactor: move global http2/http3 to $globals.config 2024-11-02 21:19:14 +01:00
Nicolas Duchon
07aef2bd83 refactor: move global acme challenge location to $globals.config 2024-11-02 21:13:56 +01:00
Nicolas Duchon
52100c40af refactor: move global hsts to $globals.config 2024-11-02 21:02:16 +01:00
Nicolas Duchon
031a2b16bb
Merge pull request #2525 from nginx-proxy/debug-endpoint
feat: nginx-proxy debug endpoint
2024-11-02 17:32:47 +01:00
Nicolas Duchon
9114b8047d test: paths are stripped from debug endpoint response if too long 2024-11-02 17:20:25 +01:00
Nicolas Duchon
190030745c test: nginx-proxy debug endpoint 2024-11-02 16:48:55 +01:00
Nicolas Duchon
32ad9b7102 feat: protection against too long debug response 2024-11-02 16:04:21 +01:00
Nicolas Duchon
7dafac8b87 docs: documentation for debug endpoint 2024-11-02 16:04:21 +01:00
Nicolas Duchon
dce7663b69 refactor: remove duplicate code 2024-11-02 16:04:21 +01:00
Nicolas Duchon
fe52878940 refactor: expose clearly access log status in debug endpoint 2024-11-02 16:04:21 +01:00
Nicolas Duchon
ebed622fd7 feat: nginx-proxy debug endpoint 2024-11-02 16:04:21 +01:00
Nicolas Duchon
8fed348ff7 refactor: move global config properties to a sub dict 2024-11-02 16:04:21 +01:00
Nicolas Duchon
a3db62bb14
Merge pull request #2533 from nginx-proxy/2529
fix: use sha1 hash for config files name when using regex host
2024-11-02 14:11:22 +01:00
Nicolas Duchon
4c67b24552 test: rename file for clarity 2024-11-01 21:54:59 +01:00
Nicolas Duchon
1cd7b97e8f test: regex vhost file names 2024-11-01 21:37:29 +01:00
Nicolas Duchon
5baf4a163f docs: update docs regex file name change 2024-11-01 21:36:00 +01:00
Nicolas Duchon
73ba28091a fix: use sha1 hash for config files when using regex host 2024-11-01 20:32:00 +01:00
Nicolas Duchon
5ec120a296
docs: TLSv1/TLSv1.1 work on the alpine image too 2024-10-16 12:25:21 +02:00
Nicolas Duchon
8417046748
Merge pull request #2510 from liuxiaoy/patch-1
fix: correctly enable TLSv1 and TLSv1.1
2024-10-12 19:33:33 +02:00
Nicolas Duchon
ac0a4ca826 docs: warn about TLSv1 / TLSv1.1 being available only on debian 2024-10-06 16:01:58 +02:00
Nicolas Duchon
3ba0678ce5 fix: re-enable TLSv1 and TLSv1.1 on relevant policies 2024-10-06 15:45:10 +02:00
Nicolas Duchon
4251249761
Merge pull request #2519 from nginx-proxy/dependabot/docker/library/nginx-1.27.2
build: bump library/nginx from 1.27.1 to 1.27.2
2024-10-03 11:38:20 +02:00
dependabot[bot]
e95a66eedf build: bump library/nginx from 1.27.1 to 1.27.2
Bumps library/nginx from 1.27.1 to 1.27.2.

---
updated-dependencies:
- dependency-name: library/nginx
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-03 10:53:25 +02:00
Nicolas Duchon
69488808b9
Merge pull request #2520 from nginx-proxy/reject-handshake
fix: reject SSL handshake rather than using empty certificate
2024-10-03 10:23:18 +02:00
Nicolas Duchon
712a7ef176 fix: reject SSL handshake rather than using empty certificate 2024-10-03 09:57:20 +02:00
Nicolas Duchon
76873746f3
Merge pull request #2512 from nginx-proxy/dependabot/pip/test/requirements/pytest-8.3.3
ci: bump pytest from 8.3.2 to 8.3.3 in /test/requirements
2024-09-20 00:58:36 +02:00
dependabot[bot]
90f6e1b3dc
ci: bump pytest from 8.3.2 to 8.3.3 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.2 to 8.3.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.2...8.3.3)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-09-16 04:44:26 +00:00
liuxy
246da3ff85
Fix nginx.tmpl when enabled TLSv1 TLSv1.1 2024-09-13 14:23:16 +08:00
Niek
1baf048a6e
build: bump nginx 1.27.0 to 1.27.1 (#2506)
* build: bump nginx 1.27.0 to 1.27.1

* Update README.md

Link to nginx changelog

Co-authored-by: Nicolas Duchon <nicolas.duchon@gmail.com>

---------

Co-authored-by: Nicolas Duchon <nicolas.duchon@gmail.com>
2024-08-27 21:50:30 +02:00
Nicolas Duchon
f100b4426f
Merge pull request #2505 from nginx-proxy/dependabot/docker/nginxproxy/docker-gen-0.14.2-debian
build: bump nginxproxy/docker-gen from 0.14.1 to 0.14.2
2024-08-27 07:40:36 +02:00
dependabot[bot]
1c00b898a3
build: bump nginxproxy/docker-gen from 0.14.1-debian to 0.14.2-debian
Bumps nginxproxy/docker-gen from 0.14.1-debian to 0.14.2-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-27 05:28:30 +00:00
Nicolas Duchon
d4d3f12a41
Merge pull request #2504 from nginx-proxy/dependabot/docker/nginxproxy/forego-0.18.2-debian
build: bump nginxproxy/forego from 0.18.1 to 0.18.2
2024-08-27 07:27:00 +02:00
dependabot[bot]
54a1b0aa25
build: bump nginxproxy/forego from 0.18.1-debian to 0.18.2-debian
Bumps nginxproxy/forego from 0.18.1-debian to 0.18.2-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/forego
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-27 05:13:17 +00:00
Nicolas Duchon
83110b24ef
Merge pull request #2498 from nginx-proxy/dependabot/docker/nginxproxy/docker-gen-0.14.1-debian
build: bump nginxproxy/docker-gen from 0.14.0 to 0.14.1
2024-07-31 20:39:59 +02:00
dependabot[bot]
dee91b4d93
build: bump nginxproxy/docker-gen from 0.14.0-debian to 0.14.1-debian
Bumps nginxproxy/docker-gen from 0.14.0-debian to 0.14.1-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-31 18:25:26 +00:00
mikfar
c5f054ed36
fix: limit exposed ports in template comment to 10 (#2494)
Co-authored-by: Nicolas Duchon <nicolas.duchon@gmail.com>
2024-07-29 21:00:42 +02:00
Nicolas Duchon
290d275a68
Merge pull request #2497 from nginx-proxy/2496
fix: use fastcgi.conf on alpine and fastcgi_params on debien
2024-07-29 18:50:33 +02:00
Nicolas Duchon
5f4e77b6e7 fix: use fastcgi.conf on alpine and fastcgi_params on debien 2024-07-29 18:15:04 +02:00
Nicolas Duchon
434a089251
Merge pull request #2495 from nginx-proxy/dependabot/pip/test/requirements/pytest-8.3.2
ci: bump pytest from 8.3.1 to 8.3.2 in /test/requirements
2024-07-29 12:28:17 +02:00
dependabot[bot]
5fe52442bb
ci: bump pytest from 8.3.1 to 8.3.2 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.3.1 to 8.3.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.3.1...8.3.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-29 04:07:25 +00:00
Nicolas Duchon
8d47458026
Merge pull request #2493 from nginx-proxy/dependabot/pip/test/requirements/pytest-8.3.1
ci: bump pytest from 8.2.2 to 8.3.1 in /test/requirements
2024-07-22 08:11:55 +02:00
dependabot[bot]
f4ccdbd656
ci: bump pytest from 8.2.2 to 8.3.1 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.2.2 to 8.3.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.2.2...8.3.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-07-22 04:05:13 +00:00
Nicolas Duchon
31642a748f
Merge pull request #2485 from nginx-proxy/dependabot/github_actions/docker/build-push-action-6
ci: bump docker/build-push-action from 5 to 6
2024-06-24 23:37:05 +02:00
dependabot[bot]
261ac6f43b
ci: bump docker/build-push-action from 5 to 6
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-24 04:26:56 +00:00
Nicolas Duchon
b67b434711
Merge pull request #2478 from SchoNie/docs-1.6
docs: update version in README.md
2024-06-12 08:15:09 +02:00
Niek
705dfa090b docs: update version in README.md 2024-06-10 09:42:07 +02:00
Nicolas Duchon
e6c301a4a5
Merge pull request #2477 from nginx-proxy/dependabot/pip/test/requirements/pytest-8.2.2
ci: bump pytest from 8.2.1 to 8.2.2 in /test/requirements
2024-06-10 08:58:11 +02:00
dependabot[bot]
ff4657181a
ci: bump pytest from 8.2.1 to 8.2.2 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.2.1 to 8.2.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.2.1...8.2.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-10 04:59:33 +00:00
Nicolas Duchon
477366d9a4
Merge pull request #2475 from pini-gh/pini-fallback-https
fix: nohttp(s) shouldn't disable fallback server
2024-06-09 14:28:35 +02:00
Gilles Filippini
4606b15309 fix: nohttp(s) shouldn't disable fallback server
Say we have two containers:
- `app1` with `HTTPS_METHOD=redirect`
- `app2` with `HTTPS_METHOD=nohttps`

Without this change the fallback answer on an HTTPS request to an unknown
server would change depending on whether `app1` is up (503) or not
(connection refused). This is not wanted.

In case someone doesn't want HTTPS at all, they just have to not bind
port 443.
2024-06-06 22:04:15 +02:00
Nicolas Duchon
50608d7826
Merge pull request #2452 from pini-gh/pini-enforce-HTTPS_METHOD
fix: enforce HTTPS_METHOD on missing cert as well
2024-06-06 12:14:38 +02:00
Gilles Filippini
60b123d249 feat: ENABLE_HTTP_ON_MISSING_CERT variable
Default: true
2024-06-06 11:26:17 +02:00
Nicolas Duchon
9506e60f43
Merge pull request #2473 from nginx-proxy/enable-acme-challenge
feat: enable acme challenge location handling by default
2024-06-06 08:31:01 +02:00
Nicolas Duchon
cea905ff88
docs: typo
Co-authored-by: Niek <100143256+SchoNie@users.noreply.github.com>
2024-06-05 15:55:49 +02:00
Nicolas Duchon
714fa25704
style: docs linting 2024-06-05 08:47:39 +02:00
Nicolas Duchon
4bd542de99
feat: handle acme challenge location by default 2024-06-05 08:47:11 +02:00
dependabot[bot]
8de923fd33
ci: bump requests from 2.32.2 to 2.32.3 in /test/requirements (#2472)
Bumps [requests](https://github.com/psf/requests) from 2.32.2 to 2.32.3.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.32.2...v2.32.3)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-03 09:36:25 +02:00
Niek
7922c925af
chore: spelling fixes for #2468 (#2471) 2024-05-31 17:07:07 +02:00
dependabot[bot]
57e86561eb
build: bump library/nginx from 1.26.0 to 1.27.0 (#2470)
Bumps library/nginx from 1.26.0 to 1.27.0.

---
updated-dependencies:
- dependency-name: library/nginx
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-31 10:28:46 +02:00
pini-gh
9cf736f1f8
feat: variable ACME_HTTP_CHALLENGE_LOCATION (#2468)
Values:
* `legacy` (default): generate location blocks for ACME HTP Challenge
  excepted when `HTTPS_METHOD=noredirect` or there is no certificate for
  the domain
* `true`: generate location blocks for ACME HTP Challenge in all cases
* `false`: do not generate location blocks for ACME HTP Challenge

This feature is currently needed because acme-companion may generate
the HTTP Challenge configuration while it was done already by nginx-proxy
(see #2465#issuecomment-2136361373).

Also sometimes a hardcoded ACME challenge location is not wanted because
the challenge validation is not done with acme-companion / Let's Encrypt,
and with a challenge location setup differently.
2024-05-31 00:10:44 +02:00
dependabot[bot]
e904471cd3
build: bump nginxproxy/docker-gen from 0.13.1-debian to 0.14.0-debian (#2467)
Bumps nginxproxy/docker-gen from 0.13.1-debian to 0.14.0-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-28 07:45:00 +02:00
pini-gh
5f3ec18b28
docs: explicit policy on missing certificate (#2465)
* chore/doc: explicit policy on missing certificate

This doesn't change the current nginx-proxy behavior, but makes explicit
the current HTTPS_METHOD policy on missing certificate.

* fix: bad wording about missing certificate

Co-authored-by: Nicolas Duchon <nicolas.duchon@gmail.com>

* docs: typo in suggestion

---------

Co-authored-by: Nicolas Duchon <nicolas.duchon@gmail.com>
2024-05-27 20:50:13 +02:00
dependabot[bot]
0dfc8b7a50
ci: bump requests from 2.31.0 to 2.32.2 in /test/requirements (#2462)
Bumps [requests](https://github.com/psf/requests) from 2.31.0 to 2.32.2.
- [Release notes](https://github.com/psf/requests/releases)
- [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
- [Commits](https://github.com/psf/requests/compare/v2.31.0...v2.32.2)

---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-23 14:04:28 +02:00
dependabot[bot]
7a761e1073
ci: bump docker from 7.0.0 to 7.1.0 in /test/requirements (#2461)
Bumps [docker](https://github.com/docker/docker-py) from 7.0.0 to 7.1.0.
- [Release notes](https://github.com/docker/docker-py/releases)
- [Commits](https://github.com/docker/docker-py/compare/7.0.0...7.1.0)

---
updated-dependencies:
- dependency-name: docker
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-23 13:54:05 +02:00
Nicolas Duchon
fb9c3a646a
feat: custom default error page (#2430)
* feat: customizable error page

* fix: use regex on catchall root location to fix DEFAULT_ROOT=none test

* docs: custom error pages

* fix: don't use default nginx image error page

* docs: small fix
2024-05-22 08:23:48 +02:00
Nicolas Duchon
b4c7ea603e
Merge pull request #2460 from nginx-proxy/pin-request
fix: hardcode requests package version to 2.31.0
2024-05-21 13:45:34 +02:00
Nicolas Duchon
2a793b2d5b
fix: hardcode requests package version to 2.31.0
This reverts commit 1c1f8e8700.
2024-05-21 13:30:34 +02:00
Nicolas Duchon
df464bbc81
Merge pull request #2459 from nginx-proxy/dependabot/pip/test/requirements/requests-2.32.1
ci: bump requests from 2.31.0 to 2.32.1 in /test/requirements
2024-05-21 11:24:46 +02:00
dependabot[bot]
1c1f8e8700
---
updated-dependencies:
- dependency-name: requests
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-21 09:09:45 +00:00
Nicolas Duchon
ce2a78bebf
Merge pull request #2455 from nginx-proxy/dependabot/pip/test/requirements/pytest-8.2.1
ci: bump pytest from 8.2.0 to 8.2.1 in /test/requirements
2024-05-20 10:01:12 +02:00
dependabot[bot]
49f0b89fb0
ci: bump pytest from 8.2.0 to 8.2.1 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.2.0 to 8.2.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.2.0...8.2.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-20 04:47:19 +00:00
Nicolas Duchon
57501eb13f
Merge pull request #2449 from nginx-proxy/fix-fastcgi
fix: include a complete fastcgi_params config
2024-05-17 15:23:58 +02:00
Nicolas Duchon
87ce03e3c3
Merge pull request #2451 from nginx-proxy/dependabot/docker/nginxproxy/docker-gen-0.13.1-debian
build: bump nginxproxy/docker-gen from 0.13.0 to 0.13.1
2024-05-16 18:37:34 +02:00
dependabot[bot]
f22b64df79
build: bump nginxproxy/docker-gen from 0.13.0-debian to 0.13.1-debian
Bumps nginxproxy/docker-gen from 0.13.0-debian to 0.13.1-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-16 16:23:18 +00:00
Rodrigo Aguilera
8e372c39c2
fix: include a complete fastcgi_params config 2024-05-16 13:11:50 +02:00
Nicolas Duchon
f0f71f72f7 ci: login to dockerhub to avoid rate limiting 2024-05-15 21:31:17 +02:00
Nicolas Duchon
dcc97b9cff test: ipv6 docker networks 2024-05-15 20:28:08 +02:00
Nicolas Duchon
5aea820aaa feat: PREFER_IPV6_NETWORK environment variable 2024-05-15 19:38:18 +02:00
Nicolas Duchon
1b4a3b036b
Merge pull request #2448 from pini-gh/pini-nohttp-behavior
fix: constistent behavior for `HTTPS_METHOD=nohttp`
2024-05-15 15:09:19 +02:00
Gilles Filippini
91652aac48 fix: constistent behavior for HTTPS_METHOD=nohttp
Without this fix the response of nohttp sites to HTTP requests changes
depending on the existence of at least one HTTP enabled site:
* no HTTP enabled sites -> connection refused
* at least one HTTP enabled site -> 503

This fix ensures the response is always 503.
2024-05-14 22:37:32 +02:00
Nicolas Duchon
2564a93966
Merge pull request #2446 from pini-gh/pini-acme-challenge
Improve acme-challenge handling
2024-05-13 22:21:41 +02:00
Gilles Filippini
6c1b532ffb Improve acme-challenge handling
So that there is no need anymore for the Let's Encrypt companion to fiddle
with vhosts nginx configuration.

When `HTTPS_METHOD=nohttp` and the certificate is missing, enforce nohttp
instead of switching to `HTTPS_METHOD=redirect`.
2024-05-13 21:10:48 +02:00
Nicolas Duchon
db07d90ad8
Merge pull request #2434 from nginx-proxy/multiport-support
feat: multiport support
2024-05-09 12:29:00 +02:00
Nicolas Duchon
8e2642909e
Merge pull request #2445 from pini-gh/pini-disambiguate
build: disambiguate base image names
2024-05-08 21:17:59 +02:00
Gilles Filippini
5b1491f464 build: disambiguate base image names
to build with podman / buildah.
2024-05-08 19:54:59 +02:00
Nicolas Duchon
fc02a5ae38
Merge pull request #2444 from pini-gh/pini-fix-test-test_build.py
fix 'requirements' path in test/test_build.py
2024-05-08 19:31:01 +02:00
Gilles Filippini
59d5293480 fix 'requirements' path in test/test_build.py
Without this patch the test fails when run from project base directory.
2024-05-08 18:30:11 +02:00
Nicolas Duchon
ec405f31d7
Merge pull request #2078 from KagurazakaNyaa/main
Support TCP and UDP proxy
2024-05-08 13:41:31 +02:00
KagurazakaNyaa
12c4f0c7c2 Support TCP and UDP proxy 2024-05-06 18:55:35 +02:00
Nicolas Duchon
be319e6629
docs: typo
Co-authored-by: Niek <100143256+SchoNie@users.noreply.github.com>
2024-05-06 15:34:51 +02:00
Nicolas Duchon
99645f104d
docs: typo 2024-05-06 14:40:32 +02:00
Nicolas Duchon
f964176106
Merge pull request #2438 from p12tic/test-acme-challenge
tests: Add tests for how Let's Encrypt ACME challenge is handled
2024-05-06 12:19:29 +02:00
Povilas Kanapickas
d6c38a0bab tests: Add tests for how Let's Encrypt ACME challenge is handled
At the moment no changes to functionality are done, only the current
behavior is captured.
2024-05-06 13:07:04 +03:00
Nicolas Duchon
1bf7eff04f
test: multiport merge with legacy variable 2024-05-05 20:45:43 +02:00
Nicolas Duchon
c4c65a4441
Merge pull request #2440 from nginx-proxy/web-image-alpine
test: use python alpine variant as base for web image
2024-05-05 17:48:43 +02:00
Nicolas Duchon
be7c4c8c85
fix: do not discard containers without VIRTUAL_PATH
For containers grouped by identical VIRTUAL_HOST,
those with no VIRTUAL_PATH variable were silently discarded
when at least one container with VIRTUAL_PATH existed.
2024-05-05 16:36:04 +02:00
Nicolas Duchon
9a76577ebc
style: shellcheck linting 2024-05-05 16:31:50 +02:00
Nicolas Duchon
1b97b11173
test: use python:3-alpine as base for the web image 2024-05-05 16:31:32 +02:00
Nicolas Duchon
8b91f09a9b
docs: use examples closer to real life scenarios 2024-05-05 16:15:28 +02:00
Nicolas Duchon
d80ca7ec36
test: json syntax for multiports variable 2024-05-05 16:15:28 +02:00
Nicolas Duchon
53e9a03ac9
feat: print warning on unparsable VIRTUAL_HOST_MULTIPORTS 2024-05-05 16:15:28 +02:00
Nicolas Duchon
0baff189bc
refactor: get rid of get_path_info template 2024-05-05 16:15:28 +02:00
Nicolas Duchon
8359aa2089
docs: documentation for multiports support 2024-05-05 16:15:28 +02:00
Nicolas Duchon
47e2838e61
refactor: rename VIRTUAL_HOST_YAML -> VIRTUAL_HOST_MULTIPORTS 2024-05-05 16:15:27 +02:00
Nicolas Duchon
216eae9f70
test: multiports base test 2024-05-05 16:15:27 +02:00
Nicolas Duchon
62212186eb
test: re-organize test files 2024-05-05 16:15:27 +02:00
Nicolas Duchon
62d9c08474
fix: default values if port and dest are missing 2024-05-05 16:15:27 +02:00
Nicolas Duchon
fc98f4c953
refactor: cleanup template 2024-05-05 16:15:27 +02:00
Gilles Filippini
87e5b58b77
feat: multiports support using yaml syntax
(See nginx-proxy/nginx-proxy#1504)

Using variable VIRTUAL_HOST_MULTIPORTS as a dictionnary:

key: hostname
value: dictionnary:
  key: path
  value: struct
    port
    dest

When the dictionnary associated with a hostname is empty, default values
apply:
  path = "/"
  port = default port
  dest = ""

For each path entry, port and dest are optionnal and are assigned default
values when missing.

Example:
      VIRTUAL_HOST_MULTIPORTS: |
        host1.example.org:
          "/":
            port: 8000
          "/somewhere":
            port: 9000
            dest: "/elsewhere"
        host2.example.org:
        host3.example.org:
          "/inner/path":
2024-05-05 16:15:26 +02:00
Nicolas Duchon
6e771fb3be
Merge pull request #2439 from nginx-proxy/dependabot/docker/nginxproxy/docker-gen-0.13.0-debian
build: bump nginxproxy/docker-gen from 0.12.1 to 0.13.0
2024-05-05 16:15:02 +02:00
dependabot[bot]
340f6b0c08
build: bump nginxproxy/docker-gen from 0.12.1-debian to 0.13.0-debian
Bumps nginxproxy/docker-gen from 0.12.1-debian to 0.13.0-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-05 14:02:17 +00:00
Mehdi Zakaria Benadel
a4c694fefc feat: basic implementation of ipv6 for ipv6 docker networks 2024-05-03 17:41:07 +02:00
Nicolas Duchon
2ac4509a61
Merge pull request #2436 from nginx-proxy/dependabot/docker/nginxproxy/docker-gen-0.12.1-debian
build: bump nginxproxy/docker-gen from 0.12.0 to 0.12.1
2024-05-03 12:57:21 +02:00
Nicolas Duchon
b4bceac3fd
Merge pull request #2435 from SchoNie/nginx-proxy-tester
tests: add test if nginx-proxy-builder can be build successfully
2024-05-03 12:56:53 +02:00
dependabot[bot]
08f563888d
build: bump nginxproxy/docker-gen from 0.12.0-debian to 0.12.1-debian
Bumps nginxproxy/docker-gen from 0.12.0-debian to 0.12.1-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-03 10:49:23 +00:00
Nicolas Duchon
6602769d9a
style: linting 2024-05-03 12:37:53 +02:00
Niek
c678cfdddf
Apply suggestions from code review
Commited code style consistency suggestions.

Co-authored-by: Nicolas Duchon <nicolas.duchon@gmail.com>
2024-05-03 12:09:40 +02:00
Niek
46724e7cb6 tests: add test if nginx-proxy-builder can be build successfully 2024-05-03 11:36:50 +02:00
Nicolas Duchon
e46e62e660
Merge pull request #2433 from SchoNie/docs-urls
docs: url fixes
2024-05-03 11:32:25 +02:00
Niek
877f243ce2 docs: url fixes
Fix 404 to docker-entrypoint.sh
Add hyperlink to nginx.tmpl reference.
2024-05-03 11:19:07 +02:00
Nicolas Duchon
43b8ab82a9
Merge pull request #2432 from SchoNie/webserver-syntaxwarning-fix
fix: tests webserver syntaxwarning
2024-05-03 11:08:46 +02:00
Niek
12d639dad7 Change to raw string literal
To fix:
/webserver.py:17: SyntaxWarning: invalid escape sequence '\d'
  elif re.match("/status/(\d+)", self.path):
/webserver.py:18: SyntaxWarning: invalid escape sequence '\d'
  result = re.match("/status/(\d+)", self.path)
2024-05-03 10:49:15 +02:00
Nicolas Duchon
1e55d9883f
Merge pull request #2429 from nginx-proxy/docs-qol
docs: redordering, grouping and navigation
2024-05-02 17:51:05 +02:00
Nicolas Duchon
2ac4540a0d
docs: redordering, grouping and navigation 2024-05-02 15:28:24 +02:00
Nicolas Duchon
769d58bcfb
Merge pull request #2425 from nginx-proxy/dependabot/docker/nginx-1.26.0
build: bump nginx from 1.25.4 to 1.26.0
2024-05-01 13:47:35 +02:00
Nicolas Duchon
766db8d942 docs: update nginx version badge 2024-05-01 13:38:32 +02:00
dependabot[bot]
559c43e75e build: bump nginx from 1.25.4 to 1.26.0
Bumps nginx from 1.25.4 to 1.26.0.

---
updated-dependencies:
- dependency-name: nginx
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-01 13:38:32 +02:00
Nicolas Duchon
0d7aac7c53
Merge pull request #2428 from nginx-proxy/dependabot/pip/test/requirements/pytest-8.2.0
ci: bump pytest from 8.1.1 to 8.2.0 in /test/requirements
2024-05-01 13:25:05 +02:00
dependabot[bot]
103cb7d4ca
ci: bump pytest from 8.1.1 to 8.2.0 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.1.1 to 8.2.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.1.1...8.2.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-29 04:03:15 +00:00
Nicolas Duchon
94fb8459cd
Merge pull request #2410 from pini-gh/pini-refactor-template-3
refactor: add 'ports' dict to the data structure
2024-03-12 21:35:11 +01:00
Nicolas Duchon
c7bf75609b
Merge pull request #2411 from nginx-proxy/dependabot/pip/test/requirements/pytest-8.1.1
ci: bump pytest from 8.1.0 to 8.1.1 in /test/requirements
2024-03-12 21:12:40 +01:00
Nicolas Duchon
3c3b3675c1
Merge pull request #2413 from Huge/patch-1
Update README.md to use 1.5 version and link DockerHub
2024-03-12 21:11:50 +01:00
Huge
16b84ea1b5
Update README.md to use 1.5 version and link DockerHub 2024-03-12 14:23:56 +01:00
dependabot[bot]
6441daf25b
ci: bump pytest from 8.1.0 to 8.1.1 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.1.0 to 8.1.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.1.0...8.1.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-11 04:19:22 +00:00
Gilles Filippini
45770e04bd refactor: add 'ports' dict to the data structure
Nothing changes for the legacy syntax, but adding this level to the data
structure enables advanced port configuration.
2024-03-09 20:13:42 +01:00
Nicolas Duchon
26b0a0008b
Merge pull request #2408 from nginx-proxy/dependabot/pip/test/requirements/pytest-8.1.0
ci: bump pytest from 8.0.2 to 8.1.0 in /test/requirements
2024-03-04 22:06:21 +01:00
Nicolas Duchon
4b38bf259d
Merge pull request #2405 from nginx-proxy/refactor-template-2
refactor: template internal data structure
2024-03-04 22:03:30 +01:00
dependabot[bot]
12e1360fc3
ci: bump pytest from 8.0.2 to 8.1.0 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.0.2 to 8.1.0.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.0.2...8.1.0)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-03-04 04:52:02 +00:00
Nicolas Duchon
b09575297d
docs: typo in comments
Co-authored-by: Niek <100143256+SchoNie@users.noreply.github.com>
2024-02-27 13:27:11 +01:00
Nicolas Duchon
418f1a3cd0
fix: don't re-assign variable
Co-authored-by: pini-gh <pini@debian.org>
2024-02-27 13:20:39 +01:00
Nicolas Duchon
60618afe52
Merge pull request #2407 from nginx-proxy/dependabot/pip/test/requirements/pytest-8.0.2
ci: bump pytest from 8.0.1 to 8.0.2 in /test/requirements
2024-02-26 08:20:17 +01:00
dependabot[bot]
2a5521625d
ci: bump pytest from 8.0.1 to 8.0.2 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 8.0.1 to 8.0.2.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/8.0.1...8.0.2)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-26 04:49:11 +00:00
Nicolas Duchon
b8b53794bf
Merge pull request #2406 from nginx-proxy/dependabot/docker/nginxproxy/docker-gen-0.12.0-debian
build: bump nginxproxy/docker-gen from 0.11.2 to 0.12.0
2024-02-25 11:51:11 +01:00
dependabot[bot]
d588c96dff
build: bump nginxproxy/docker-gen from 0.11.2-debian to 0.12.0-debian
Bumps nginxproxy/docker-gen from 0.11.2-debian to 0.12.0-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-25 10:42:38 +00:00
Nicolas Duchon
f960061e2d
Merge pull request #2404 from nginx-proxy/network-host
docs: add comment about host network to compose example
2024-02-25 10:01:02 +01:00
Nicolas Duchon
e97be61272
refactor: refactor virtual paths 2024-02-24 21:51:50 +01:00
Nicolas Duchon
4d9d067630
refactor: refactor virtual hosts 2024-02-24 21:51:38 +01:00
Michael Bianco
8c95ed1cc0
docs: add comment about host network to compose example 2024-02-22 05:59:51 -07:00
Nicolas Duchon
9d2eeb7273
Merge pull request #2399 from nginx-proxy/dependabot/pip/test/requirements/pytest-8.0.1
ci: bump pytest from 7.4.4 to 8.0.1 in /test/requirements
2024-02-21 17:55:46 +01:00
Nicolas Duchon
24592e39a3
Merge pull request #2402 from SchoNie/htpasswd-tests
tests: htpasswd
2024-02-21 08:42:56 +01:00
Niek
a9f8a9c32a htpasswd tests 2024-02-21 08:34:38 +01:00
Nicolas Duchon
da006557d0
Merge pull request #2400 from SchoNie/tests-remove-obsolete
tests: remove obsolete stress-test
2024-02-21 08:33:58 +01:00
Niek
4464269c51 remove obsolete stress-test 2024-02-20 15:21:09 +01:00
Nicolas Duchon
b4902f145d
Merge pull request #2401 from SchoNie/docs-htpasswd-readability
docs: htpasswd readability
2024-02-19 22:42:24 +01:00
Niek
d4438b5a09
prevent double slash 2024-02-19 12:23:19 +01:00
Niek
50750bea53
highlight variables similar to other in readme 2024-02-19 12:21:02 +01:00
dependabot[bot]
0dd4f7a8a8
ci: bump pytest from 7.4.4 to 8.0.1 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.4 to 8.0.1.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.4...8.0.1)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-19 04:53:15 +00:00
Nicolas Duchon
a2a441e1db
docs: update nginx badge 2024-02-18 10:08:23 +01:00
Nicolas Duchon
5a32bffd6f
Merge pull request #2398 from nginx-proxy/dependabot/docker/nginx-1.25.4
build: bump nginx from 1.25.3 to 1.25.4
2024-02-18 09:56:22 +01:00
Nicolas Duchon
745a2035cf
Merge pull request #2397 from whomobile/patch-1
fix typo README.md
2024-02-16 10:59:15 +01:00
dependabot[bot]
29168655cf
build: bump nginx from 1.25.3 to 1.25.4
Bumps nginx from 1.25.3 to 1.25.4.

---
updated-dependencies:
- dependency-name: nginx
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-16 04:25:16 +00:00
Man Kim
2eaf689172
fix typo README.md
ngingx to nginx
2024-02-15 14:37:21 -08:00
Nicolas Duchon
e75c2dfb79
build: revert nginx to 1.25.3 (#2396)
* Revert "build: update docs and tests with nginx 1.25.4"

This reverts commit d9b1751f97.

* Revert "build: bump nginx from 1.25.3 to 1.25.4"

This reverts commit 1aef017df2.
2024-02-15 09:50:12 +01:00
Nicolas Duchon
020b993654
Merge pull request #2395 from nginx-proxy/dependabot/docker/nginx-1.25.4
build: bump nginx from 1.25.3 to 1.25.4
2024-02-15 08:54:52 +01:00
Nicolas Duchon
5583b385cb
style: docs linting 2024-02-15 08:41:11 +01:00
Nicolas Duchon
d9b1751f97
build: update docs and tests with nginx 1.25.4 2024-02-15 08:40:46 +01:00
dependabot[bot]
1aef017df2
build: bump nginx from 1.25.3 to 1.25.4
Bumps nginx from 1.25.3 to 1.25.4.

---
updated-dependencies:
- dependency-name: nginx
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-15 04:46:02 +00:00
Nicolas Duchon
5c0c8c93d8
Merge pull request #2393 from SchoNie/tests-nonstandardport-hostheader
tests: non standard port Host header check
2024-02-13 18:23:14 +01:00
Niek
cb59c24470
tests non standard port Host header 2024-02-13 15:24:37 +01:00
Nicolas Duchon
887e2e950c
Merge pull request #2390 from nginx-proxy/dependabot/docker/nginxproxy/docker-gen-0.11.2-debian
build: bump nginxproxy/docker-gen from 0.11.1 to 0.11.2
2024-02-10 19:25:13 +01:00
dependabot[bot]
3a19382702
build: bump nginxproxy/docker-gen from 0.11.1-debian to 0.11.2-debian
Bumps nginxproxy/docker-gen from 0.11.1-debian to 0.11.2-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-10 18:16:49 +00:00
Nicolas Duchon
f47c874c5a
Merge pull request #2197 from darh/json_log_format
Add more control over log_format config directive
2024-02-10 19:16:11 +01:00
Nicolas Duchon
25883ac05f
style: remove extra blank lines 2024-02-10 19:04:56 +01:00
Nicolas Duchon
62f55b4428
docs: add logging documentation 2024-02-10 19:03:13 +01:00
Nicolas Duchon
76778cebb1
refactor: parse LOG_JSON as boolean + avoid unnecessary backticks 2024-02-10 18:40:18 +01:00
Nicolas Duchon
8aefce916f
tests: fix the json log test compose files 2024-02-10 18:02:42 +01:00
Denis Arh
de9809a9e5 Add more control over log_format config directive
Introduces 3 new environmental variables:
 - `LOG_FORMAT`
 - `LOG_FORMAT_ESCAPE`
 - `LOG_JSON`

`LOG_FORMAT` and `LOG_FORMAT_ESCAPE` default to standard values.
When `LOG_JSON` is set, defaults are changed to: `{"time_local":"$time_iso8601","client_ip":"$http_x_forwarded_for","remote_addr":"$remote_addr","request":"$request","status":"$status","body_bytes_sent":"$body_bytes_sent","request_time":"$request_time","upstream_response_time":"$upstream_response_time","upstream_addr":"$upstream_addr","http_referrer":"$http_referer","http_user_agent":"$http_user_agent","request_id":"$request_id"}`and `json`.

See `nginx.tmpl` and https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format for details
2024-02-10 17:39:16 +01:00
Nicolas Duchon
e50429e87e
Merge pull request #2389 from nginx-proxy/2300
feat: define basic auth for virtual path
2024-02-10 16:33:27 +01:00
jmformenti
fa23c11edb
feat: define basic auth for virtual path 2024-02-10 16:24:00 +01:00
Nicolas Duchon
df890def7c
Merge pull request #2388 from nginx-proxy/2386
fix: add non standard port to Host header
2024-02-10 16:06:46 +01:00
Nicolas Duchon
40a347bfae
fix: add non standard port to Host header 2024-02-10 15:23:35 +01:00
Nicolas Duchon
af56ba2254
Merge pull request #2387 from nginx-proxy/1780
fix: set worker_rlimit_nofile to (worker_connections x 2)
2024-02-10 14:17:40 +01:00
Nicolas Duchon
5d10467c42
fix: set worker_rlimit_nofile to (worker_connections x 2) 2024-02-10 13:56:38 +01:00
Nicolas Duchon
3d61f47b54
Merge pull request #2383 from lysliu/patch-1
Add s390x support
2024-02-01 11:19:41 +01:00
Yan Song Liu
af5acae58a
Add s390x support
Add s390x support

Signed-off-by: Yan Song Liu <lysliu@cn.ibm.com>
2024-02-01 14:42:15 +08:00
Nicolas Duchon
e8d95764fb
Merge pull request #2381 from nginx-proxy/dependabot/github_actions/peter-evans/dockerhub-description-4
ci: bump peter-evans/dockerhub-description from 3 to 4
2024-01-29 19:59:23 +01:00
dependabot[bot]
bfe9e0ac1d
ci: bump peter-evans/dockerhub-description from 3 to 4
Bumps [peter-evans/dockerhub-description](https://github.com/peter-evans/dockerhub-description) from 3 to 4.
- [Release notes](https://github.com/peter-evans/dockerhub-description/releases)
- [Commits](https://github.com/peter-evans/dockerhub-description/compare/v3...v4)

---
updated-dependencies:
- dependency-name: peter-evans/dockerhub-description
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-29 04:35:11 +00:00
Nicolas Duchon
d46881fb58
Merge pull request #2321 from theFra985/patch-1
Add support for grpcs protocol
2024-01-16 18:59:45 +01:00
Nicolas Duchon
6f042854e1
Merge pull request #2364 from nginx-proxy/keepalive
feat: keepalive auto setting
2024-01-13 11:40:45 +01:00
Nicolas Duchon
14347a4178
Merge pull request #2372 from nginx-proxy/add-openssl-back
build: add the openssl cli back to the alpine image
2024-01-10 17:11:52 +01:00
Nicolas Duchon
63411b2407
build: add the openssl cli back to the alpine image 2024-01-10 17:00:47 +01:00
Nicolas Duchon
b492cae053
Merge pull request #2369 from SchoNie/nginx-proxy-tester-compose
Install docker compose dependencies in nginx-proxy-tester image
2024-01-05 17:44:31 +01:00
Niek
329b69fe76
Update test readme 2024-01-05 14:33:05 +01:00
Niek
1433daed4d
Install docker dependencies in nginx-proxy-tester image 2024-01-05 14:32:11 +01:00
Nicolas Duchon
a3de83c7d1
Merge pull request #2365 from nginx-proxy/dependabot/pip/test/requirements/pytest-7.4.4
ci: bump pytest from 7.4.3 to 7.4.4 in /test/requirements
2024-01-01 10:58:15 +01:00
dependabot[bot]
e2bd0d6365
ci: bump pytest from 7.4.3 to 7.4.4 in /test/requirements
Bumps [pytest](https://github.com/pytest-dev/pytest) from 7.4.3 to 7.4.4.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/7.4.3...7.4.4)

---
updated-dependencies:
- dependency-name: pytest
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-01 04:39:54 +00:00
Nicolas Duchon
d12689cd52 docs: keepalive auto setting 2023-12-26 19:10:42 +01:00
Nicolas Duchon
2aa35aa637 tests: keepalive auto setting 2023-12-26 19:07:09 +01:00
Nicolas Duchon
443ee5202c test: do we get desired number of idle keepalive connections 2023-12-26 18:52:43 +01:00
Nicolas Duchon
d56e8f1d8a refactor: $server_found and $servers aren't both needed 2023-12-26 18:43:05 +01:00
Nicolas Duchon
7ce72d59a9 feat: add auto keepalive setting 2023-12-26 18:33:28 +01:00
Nicolas Duchon
26db13387e refactor: explicitely default keepalive to disabled 2023-12-26 17:58:24 +01:00
Nicolas Duchon
35c6b2afe5
Merge pull request #2362 from nginx-proxy/dependabot/docker/nginxproxy/forego-0.18.1-debian
build: bump nginxproxy/forego from 0.17.3 to 0.18.1
2023-12-25 21:26:58 +01:00
Nicolas Duchon
beeb80732a docs: mention color disabling 2023-12-25 21:19:02 +01:00
dependabot[bot]
47ee75d780
build: bump nginxproxy/forego from 0.17.3-debian to 0.18.1-debian
Bumps nginxproxy/forego from 0.17.3-debian to 0.18.1-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/forego
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-25 20:12:56 +00:00
Nicolas Duchon
53656ffe51
Merge pull request #2360 from nginx-proxy/dependabot/docker/nginxproxy/docker-gen-0.11.1-debian
build: bump nginxproxy/docker-gen from 0.11.0 to 0.11.1
2023-12-25 21:11:57 +01:00
Nicolas Duchon
795cc1332b
Merge pull request #2358 from nginx-proxy/proxy_buffering
feat: enable proxy_buffering
2023-12-25 20:45:51 +01:00
dependabot[bot]
051c8a5105
build: bump nginxproxy/docker-gen from 0.11.0-debian to 0.11.1-debian
Bumps nginxproxy/docker-gen from 0.11.0-debian to 0.11.1-debian.

---
updated-dependencies:
- dependency-name: nginxproxy/docker-gen
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-25 19:45:00 +00:00
Nicolas Duchon
4fbd14f1fd
Merge pull request #2359 from nginx-proxy/cleanup-dockerfiles
refactor: cleanup dockerfiles
2023-12-25 20:22:37 +01:00
Nicolas Duchon
eb9fca85cf refactor: remove already present or unneeded dependencies 2023-12-25 19:19:57 +01:00
Nicolas Duchon
758b43a5b2 refactor: remove unneeded nginx.conf modification
the upstream nginx.conf already has "worker_processes  auto;"
2023-12-25 19:18:00 +01:00
Nicolas Duchon
de4cb3d2b0 refactor: move nginx daemon off to procfile 2023-12-25 19:16:10 +01:00
Nicolas Duchon
5c1db95551 feat: enable proxy_buffering 2023-12-25 17:27:34 +01:00
Francesco Cattoni
a5566f5e8f
Added support for grpcs protocol 2023-10-22 00:34:32 +02:00
268 changed files with 4332 additions and 1782 deletions

View file

@ -0,0 +1,85 @@
name: Build and publish Docker images on demand
on:
workflow_dispatch:
inputs:
image_tag:
description: "Image tag"
type: string
required: true
jobs:
multiarch-build:
name: Build and publish ${{ matrix.base }} image with tag ${{ inputs.image_tag }}
strategy:
matrix:
base: [alpine, debian]
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Retrieve nginx-proxy version
id: nginx-proxy_version
run: echo "VERSION=$(git describe --tags)" >> "$GITHUB_OUTPUT"
- name: Retrieve docker-gen version
id: docker-gen_version
run: sed -n -e 's;^FROM nginxproxy/docker-gen:\([0-9.]*\).*;VERSION=\1;p' Dockerfile.${{ matrix.base }} >> "$GITHUB_OUTPUT"
- name: Get Docker tags
id: docker_meta
uses: docker/metadata-action@v5
with:
images: |
nginxproxy/nginx-proxy
tags: |
type=raw,value=${{ inputs.image_tag }},enable=${{ matrix.base == 'debian' }}
type=raw,value=${{ inputs.image_tag }},suffix=-alpine,enable=${{ matrix.base == 'alpine' }}
labels: |
org.opencontainers.image.authors=Nicolas Duchon <nicolas.duchon@gmail.com> (@buchdag), Jason Wilder
org.opencontainers.image.version=${{ steps.nginx-proxy_version.outputs.VERSION }}
flavor: |
latest=false
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push the image
id: docker_build
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile.${{ matrix.base }}
build-args: |
NGINX_PROXY_VERSION=${{ steps.nginx-proxy_version.outputs.VERSION }}
DOCKER_GEN_VERSION=${{ steps.docker-gen_version.outputs.VERSION }}
platforms: linux/amd64,linux/arm64,linux/s390x,linux/arm/v7
sbom: true
push: true
provenance: mode=max
tags: ${{ steps.docker_meta.outputs.tags }}
labels: ${{ steps.docker_meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Images digests
run: echo ${{ steps.docker_build.outputs.digest }}

View file

@ -81,14 +81,14 @@ jobs:
- name: Build and push the image - name: Build and push the image
id: docker_build id: docker_build
uses: docker/build-push-action@v5 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: Dockerfile.${{ matrix.base }} file: Dockerfile.${{ matrix.base }}
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 }}
platforms: linux/amd64,linux/arm64,linux/arm/v7 platforms: linux/amd64,linux/arm64,linux/s390x,linux/arm/v7
sbom: true sbom: true
push: true push: true
provenance: mode=max provenance: mode=max

View file

@ -18,7 +18,7 @@ jobs:
uses: actions/checkout@v4 uses: actions/checkout@v4
- name: Docker Hub Description - name: Docker Hub Description
uses: peter-evans/dockerhub-description@v3 uses: peter-evans/dockerhub-description@v4
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN_RWD }} password: ${{ secrets.DOCKERHUB_TOKEN_RWD }}

View file

@ -25,10 +25,10 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Set up Python 3.9 - name: Set up Python 3.12
uses: actions/setup-python@v5 uses: actions/setup-python@v5
with: with:
python-version: 3.9 python-version: 3.12
- name: Install dependencies - name: Install dependencies
run: | run: |
@ -36,6 +36,9 @@ jobs:
pip install -r python-requirements.txt pip install -r python-requirements.txt
working-directory: test/requirements working-directory: test/requirements
- name: Pull nginx:alpine image
run: docker pull nginx:alpine
- name: Build Docker web server image - name: Build Docker web server image
run: make build-webserver run: make build-webserver

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
**/__pycache__/ **/__pycache__/
**/.cache/ **/.cache/
.idea/ .idea/
wip

View file

@ -1,9 +1,9 @@
FROM nginxproxy/docker-gen:0.11.0 AS docker-gen FROM docker.io/nginxproxy/docker-gen:0.14.5 AS docker-gen
FROM nginxproxy/forego:0.17.3 AS forego FROM docker.io/nginxproxy/forego:0.18.2 AS forego
# Build the final image # Build the final image
FROM nginx:1.25.3-alpine FROM docker.io/library/nginx:1.27.3-alpine
ARG NGINX_PROXY_VERSION ARG NGINX_PROXY_VERSION
# Add DOCKER_GEN_VERSION environment variable because # Add DOCKER_GEN_VERSION environment variable because
@ -14,26 +14,25 @@ ENV NGINX_PROXY_VERSION=${NGINX_PROXY_VERSION} \
DOCKER_HOST=unix:///tmp/docker.sock DOCKER_HOST=unix:///tmp/docker.sock
# Install dependencies # Install dependencies
RUN apk add --no-cache --virtual .run-deps \ RUN apk add --no-cache --virtual .run-deps bash openssl
bash \
ca-certificates \
openssl \
&& update-ca-certificates
# Configure Nginx # Configure Nginx
RUN sed -i 's/\[ "\$1" = "nginx" \]/\[ "\$1" = "forego" \] || \[ "\$1" = "nginx" \]/' /docker-entrypoint.sh \ RUN echo -e "\ninclude /etc/nginx/toplevel.conf.d/*.conf;" >> /etc/nginx/nginx.conf \
&& sed -i 's/worker_processes 1/worker_processes auto/' /etc/nginx/nginx.conf \ && sed -i 's/worker_connections.*;$/worker_connections 10240;/' /etc/nginx/nginx.conf \
&& sed -i 's/worker_connections 1024/worker_connections 10240/' /etc/nginx/nginx.conf \ && sed -i -e '/^\}$/{s//\}\nworker_rlimit_nofile 20480;/;:a' -e '$!N;$!ba' -e '}' /etc/nginx/nginx.conf \
&& mkdir -p '/etc/nginx/dhparam' && mkdir -p '/etc/nginx/toplevel.conf.d' \
&& mkdir -p '/etc/nginx/dhparam' \
&& mkdir -p '/etc/nginx/certs' \
&& mkdir -p '/usr/share/nginx/html/errors'
# Install Forego + docker-gen # Install Forego + docker-gen
COPY --from=forego /usr/local/bin/forego /usr/local/bin/forego COPY --from=forego /usr/local/bin/forego /usr/local/bin/forego
COPY --from=docker-gen /usr/local/bin/docker-gen /usr/local/bin/docker-gen COPY --from=docker-gen /usr/local/bin/docker-gen /usr/local/bin/docker-gen
COPY network_internal.conf /etc/nginx/ COPY network_internal.conf /etc/nginx/
COPY app/40-nginx-proxy.sh /docker-entrypoint.d/
COPY app nginx.tmpl LICENSE /app/ COPY app nginx.tmpl LICENSE /app/
WORKDIR /app/ WORKDIR /app/
ENTRYPOINT ["/app/docker-entrypoint.sh"]
CMD ["forego", "start", "-r"] CMD ["forego", "start", "-r"]

View file

@ -1,9 +1,9 @@
FROM nginxproxy/docker-gen:0.11.0-debian AS docker-gen FROM docker.io/nginxproxy/docker-gen:0.14.5-debian AS docker-gen
FROM nginxproxy/forego:0.17.3-debian AS forego FROM docker.io/nginxproxy/forego:0.18.2-debian AS forego
# Build the final image # Build the final image
FROM nginx:1.25.3 FROM docker.io/library/nginx:1.27.3
ARG NGINX_PROXY_VERSION ARG NGINX_PROXY_VERSION
# Add DOCKER_GEN_VERSION environment variable because # Add DOCKER_GEN_VERSION environment variable because
@ -13,26 +13,23 @@ ENV NGINX_PROXY_VERSION=${NGINX_PROXY_VERSION} \
DOCKER_GEN_VERSION=${DOCKER_GEN_VERSION} \ DOCKER_GEN_VERSION=${DOCKER_GEN_VERSION} \
DOCKER_HOST=unix:///tmp/docker.sock DOCKER_HOST=unix:///tmp/docker.sock
# Install/update certificates
RUN apt-get update \
&& apt-get install -y -q --no-install-recommends ca-certificates \
&& apt-get clean \
&& rm -r /var/lib/apt/lists/*
# Configure Nginx # Configure Nginx
RUN sed -i 's/\[ "\$1" = "nginx" \]/\[ "\$1" = "forego" \] || \[ "\$1" = "nginx" \]/' /docker-entrypoint.sh \ RUN echo "\ninclude /etc/nginx/toplevel.conf.d/*.conf;" >> /etc/nginx/nginx.conf \
&& sed -i 's/worker_processes 1/worker_processes auto/' /etc/nginx/nginx.conf \ && sed -i 's/worker_connections.*;$/worker_connections 10240;/' /etc/nginx/nginx.conf \
&& sed -i 's/worker_connections 1024/worker_connections 10240/' /etc/nginx/nginx.conf \ && sed -i -e '/^\}$/{s//\}\nworker_rlimit_nofile 20480;/;:a' -e '$!N;$!ba' -e '}' /etc/nginx/nginx.conf \
&& mkdir -p '/etc/nginx/dhparam' && mkdir -p '/etc/nginx/toplevel.conf.d' \
&& mkdir -p '/etc/nginx/dhparam' \
&& mkdir -p '/etc/nginx/certs' \
&& mkdir -p '/usr/share/nginx/html/errors'
# Install Forego + docker-gen # Install Forego + docker-gen
COPY --from=forego /usr/local/bin/forego /usr/local/bin/forego COPY --from=forego /usr/local/bin/forego /usr/local/bin/forego
COPY --from=docker-gen /usr/local/bin/docker-gen /usr/local/bin/docker-gen COPY --from=docker-gen /usr/local/bin/docker-gen /usr/local/bin/docker-gen
COPY network_internal.conf /etc/nginx/ COPY network_internal.conf /etc/nginx/
COPY app/40-nginx-proxy.sh /docker-entrypoint.d/
COPY app nginx.tmpl LICENSE /app/ COPY app nginx.tmpl LICENSE /app/
WORKDIR /app/ WORKDIR /app/
ENTRYPOINT ["/app/docker-entrypoint.sh"]
CMD ["forego", "start", "-r"] CMD ["forego", "start", "-r"]

View file

@ -1,10 +1,9 @@
[![Test](https://github.com/nginx-proxy/nginx-proxy/actions/workflows/test.yml/badge.svg)](https://github.com/nginx-proxy/nginx-proxy/actions/workflows/test.yml) [![Test](https://github.com/nginx-proxy/nginx-proxy/actions/workflows/test.yml/badge.svg)](https://github.com/nginx-proxy/nginx-proxy/actions/workflows/test.yml)
[![GitHub release](https://img.shields.io/github/v/release/nginx-proxy/nginx-proxy)](https://github.com/nginx-proxy/nginx-proxy/releases) [![GitHub release](https://img.shields.io/github/v/release/nginx-proxy/nginx-proxy)](https://github.com/nginx-proxy/nginx-proxy/releases)
![nginx 1.25.3](https://img.shields.io/badge/nginx-1.25.3-brightgreen.svg) [![nginx 1.27.3](https://img.shields.io/badge/nginx-1.27.3-brightgreen.svg?logo=nginx)](https://nginx.org/en/CHANGES)
[![Docker Image Size](https://img.shields.io/docker/image-size/nginxproxy/nginx-proxy?sort=semver)](https://hub.docker.com/r/nginxproxy/nginx-proxy "Click to view the image on Docker Hub") [![Docker Image Size](https://img.shields.io/docker/image-size/nginxproxy/nginx-proxy?sort=semver)](https://hub.docker.com/r/nginxproxy/nginx-proxy "Click to view the image on Docker Hub")
[![Docker stars](https://img.shields.io/docker/stars/nginxproxy/nginx-proxy.svg)](https://hub.docker.com/r/nginxproxy/nginx-proxy 'DockerHub') [![Docker stars](https://img.shields.io/docker/stars/nginxproxy/nginx-proxy.svg)](https://hub.docker.com/r/nginxproxy/nginx-proxy "DockerHub")
[![Docker pulls](https://img.shields.io/docker/pulls/nginxproxy/nginx-proxy.svg)](https://hub.docker.com/r/nginxproxy/nginx-proxy 'DockerHub') [![Docker pulls](https://img.shields.io/docker/pulls/nginxproxy/nginx-proxy.svg)](https://hub.docker.com/r/nginxproxy/nginx-proxy "DockerHub")
nginx-proxy sets up a container running nginx and [docker-gen](https://github.com/nginx-proxy/docker-gen). docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped. nginx-proxy sets up a container running nginx and [docker-gen](https://github.com/nginx-proxy/docker-gen). docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped.
@ -19,9 +18,19 @@ docker run --detach \
--name nginx-proxy \ --name nginx-proxy \
--publish 80:80 \ --publish 80:80 \
--volume /var/run/docker.sock:/tmp/docker.sock:ro \ --volume /var/run/docker.sock:/tmp/docker.sock:ro \
nginxproxy/nginx-proxy:1.4 nginxproxy/nginx-proxy:1.6
```
docker-compose
```docker-compose
services:
nginx-proxy:
image: nginxproxy/nginx-proxy
restart: always
ports:
- "80:80"
volumes:
- "/var/run/docker.sock:/tmp/docker.sock"
``` ```
Then start any containers (here an nginx container) you want proxied with an env var `VIRTUAL_HOST=subdomain.yourdomain.com` Then start any containers (here an nginx container) you want proxied with an env var `VIRTUAL_HOST=subdomain.yourdomain.com`
```console ```console
@ -30,10 +39,16 @@ docker run --detach \
--env VIRTUAL_HOST=foo.bar.com \ --env VIRTUAL_HOST=foo.bar.com \
nginx nginx
``` ```
docker-compose
```docker-compose
environment:
- VIRTUAL_HOST=git.patachina.casacam.net
- VIRTUAL_PORT=3000
```
Provided your DNS is setup to resolve `foo.bar.com` to the host running nginx-proxy, a request to `http://foo.bar.com` will then be routed to a container with the `VIRTUAL_HOST` env var set to `foo.bar.com` (in this case, the **your-proxied-app** container). Provided your DNS is setup to resolve `foo.bar.com` to the host running nginx-proxy, a request to `http://foo.bar.com` will then be routed to a container with the `VIRTUAL_HOST` env var set to `foo.bar.com` (in this case, the **your-proxied-app** container).
The containers being proxied must : The containers being proxied must :
- [expose](https://docs.docker.com/engine/reference/run/#expose-incoming-ports) the port to be proxied, either by using the `EXPOSE` directive in their `Dockerfile` or by using the `--expose` flag to `docker run` or `docker create`. - [expose](https://docs.docker.com/engine/reference/run/#expose-incoming-ports) the port to be proxied, either by using the `EXPOSE` directive in their `Dockerfile` or by using the `--expose` flag to `docker run` or `docker create`.
- share at least one Docker network with the nginx-proxy container: by default, if you don't pass the `--net` flag when your nginx-proxy container is created, it will only be attached to the default bridge network. This means that it will not be able to connect to containers on networks other than bridge. - share at least one Docker network with the nginx-proxy container: by default, if you don't pass the `--net` flag when your nginx-proxy container is created, it will only be attached to the default bridge network. This means that it will not be able to connect to containers on networks other than bridge.
@ -48,7 +63,7 @@ The nginx-proxy images are available in two flavors.
This image is based on the nginx:mainline image, itself based on the debian slim image. This image is based on the nginx:mainline image, itself based on the debian slim image.
```console ```console
docker pull nginxproxy/nginx-proxy:1.4 docker pull nginxproxy/nginx-proxy:1.6
``` ```
#### Alpine based version (`-alpine` suffix) #### Alpine based version (`-alpine` suffix)
@ -56,15 +71,22 @@ docker pull nginxproxy/nginx-proxy:1.4
This image is based on the nginx:alpine image. This image is based on the nginx:alpine image.
```console ```console
docker pull nginxproxy/nginx-proxy:1.4-alpine docker pull nginxproxy/nginx-proxy:1.6-alpine
``` ```
#### :warning: a note on `latest` and `alpine`: > [!IMPORTANT]
>
It is not recommended to use the `latest` (`nginxproxy/nginx-proxy`, `nginxproxy/nginx-proxy:latest`) or `alpine` (`nginxproxy/nginx-proxy:alpine`) tag for production setups. > #### A note on `latest` and `alpine`:
>
Those tags points to the latest commit in the `main` branch. They do not carry any promise of stability, and using them will probably put your nginx-proxy setup at risk of experiencing uncontrolled updates to non backward compatible versions (or versions with breaking changes). You should always specify the version you want to use explicitly to ensure your setup doesn't break when the image is updated. > It is not recommended to use the `latest` (`nginxproxy/nginx-proxy`, `nginxproxy/nginx-proxy:latest`) or `alpine` (`nginxproxy/nginx-proxy:alpine`) tag for production setups.
>
> [Those tags point](https://hub.docker.com/r/nginxproxy/nginx-proxy/tags) to the latest commit in the `main` branch. They do not carry any promise of stability, and using them will probably put your nginx-proxy setup at risk of experiencing uncontrolled updates to non backward compatible versions (or versions with breaking changes). You should always specify the version you want to use explicitly to ensure your setup doesn't break when the image is updated.
### Additional documentation ### Additional documentation
Please check the [docs section](https://github.com/nginx-proxy/nginx-proxy/tree/main/docs). Please check the [docs section](https://github.com/nginx-proxy/nginx-proxy/tree/main/docs).
### Powered by
[![GoLand logo](https://resources.jetbrains.com/storage/products/company/brand/logos/GoLand_icon.svg)](https://www.jetbrains.com/go/)
[![PyCharm logo](https://resources.jetbrains.com/storage/products/company/brand/logos/PyCharm_icon.svg)](https://www.jetbrains.com/pycharm/)

View file

@ -117,3 +117,5 @@ if [[ $* == 'forego start -r' ]]; then
EOT EOT
fi fi
fi fi
exec "$@"

View file

@ -1,4 +1,5 @@
version: "2" volumes:
nginx_conf:
services: services:
nginx: nginx:
@ -7,17 +8,15 @@ services:
ports: ports:
- "80:80" - "80:80"
volumes: volumes:
- /etc/nginx/conf.d - nginx_conf:/etc/nginx/conf.d:ro
dockergen: dockergen:
image: nginxproxy/docker-gen image: nginxproxy/docker-gen
command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
/etc/nginx/conf.d/default.conf
volumes_from:
- nginx
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
whoami: whoami:
image: jwilder/whoami image: jwilder/whoami

View file

@ -1,5 +1,3 @@
version: "2"
services: services:
nginx-proxy: nginx-proxy:
image: nginxproxy/nginx-proxy image: nginxproxy/nginx-proxy
@ -9,6 +7,9 @@ services:
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - /var/run/docker.sock:/tmp/docker.sock:ro
# if you want to proxy based on host ports, you'll want to use the host network
# network_mode: "host"
whoami: whoami:
image: jwilder/whoami image: jwilder/whoami
environment: environment:

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

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

View file

@ -24,7 +24,7 @@ fi
# Create a nginx container (which conveniently provides the `openssl` command) # Create a nginx container (which conveniently provides the `openssl` command)
############################################################################### ###############################################################################
CONTAINER=$(docker run -d -v $DIR:/work -w /work -e SAN="$ALTERNATE_DOMAINS" nginx:1.25.3) CONTAINER=$(docker run -d -v $DIR:/work -w /work -e SAN="$ALTERNATE_DOMAINS" nginx:1.27.3)
# Configure openssl # Configure openssl
docker exec $CONTAINER bash -c ' docker exec $CONTAINER bash -c '
mkdir -p /ca/{certs,crl,private,newcerts} 2>/dev/null mkdir -p /ca/{certs,crl,private,newcerts} 2>/dev/null

View file

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

View file

@ -1,28 +1,35 @@
import contextlib import contextlib
import logging import logging
import os import os
import pathlib
import platform
import re import re
import shlex import shlex
import socket import socket
import subprocess import subprocess
import time import time
from typing import List from io import StringIO
from typing import Iterator, List, Optional
import backoff import backoff
import docker import docker.errors
import pytest import pytest
import requests import requests
from _pytest._code.code import ReprExceptionInfo from _pytest.fixtures import FixtureRequest
from distutils.version import LooseVersion from docker import DockerClient
from docker.models.containers import Container from docker.models.containers import Container
from requests.packages.urllib3.util.connection import HAS_IPV6 from docker.models.networks import Network
from packaging.version import Version
from requests import Response
from urllib3.util.connection import HAS_IPV6
logging.basicConfig(level=logging.INFO) logging.basicConfig(level=logging.INFO)
logging.getLogger('backoff').setLevel(logging.INFO) logging.getLogger('backoff').setLevel(logging.INFO)
logging.getLogger('DNS').setLevel(logging.DEBUG) logging.getLogger('DNS').setLevel(logging.DEBUG)
logging.getLogger('requests.packages.urllib3.connectionpool').setLevel(logging.WARN) logging.getLogger('requests.packages.urllib3.connectionpool').setLevel(logging.WARN)
CA_ROOT_CERTIFICATE = os.path.join(os.path.dirname(__file__), 'certs/ca-root.crt') CA_ROOT_CERTIFICATE = pathlib.Path(__file__).parent.joinpath("certs/ca-root.crt")
PYTEST_RUNNING_IN_CONTAINER = os.environ.get('PYTEST_RUNNING_IN_CONTAINER') == "1" PYTEST_RUNNING_IN_CONTAINER = os.environ.get('PYTEST_RUNNING_IN_CONTAINER') == "1"
FORCE_CONTAINER_IPV6 = False # ugly global state to consider containers' IPv6 address instead of IPv4 FORCE_CONTAINER_IPV6 = False # ugly global state to consider containers' IPv6 address instead of IPv4
@ -40,8 +47,9 @@ test_container = 'nginx-proxy-pytest'
# #
############################################################################### ###############################################################################
@contextlib.contextmanager @contextlib.contextmanager
def ipv6(force_ipv6=True): def ipv6(force_ipv6: bool = True):
""" """
Meant to be used as a context manager to force IPv6 sockets: Meant to be used as a context manager to force IPv6 sockets:
@ -59,19 +67,19 @@ def ipv6(force_ipv6=True):
FORCE_CONTAINER_IPV6 = False FORCE_CONTAINER_IPV6 = False
class requests_for_docker(object): class RequestsForDocker:
""" """
Proxy for calling methods of the requests module. Proxy for calling methods of the requests module.
When a HTTP response failed due to HTTP Error 404 or 502, retry a few times. When an HTTP response failed due to HTTP Error 404 or 502, retry a few times.
Provides method `get_conf` to extract the nginx-proxy configuration content. Provides method `get_conf` to extract the nginx-proxy configuration content.
""" """
def __init__(self): def __init__(self):
self.session = requests.Session() self.session = requests.Session()
if os.path.isfile(CA_ROOT_CERTIFICATE): if CA_ROOT_CERTIFICATE.is_file():
self.session.verify = CA_ROOT_CERTIFICATE self.session.verify = CA_ROOT_CERTIFICATE.as_posix()
@staticmethod @staticmethod
def get_nginx_proxy_containers() -> List[Container]: def get_nginx_proxy_container() -> Container:
""" """
Return list of containers Return list of containers
""" """
@ -80,69 +88,69 @@ class requests_for_docker(object):
pytest.fail("Too many running nginxproxy/nginx-proxy:test containers", pytrace=False) pytest.fail("Too many running nginxproxy/nginx-proxy:test 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("No running nginxproxy/nginx-proxy:test container", pytrace=False)
return nginx_proxy_containers return nginx_proxy_containers.pop()
def get_conf(self): def get_conf(self) -> bytes:
""" """
Return the nginx config file Return the nginx config file
""" """
nginx_proxy_containers = self.get_nginx_proxy_containers() nginx_proxy_container = self.get_nginx_proxy_container()
return get_nginx_conf_from_container(nginx_proxy_containers[0]) return get_nginx_conf_from_container(nginx_proxy_container)
def get_ip(self) -> str: def get_ip(self) -> str:
""" """
Return the nginx container ip address Return the nginx container ip address
""" """
nginx_proxy_containers = self.get_nginx_proxy_containers() nginx_proxy_container = self.get_nginx_proxy_container()
return container_ip(nginx_proxy_containers[0]) return container_ip(nginx_proxy_container)
def get(self, *args, **kwargs): def get(self, *args, **kwargs) -> Response:
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_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) -> Response:
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_predicate(backoff.constant, lambda r: r.status_code in (404, 502), 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) -> Response:
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_predicate(backoff.constant, lambda r: r.status_code in (404, 502), 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) -> Response:
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_predicate(backoff.constant, lambda r: r.status_code in (404, 502), 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) -> Response:
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_predicate(backoff.constant, lambda r: r.status_code in (404, 502), 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) -> Response:
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_predicate(backoff.constant, lambda r: r.status_code in (404, 502), 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)
def __getattr__(self, name): def __getattr__(self, name):
return getattr(requests, name) return getattr(requests, name)
def container_ip(container: Container): def container_ip(container: Container) -> str:
""" """
return the IP address of a container. return the IP address of a container.
@ -171,7 +179,7 @@ def container_ip(container: Container):
return net_info[network_name]["IPAddress"] return net_info[network_name]["IPAddress"]
def container_ipv6(container): def container_ipv6(container: Container) -> str:
""" """
return the IPv6 address of a container. return the IPv6 address of a container.
""" """
@ -188,7 +196,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_dns_resolver(domain_name: str) -> Optional[str]:
""" """
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.
@ -200,21 +208,21 @@ def nginx_proxy_dns_resolver(domain_name):
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.warning(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 None
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 docker_container_dns_resolver(domain_name): def docker_container_dns_resolver(domain_name: str) -> Optional[str]:
""" """
if domain name is of the form "XXX.container.docker" or "anything.XXX.container.docker", return the ip address of the docker container if domain name is of the form "XXX.container.docker" or "anything.XXX.container.docker",
named XXX. return the ip address of the docker container named XXX.
:return: IP or None :return: IP or None
""" """
@ -224,15 +232,15 @@ def docker_container_dns_resolver(domain_name):
match = re.search(r'(^|.+\.)(?P<container>[^.]+)\.container\.docker$', domain_name) match = re.search(r'(^|.+\.)(?P<container>[^.]+)\.container\.docker$', domain_name)
if not match: if not match:
log.debug(f"{domain_name!r} does not match") log.debug(f"{domain_name!r} does not match")
return return None
container_name = match.group('container') container_name = match.group('container')
log.debug(f"looking for container {container_name!r}") log.debug(f"looking for container {container_name!r}")
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 None
log.debug(f"container {container.name!r} found ({container.short_id})") log.debug(f"container {container.name!r} found ({container.short_id})")
ip = container_ip(container) ip = container_ip(container)
@ -244,7 +252,10 @@ 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 to 127.0.0.1 on Darwin.
see https://docs.docker.com/desktop/features/networking/#i-want-to-connect-to-a-container-from-the-host
""" """
prv_getaddrinfo = socket.getaddrinfo prv_getaddrinfo = socket.getaddrinfo
dns_cache = {} dns_cache = {}
@ -252,13 +263,18 @@ def monkey_patch_urllib_dns_resolver():
logging.getLogger('DNS').debug(f"resolving domain name {repr(args)}") logging.getLogger('DNS').debug(f"resolving domain name {repr(args)}")
_args = list(args) _args = list(args)
# Fail early when querying IP directly and it is forced ipv6 when not supported, # Fail early when querying IP directly, and it is forced ipv6 when not supported,
# Otherwise a pytest container not using the host network fails to pass `test_raw-ip-vhost`. # Otherwise a pytest container not using the host network fails to pass `test_raw-ip-vhost`.
if FORCE_CONTAINER_IPV6 and not HAS_IPV6: if FORCE_CONTAINER_IPV6 and not HAS_IPV6:
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
# Docker Desktop can't route traffic directly to Linux containers.
if platform.system() == "Darwin":
ip = "127.0.0.1"
if ip is None:
ip = nginx_proxy_dns_resolver(args[0])
if ip is None: 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:
@ -274,19 +290,12 @@ def monkey_patch_urllib_dns_resolver():
socket.getaddrinfo = new_getaddrinfo socket.getaddrinfo = new_getaddrinfo
return prv_getaddrinfo return prv_getaddrinfo
def restore_urllib_dns_resolver(getaddrinfo_func): def restore_urllib_dns_resolver(getaddrinfo_func):
socket.getaddrinfo = getaddrinfo_func socket.getaddrinfo = getaddrinfo_func
def remove_all_containers(): def get_nginx_conf_from_container(container: Container) -> bytes:
for container in docker_client.containers.list(all=True):
if PYTEST_RUNNING_IN_CONTAINER and container.name == test_container:
continue # pytest is running within a Docker container, so we do not want to remove that particular container
logging.info(f"removing container {container.name}")
container.remove(v=True, force=True)
def get_nginx_conf_from_container(container):
""" """
return the nginx /etc/nginx/conf.d/default.conf file content from a container return the nginx /etc/nginx/conf.d/default.conf file content from a container
""" """
@ -301,20 +310,40 @@ def get_nginx_conf_from_container(container):
return conffile.read() return conffile.read()
def docker_compose_up(compose_file='docker-compose.yml'): def __prepare_and_execute_compose_cmd(compose_files: List[str], project_name: str, cmd: str):
logging.info(f'{DOCKER_COMPOSE} -f {compose_file} up -d') """
Prepare and execute the Docker Compose command with the provided compose files and project name.
"""
compose_cmd = StringIO()
compose_cmd.write(DOCKER_COMPOSE)
compose_cmd.write(f" --project-name {project_name}")
for compose_file in compose_files:
compose_cmd.write(f" --file {compose_file}")
compose_cmd.write(f" {cmd}")
logging.info(compose_cmd.getvalue())
try: try:
subprocess.check_output(shlex.split(f'{DOCKER_COMPOSE} -f {compose_file} up -d'), stderr=subprocess.STDOUT) subprocess.check_output(shlex.split(compose_cmd.getvalue()), stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as e: 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 running '{compose_cmd.getvalue()}':\n{e.output}", pytrace=False)
def docker_compose_down(compose_file='docker-compose.yml'): def docker_compose_up(compose_files: List[str], project_name: str):
logging.info(f'{DOCKER_COMPOSE} -f {compose_file} down -v') """
try: Execute compose up --detach with the provided compose files and project name.
subprocess.check_output(shlex.split(f'{DOCKER_COMPOSE} -f {compose_file} down -v'), stderr=subprocess.STDOUT) """
except subprocess.CalledProcessError as e: if compose_files is None or len(compose_files) == 0:
pytest.fail(f"Error while runninng '{DOCKER_COMPOSE} -f {compose_file} down -v':\n{e.output}", pytrace=False) pytest.fail(f"No compose file passed to docker_compose_up", pytrace=False)
__prepare_and_execute_compose_cmd(compose_files, project_name, cmd="up --detach")
def docker_compose_down(compose_files: List[str], project_name: str):
"""
Execute compose down --volumes with the provided compose files and project name.
"""
if compose_files is None or len(compose_files) == 0:
pytest.fail(f"No compose file passed to docker_compose_up", pytrace=False)
__prepare_and_execute_compose_cmd(compose_files, project_name, cmd="down --volumes")
def wait_for_nginxproxy_to_be_ready(): def wait_for_nginxproxy_to_be_ready():
@ -333,35 +362,50 @@ def wait_for_nginxproxy_to_be_ready():
@pytest.fixture @pytest.fixture
def docker_compose_file(request): def docker_compose_files(request: FixtureRequest) -> List[str]:
"""Fixture naming the docker compose file to consider. """Fixture returning the docker compose files to consider:
If a YAML file exists with the same name as the test module (with the `.py` extension replaced If a YAML file exists with the same name as the test module (with the `.py` extension
with `.yml` or `.yaml`), use that. Otherwise, use `docker-compose.yml` in the same directory replaced with `.base.yml`, ie `test_foo.py`-> `test_foo.base.yml`) and in the same
as the test module. directory as the test module, use only that file.
Otherwise, merge the following files in this order:
- the `compose.base.yml` file in the parent `test` directory.
- if present in the same directory as the test module, the `compose.base.override.yml` file.
- the YAML file named after the current test module (ie `test_foo.py`-> `test_foo.yml`)
Tests can override this fixture to specify a custom location. Tests can override this fixture to specify a custom location.
""" """
test_module_dir = os.path.dirname(request.module.__file__) compose_files: List[str] = []
yml_file = os.path.join(test_module_dir, request.module.__name__ + '.yml') test_module_path = pathlib.Path(request.module.__file__).parent
yaml_file = os.path.join(test_module_dir, request.module.__name__ + '.yaml')
default_file = os.path.join(test_module_dir, 'docker-compose.yml')
if os.path.isfile(yml_file): module_base_file = test_module_path.joinpath(f"{request.module.__name__}.base.yml")
docker_compose_file = yml_file if module_base_file.is_file():
elif os.path.isfile(yaml_file): return [module_base_file.as_posix()]
docker_compose_file = yaml_file
else:
docker_compose_file = default_file
if not os.path.isfile(docker_compose_file): global_base_file = test_module_path.parent.joinpath("compose.base.yml")
logging.error("Could not find any docker compose file named either '{0}.yml', '{0}.yaml' or 'docker-compose.yml'".format(request.module.__name__)) if global_base_file.is_file():
compose_files.append(global_base_file.as_posix())
logging.debug(f"using docker compose file {docker_compose_file}") module_base_override_file = test_module_path.joinpath("compose.base.override.yml")
return docker_compose_file if module_base_override_file.is_file():
compose_files.append(module_base_override_file.as_posix())
module_compose_file = test_module_path.joinpath(f"{request.module.__name__}.yml")
if module_compose_file.is_file():
compose_files.append(module_compose_file.as_posix())
if not module_base_file.is_file() and not module_compose_file.is_file():
logging.error(
f"Could not find any docker compose file named '{module_base_file.name}' or '{module_compose_file.name}'"
)
logging.debug(f"using docker compose files {compose_files}")
return compose_files
def connect_to_network(network): def connect_to_network(network: Network) -> Optional[Network]:
""" """
If we are running from a container, connect our container to the given network If we are running from a container, connect our container to the given network
@ -371,8 +415,8 @@ 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 None
# figure out our container networks # figure out our container networks
my_networks = list(my_container.attrs["NetworkSettings"]["Networks"].keys()) my_networks = list(my_container.attrs["NetworkSettings"]["Networks"].keys())
@ -389,7 +433,7 @@ def connect_to_network(network):
return network return network
def disconnect_from_network(network=None): def disconnect_from_network(network: Network = None):
""" """
If we are running from a container, disconnect our container from the given network. If we are running from a container, disconnect our container from the given network.
@ -399,7 +443,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
@ -411,7 +455,7 @@ def disconnect_from_network(network=None):
network.disconnect(my_container) network.disconnect(my_container)
def connect_to_all_networks(): def connect_to_all_networks() -> List[Network]:
""" """
If we are running from a container, connect our container to all current docker networks. If we are running from a container, connect our container to all current docker networks.
@ -427,31 +471,34 @@ def connect_to_all_networks():
class DockerComposer(contextlib.AbstractContextManager): class DockerComposer(contextlib.AbstractContextManager):
def __init__(self): def __init__(self):
self._docker_compose_file = None self._networks = None
self._docker_compose_files = None
self._project_name = None
def __exit__(self, *exc_info): def __exit__(self, *exc_info):
self._down() self._down()
def _down(self): def _down(self):
if self._docker_compose_file is None: if self._docker_compose_files is None:
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._docker_compose_files, self._project_name)
self._docker_compose_file = None self._docker_compose_file = None
self._project_name = None
def compose(self, docker_compose_file): def compose(self, docker_compose_files: List[str], project_name: str):
if docker_compose_file == self._docker_compose_file: if docker_compose_files == self._docker_compose_files and project_name == self._project_name:
return return
self._down() self._down()
if docker_compose_file is None: if docker_compose_files is None or project_name is None:
return return
remove_all_containers() docker_compose_up(docker_compose_files, project_name)
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 time.sleep(3) # give time to containers to be ready
self._docker_compose_file = docker_compose_file self._docker_compose_files = docker_compose_files
self._project_name = project_name
############################################################################### ###############################################################################
@ -462,14 +509,14 @@ class DockerComposer(contextlib.AbstractContextManager):
@pytest.fixture(scope="module") @pytest.fixture(scope="module")
def docker_composer(): def docker_composer() -> Iterator[DockerComposer]:
with DockerComposer() as d: with DockerComposer() as d:
yield d yield d
@pytest.fixture @pytest.fixture
def ca_root_certificate(): def ca_root_certificate() -> str:
return CA_ROOT_CERTIFICATE return CA_ROOT_CERTIFICATE.as_posix()
@pytest.fixture @pytest.fixture
@ -480,25 +527,38 @@ def monkey_patched_dns():
@pytest.fixture @pytest.fixture
def docker_compose(monkey_patched_dns, docker_composer, docker_compose_file): def docker_compose(
"""Ensures containers described in a docker compose file are started. request: FixtureRequest,
monkeypatch,
A custom docker compose file name can be specified by overriding the `docker_compose_file` monkey_patched_dns,
fixture. docker_composer,
docker_compose_files
Also, in the case where pytest is running from a docker container, this fixture makes sure ) -> Iterator[DockerClient]:
our container will be attached to all the docker networks.
""" """
docker_composer.compose(docker_compose_file) Ensures containers necessary for the test module are started in a compose project,
and set the environment variable `PYTEST_MODULE_PATH` to the test module's parent folder.
A list of custom docker compose files path can be specified by overriding
the `docker_compose_file` fixture.
Also, in the case where pytest is running from a docker container, this fixture
makes sure our container will be attached to all the docker networks.
"""
pytest_module_path = pathlib.Path(request.module.__file__).parent
monkeypatch.setenv("PYTEST_MODULE_PATH", pytest_module_path.as_posix())
project_name = request.module.__name__
docker_composer.compose(docker_compose_files, project_name)
yield docker_client yield docker_client
@pytest.fixture() @pytest.fixture
def nginxproxy(): def nginxproxy() -> Iterator[RequestsForDocker]:
""" """
Provides the `nginxproxy` object that can be used in the same way the requests module is: Provides the `nginxproxy` object that can be used in the same way the requests module is:
r = nginxproxy.get("http://foo.com") r = nginxproxy.get("https://foo.com")
The difference is that in case an HTTP requests has status code 404 or 502 (which mostly The difference is that in case an HTTP requests has status code 404 or 502 (which mostly
indicates that nginx has just reloaded), we retry up to 30 times the query. indicates that nginx has just reloaded), we retry up to 30 times the query.
@ -507,23 +567,29 @@ def nginxproxy():
made against containers to use the containers IPv6 address when set to `True`. If IPv6 is not made against containers to use the containers IPv6 address when set to `True`. If IPv6 is not
supported by the system or docker, that particular test will be skipped. supported by the system or docker, that particular test will be skipped.
""" """
yield requests_for_docker() yield RequestsForDocker()
@pytest.fixture
def acme_challenge_path() -> str:
"""
Provides fake Let's Encrypt ACME challenge path used in certain tests
"""
return ".well-known/acme-challenge/test-filename"
############################################################################### ###############################################################################
# #
# Py.test hooks # Py.test hooks
# #
############################################################################### ###############################################################################
# pytest hook to display additionnal stuff in test report # pytest hook to display additional 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): test_containers = docker_client.containers.list(all=True, filters={"ancestor": "nginxproxy/nginx-proxy:test"})
test_containers = docker_client.containers.list(all=True, filters={"ancestor": "nginxproxy/nginx-proxy:test"}) for container in test_containers:
for container in test_containers: report.longrepr.addsection('nginx-proxy logs', container.logs().decode())
report.longrepr.addsection('nginx-proxy logs', container.logs()) report.longrepr.addsection('nginx-proxy conf', get_nginx_conf_from_container(container).decode())
report.longrepr.addsection('nginx-proxy conf', get_nginx_conf_from_container(container))
# Py.test `incremental` marker, see http://stackoverflow.com/a/12579625/107049 # Py.test `incremental` marker, see http://stackoverflow.com/a/12579625/107049
@ -550,5 +616,5 @@ try:
except docker.errors.ImageNotFound: except docker.errors.ImageNotFound:
pytest.exit("The docker image 'nginxproxy/nginx-proxy:test' is missing") pytest.exit("The docker image 'nginxproxy/nginx-proxy:test' is missing")
if LooseVersion(docker.__version__) < LooseVersion("5.0.0"): if Version(docker.__version__) < Version("7.0.0"):
pytest.exit("This test suite is meant to work with the python docker module v5.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

@ -3,7 +3,7 @@
# # # #
# This script is meant to run the test suite from a Docker container. # # This script is meant to run the test suite from a Docker container. #
# # # #
# This is usefull when you want to run the test suite from Mac or # # This is useful when you want to run the test suite from Mac or #
# Docker Toolbox. # # Docker Toolbox. #
# # # #
############################################################################### ###############################################################################

View file

@ -1,9 +1,35 @@
FROM python:3.9 FROM python:3.12
ENV PYTEST_RUNNING_IN_CONTAINER=1 ENV PYTEST_RUNNING_IN_CONTAINER=1
COPY python-requirements.txt /requirements.txt COPY python-requirements.txt /requirements.txt
RUN pip install -r /requirements.txt RUN pip install -r /requirements.txt
# Add Docker's official GPG key
RUN apt-get update \
&& apt-get install -y \
ca-certificates \
curl \
&& install -m 0755 -d /etc/apt/keyrings \
&& curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc \
&& chmod a+r /etc/apt/keyrings/docker.asc
# Add the Docker repository to Apt sources
RUN echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
tee /etc/apt/sources.list.d/docker.list > /dev/null
# Install docker-ce-cli and docker-compose-plugin requirements for Pytest docker_compose fixture
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
docker-ce-cli \
docker-compose-plugin \
&& apt-get clean \
&& rm -r /var/lib/apt/lists/*
# Check if docker compose is available
RUN docker compose version
WORKDIR /test WORKDIR /test
ENTRYPOINT ["pytest"] ENTRYPOINT ["pytest"]

View file

@ -1,4 +1,6 @@
backoff==2.2.1 backoff==2.2.1
docker==7.0.0 docker==7.1.0
pytest==7.4.3 packaging==24.2
requests==2.31.0 pytest==8.3.4
requests==2.32.3
urllib3==2.3.0

View file

@ -1,6 +1,7 @@
# Docker Image running one (or multiple) webservers listening on all given ports from WEB_PORTS environment variable # Docker Image running one (or multiple) webservers listening on all given ports from WEB_PORTS environment variable
FROM python:3 FROM python:3-alpine
RUN apk add --no-cache bash
COPY ./webserver.py / COPY ./webserver.py /
COPY ./entrypoint.sh / COPY ./entrypoint.sh /
WORKDIR /opt WORKDIR /opt

View file

@ -5,11 +5,11 @@ trap '[ ${#PIDS[@]} -gt 0 ] && kill -TERM ${PIDS[@]}' TERM
declare -a PIDS declare -a PIDS
for port in $WEB_PORTS; do for port in $WEB_PORTS; do
echo starting a web server listening on port $port; echo starting a web server listening on port "$port";
/webserver.py $port & /webserver.py "$port" &
PIDS+=($!) PIDS+=($!)
done done
wait ${PIDS[@]} wait "${PIDS[@]}"
trap - TERM trap - TERM
wait ${PIDS[@]} wait "${PIDS[@]}"

View file

@ -14,8 +14,8 @@ class Handler(http.server.SimpleHTTPRequestHandler):
response_body += self.headers.as_string() response_body += self.headers.as_string()
elif self.path == "/port": elif self.path == "/port":
response_body += f"answer from port {PORT}\n" response_body += f"answer from port {PORT}\n"
elif re.match("/status/(\d+)", self.path): elif re.match(r"/status/(\d+)", self.path):
result = re.match("/status/(\d+)", self.path) result = re.match(r"/status/(\d+)", self.path)
response_code = int(result.group(1)) response_code = int(result.group(1))
response_body += f"answer with response code {response_code}\n" response_body += f"answer with response code {response_code}\n"
elif self.path == "/": elif self.path == "/":
@ -28,7 +28,7 @@ class Handler(http.server.SimpleHTTPRequestHandler):
self.send_header("Content-Type", "text/plain") self.send_header("Content-Type", "text/plain")
self.end_headers() self.end_headers()
if (len(response_body)): if len(response_body):
self.wfile.write(response_body.encode()) self.wfile.write(response_body.encode())
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -1 +0,0 @@
This directory contains tests that showcase scenarios known to break the expected behavior of nginx-proxy.

View file

@ -1,5 +0,0 @@
Test the behavior of nginx-proxy when restarted after deleting a certificate file is was using.
1. nginx-proxy is created with a virtual host having a certificate
1. while nginx-proxy is running, the certificate file is deleted
1. nginx-proxy is then restarted (without removing the container)

View file

@ -1,70 +0,0 @@
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: Feb 17 23:20:54 2017 GMT
Not After : Jul 5 23:20:54 2044 GMT
Subject: CN=web.nginx-proxy
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:b6:27:63:a5:c6:e8:f4:7a:94:0e:cc:a2:62:76:
6d:5d:33:6f:cf:19:fc:e7:e5:bb:0e:0e:d0:7c:4f:
73:4c:48:2b:17:d1:4d:d5:9f:42:08:73:84:54:8c:
86:d2:c5:da:59:01:3f:42:22:e0:36:f0:dc:ab:de:
0a:bd:26:2b:22:13:87:a6:1f:23:ef:0e:99:27:8b:
15:4a:1b:ef:93:c9:6b:91:de:a0:02:0c:62:bb:cc:
56:37:e8:25:92:c3:1f:f1:69:d8:7c:a8:33:e0:89:
ce:14:67:a0:39:77:88:91:e6:a3:07:97:90:22:88:
d0:79:18:63:fb:6f:7e:ee:2b:42:7e:23:f5:e7:da:
e9:ee:6a:fa:96:65:9f:e1:2b:15:49:c8:cd:2d:ce:
86:4f:2c:2a:67:79:bf:41:30:14:cc:f6:0f:14:74:
9e:b6:d3:d0:3b:f0:1b:b8:e8:19:2a:fd:d6:fd:dc:
4b:4e:65:7d:9b:bf:37:7e:2d:35:22:2e:74:90:ce:
41:35:3d:41:a0:99:db:97:1f:bf:3e:18:3c:48:fb:
da:df:c6:4e:4e:b9:67:b8:10:d5:a5:13:03:c4:b7:
65:e7:aa:f0:14:4b:d3:4d:ea:fe:8f:69:cf:50:21:
63:27:cf:9e:4c:67:15:7b:3f:3b:da:cb:17:80:61:
1e:25
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:web.nginx-proxy
Signature Algorithm: sha256WithRSAEncryption
09:31:be:db:4e:b0:b6:68:da:ae:5b:16:51:29:fc:9f:61:b6:
5a:2f:3c:35:ef:67:76:97:b0:34:4e:3b:b4:d6:88:19:4f:84:
2e:73:d3:c0:3a:4c:41:54:6c:bb:67:89:67:ad:25:55:d7:d4:
80:fe:a7:3f:3d:9e:f1:34:96:d8:da:5a:78:51:c0:63:f1:52:
29:35:55:f4:7d:70:1c:d3:96:62:7f:64:86:81:52:27:c4:c6:
10:13:c6:73:56:4d:32:d0:b3:c3:c8:2c:25:83:e4:2b:1d:d4:
74:30:e5:85:af:2d:b6:a5:6b:fe:5d:d3:3c:00:58:94:f4:6a:
f5:a6:1d:cf:f9:ed:d5:27:ed:13:24:b2:4f:2b:f3:b8:e4:af:
0c:1d:fe:e0:6a:01:5e:a2:44:ff:3e:96:fa:6c:39:a3:51:37:
f3:72:55:d8:2d:29:6e:de:95:b9:d8:e3:1e:65:a5:9c:0d:79:
2d:39:ab:c7:ac:16:b6:a5:71:4b:35:a4:6c:72:47:1b:72:9c:
67:58:c1:fc:f6:7f:a7:73:50:7b:d6:27:57:74:a1:31:38:a7:
31:e3:b9:d4:c9:45:33:ec:ed:16:cf:c5:bd:d0:03:b1:45:3f:
68:0d:91:5c:26:4e:37:05:74:ed:3e:75:5e:ca:5e:ee:e2:51:
4b:da:08:99
-----BEGIN CERTIFICATE-----
MIIC8zCCAdugAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwPzEfMB0GA1UECgwWbmdp
bngtcHJveHkgdGVzdCBzdWl0ZTEcMBoGA1UEAwwTd3d3Lm5naW54LXByb3h5LnRs
ZDAeFw0xNzAyMTcyMzIwNTRaFw00NDA3MDUyMzIwNTRaMBoxGDAWBgNVBAMMD3dl
Yi5uZ2lueC1wcm94eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALYn
Y6XG6PR6lA7MomJ2bV0zb88Z/Ofluw4O0HxPc0xIKxfRTdWfQghzhFSMhtLF2lkB
P0Ii4Dbw3KveCr0mKyITh6YfI+8OmSeLFUob75PJa5HeoAIMYrvMVjfoJZLDH/Fp
2HyoM+CJzhRnoDl3iJHmoweXkCKI0HkYY/tvfu4rQn4j9efa6e5q+pZln+ErFUnI
zS3Ohk8sKmd5v0EwFMz2DxR0nrbT0DvwG7joGSr91v3cS05lfZu/N34tNSIudJDO
QTU9QaCZ25cfvz4YPEj72t/GTk65Z7gQ1aUTA8S3Zeeq8BRL003q/o9pz1AhYyfP
nkxnFXs/O9rLF4BhHiUCAwEAAaMeMBwwGgYDVR0RBBMwEYIPd2ViLm5naW54LXBy
b3h5MA0GCSqGSIb3DQEBCwUAA4IBAQAJMb7bTrC2aNquWxZRKfyfYbZaLzw172d2
l7A0Tju01ogZT4Quc9PAOkxBVGy7Z4lnrSVV19SA/qc/PZ7xNJbY2lp4UcBj8VIp
NVX0fXAc05Zif2SGgVInxMYQE8ZzVk0y0LPDyCwlg+QrHdR0MOWFry22pWv+XdM8
AFiU9Gr1ph3P+e3VJ+0TJLJPK/O45K8MHf7gagFeokT/Ppb6bDmjUTfzclXYLSlu
3pW52OMeZaWcDXktOavHrBa2pXFLNaRsckcbcpxnWMH89n+nc1B71idXdKExOKcx
47nUyUUz7O0Wz8W90AOxRT9oDZFcJk43BXTtPnVeyl7u4lFL2giZ
-----END CERTIFICATE-----

View file

@ -1,27 +0,0 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAtidjpcbo9HqUDsyiYnZtXTNvzxn85+W7Dg7QfE9zTEgrF9FN
1Z9CCHOEVIyG0sXaWQE/QiLgNvDcq94KvSYrIhOHph8j7w6ZJ4sVShvvk8lrkd6g
Agxiu8xWN+glksMf8WnYfKgz4InOFGegOXeIkeajB5eQIojQeRhj+29+7itCfiP1
59rp7mr6lmWf4SsVScjNLc6GTywqZ3m/QTAUzPYPFHSettPQO/AbuOgZKv3W/dxL
TmV9m783fi01Ii50kM5BNT1BoJnblx+/Phg8SPva38ZOTrlnuBDVpRMDxLdl56rw
FEvTTer+j2nPUCFjJ8+eTGcVez872ssXgGEeJQIDAQABAoIBAGQCMFW+ZfyEqHGP
rMA+oUEAkqy0agSwPwky3QjDXlxNa0uCYSeebtTRB6CcHxHuCzm+04puN4gyqhW6
rU64fAoTivCMPGBuNWxekmvD9r+/YM4P2u4E+th9EgFT9f0kII+dO30FpKXtQzY0
xuWGWXcxl+T9M+eiEkPKPmq4BoqgTDo5ty7qDv0ZqksGotKFmdYbtSvgBAueJdwu
VWJvenI9F42ExBRKOW1aldiRiaYBCLiCVPKJtOg9iuOP9RHUL1SE8xy5I5mm78g3
a13ji3BNq3yS+VhGjQ7zDy1V1jGupLoJw4I7OThu8hy+B8Vt8EN/iqakufOkjlTN
xTJ33CkCgYEA5Iymg0NTjWk6aEkFa9pERjfUWqdVp9sWSpFFZZgi55n7LOx6ohi3
vuLim3is/gYfK2kU/kHGZZLPnT0Rdx0MbOB4XK0CAUlqtUd0IyO4jMZ06g4/kn3N
e2jLdCCIBoEQuLk4ELxj2mHsLQhEvDrg7nzU2WpTHHhvJbIbDWOAxhsCgYEAzAgv
rKpanF+QDf4yeKHxAj2rrwRksTw4Pe7ZK/bog/i+HIVDA70vMapqftHbual/IRrB
JL7hxskoJ/h9c1w4xkWDjqkSKz8/Ihr4dyPfWyGINWbx/rarT/m5MU5SarScoK7o
Xgb25x+W+61rtI+2JhVRGO86+JiAeT4LkAX88L8CgYAwHHug/jdEeXZWJakCfzwI
HBCT1M3vO+uBXvtg25ndb0i0uENIhDOJ93EEkW65Osis9r34mBgPocwaqZRXosHO
2aH8wF6/rpjL+HK2QvrCh7Rs4Pr494qeA/1wQLjhxaGjgToQK9hJTHvPLwJpLWvU
SGr2Ka+9Oo0LPmb7dorRKQKBgQCLsNcjOodLJMp2KiHYIdfmlt6itzlRd09yZ8Nc
rHHJWVagJEUbnD1hnbHIHlp3pSqbObwfMmlWNoc9xo3tm6hrZ1CJLgx4e5b3/Ms8
ltznge/F0DPDFsH3wZwfu+YFlJ7gDKCfL9l/qEsxCS0CtJobPOEHV1NivNbJK8ey
1ca19QKBgDTdMOUsobAmDEkPQIpxfK1iqYAB7hpRLi79OOhLp23NKeyRNu8FH9fo
G3DZ4xUi6hP2bwiYugMXDyLKfvxbsXwQC84kGF8j+bGazKNhHqEC1OpYwmaTB3kg
qL9cHbjWySeRdIsRY/eWmiKjUwmiO54eAe1HWUdcsuz8yM3xf636
-----END RSA PRIVATE KEY-----

View file

@ -1,17 +0,0 @@
version: "2"
services:
web:
image: web
expose:
- "81"
environment:
WEB_PORTS: 81
VIRTUAL_HOST: web.nginx-proxy
reverseproxy:
image: nginxproxy/nginx-proxy:test
container_name: reverseproxy
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./tmp_certs:/etc/nginx/certs:ro

View file

@ -1,72 +0,0 @@
import logging
import os
from os.path import join, isfile
from shutil import copy
from time import sleep
import pytest
from requests import ConnectionError
script_dir = os.path.dirname(__file__)
pytestmark = pytest.mark.xfail() # TODO delete this marker once those issues are fixed
@pytest.fixture(scope="module", autouse=True)
def certs():
"""
pytest fixture that provides cert and key files into the tmp_certs directory
"""
file_names = ("web.nginx-proxy.crt", "web.nginx-proxy.key")
logging.info("copying server cert and key files into tmp_certs")
for f_name in file_names:
copy(join(script_dir, "certs", f_name), join(script_dir, "tmp_certs"))
yield
logging.info("cleaning up the tmp_cert directory")
for f_name in file_names:
if isfile(join(script_dir, "tmp_certs", f_name)):
os.remove(join(script_dir, "tmp_certs", f_name))
###############################################################################
def test_unknown_virtual_host_is_503(docker_compose, nginxproxy):
r = nginxproxy.get("http://foo.nginx-proxy/")
assert r.status_code == 503
def test_http_web_is_301(docker_compose, nginxproxy):
r = nginxproxy.get("http://web.nginx-proxy/port", allow_redirects=False)
assert r.status_code == 301
def test_https_web_is_200(docker_compose, nginxproxy):
r = nginxproxy.get("https://web.nginx-proxy/port")
assert r.status_code == 200
assert "answer from port 81\n" in r.text
@pytest.mark.incremental
def test_delete_cert_and_restart_reverseproxy(docker_compose):
os.remove(join(script_dir, "tmp_certs", "web.nginx-proxy.crt"))
docker_compose.containers.get("reverseproxy").restart()
sleep(3) # give time for the container to initialize
assert "running" == docker_compose.containers.get("reverseproxy").status
@pytest.mark.incremental
def test_unknown_virtual_host_is_still_503(nginxproxy):
r = nginxproxy.get("http://foo.nginx-proxy/")
assert r.status_code == 503
@pytest.mark.incremental
def test_http_web_is_now_200(nginxproxy):
r = nginxproxy.get("http://web.nginx-proxy/port", allow_redirects=False)
assert r.status_code == 200
assert "answer from port 81\n" == r.text
@pytest.mark.incremental
def test_https_web_is_now_broken_since_there_is_no_cert(nginxproxy):
with pytest.raises(ConnectionError):
nginxproxy.get("https://web.nginx-proxy/port")

View file

@ -1,2 +0,0 @@
*
!.gitignore

View file

@ -0,0 +1 @@
challenge-teststring

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 10 00:08:52 2017 GMT
Not After : May 28 00:08:52 2044 GMT
Subject: CN=*.nginx-proxy.tld
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:cb:45:f4:14:9b:fe:64:85:79:4a:36:8d:3d:d1:
27:d0:7c:36:28:30:e6:73:80:6f:7c:49:23:d0:6c:
17:e4:44:c0:77:4d:9a:c2:bc:24:84:e3:a5:4d:ba:
d2:da:51:7b:a1:2a:12:d4:c0:19:55:69:2c:22:27:
2d:1a:f6:fc:4b:7f:e9:cb:a8:3c:e8:69:b8:d2:4f:
de:4e:50:e2:d0:74:30:7c:42:5a:ae:aa:85:a5:b1:
71:4d:c9:7e:86:8b:62:8c:3e:0d:e3:3b:c3:f5:81:
0b:8c:68:79:fe:bf:10:fb:ae:ec:11:49:6d:64:5e:
1a:7d:b3:92:93:4e:96:19:3a:98:04:a7:66:b2:74:
61:2d:41:13:0c:a4:54:0d:2c:78:fd:b4:a3:e8:37:
78:9a:de:fa:bc:2e:a8:0f:67:14:58:ce:c3:87:d5:
14:0e:8b:29:7d:48:19:b2:a9:f5:b4:e8:af:32:21:
67:15:7e:43:52:8b:20:cf:9f:38:43:bf:fd:c8:24:
7f:52:a3:88:f2:f1:4a:14:91:2a:6e:91:6f:fb:7d:
6a:78:c6:6d:2e:dd:1e:4c:2b:63:bb:3a:43:9c:91:
f9:df:d3:08:13:63:86:7d:ce:e8:46:cf:f1:6c:1f:
ca:f7:4c:de:d8:4b:e0:da:bc:06:d9:87:0f:ff:96:
45:85
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:*.nginx-proxy.tld
Signature Algorithm: sha256WithRSAEncryption
6e:a5:0e:e4:d3:cc:d5:b7:fc:34:75:89:4e:98:8c:e7:08:06:
a8:5b:ec:13:7d:83:99:a2:61:b8:d5:12:6e:c5:b4:53:4e:9a:
22:cd:ad:14:30:6a:7d:58:d7:23:d9:a4:2a:96:a0:40:9e:50:
9f:ce:f2:fe:8c:dd:9a:ac:99:39:5b:89:2d:ca:e5:3e:c3:bc:
03:04:1c:12:d9:6e:b8:9f:f0:3a:be:12:44:7e:a4:21:86:73:
af:d5:00:51:3f:2c:56:70:34:8f:26:b0:7f:b0:cf:cf:7f:f9:
40:6f:00:29:c4:cf:c3:b7:c2:49:3d:3f:b0:26:78:87:b9:c7:
6c:1b:aa:6a:1a:dd:c5:eb:f2:69:ba:6d:46:0b:92:49:b5:11:
3c:eb:48:c7:2f:fb:33:a6:6a:82:a2:ab:f8:1e:5f:7d:e3:b7:
f2:fd:f5:88:a5:09:4d:a0:bc:f4:3b:cd:d2:8b:d7:57:1f:86:
3b:d2:3e:a4:92:21:b0:02:0b:e9:e0:c4:1c:f1:78:e2:58:a7:
26:5f:4c:29:c8:23:f0:6e:12:3f:bd:ad:44:7b:0b:bd:db:ba:
63:8d:07:c6:9d:dc:46:cc:63:40:ba:5e:45:82:dd:9a:e5:50:
e8:e7:d7:27:88:fc:6f:1d:8a:e7:5c:49:28:aa:10:29:75:28:
c7:52:de:f9
-----BEGIN CERTIFICATE-----
MIIC9zCCAd+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwPzEfMB0GA1UECgwWbmdp
bngtcHJveHkgdGVzdCBzdWl0ZTEcMBoGA1UEAwwTd3d3Lm5naW54LXByb3h5LnRs
ZDAeFw0xNzAxMTAwMDA4NTJaFw00NDA1MjgwMDA4NTJaMBwxGjAYBgNVBAMMESou
bmdpbngtcHJveHkudGxkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
y0X0FJv+ZIV5SjaNPdEn0Hw2KDDmc4BvfEkj0GwX5ETAd02awrwkhOOlTbrS2lF7
oSoS1MAZVWksIictGvb8S3/py6g86Gm40k/eTlDi0HQwfEJarqqFpbFxTcl+hoti
jD4N4zvD9YELjGh5/r8Q+67sEUltZF4afbOSk06WGTqYBKdmsnRhLUETDKRUDSx4
/bSj6Dd4mt76vC6oD2cUWM7Dh9UUDospfUgZsqn1tOivMiFnFX5DUosgz584Q7/9
yCR/UqOI8vFKFJEqbpFv+31qeMZtLt0eTCtjuzpDnJH539MIE2OGfc7oRs/xbB/K
90ze2Evg2rwG2YcP/5ZFhQIDAQABoyAwHjAcBgNVHREEFTATghEqLm5naW54LXBy
b3h5LnRsZDANBgkqhkiG9w0BAQsFAAOCAQEAbqUO5NPM1bf8NHWJTpiM5wgGqFvs
E32DmaJhuNUSbsW0U06aIs2tFDBqfVjXI9mkKpagQJ5Qn87y/ozdmqyZOVuJLcrl
PsO8AwQcEtluuJ/wOr4SRH6kIYZzr9UAUT8sVnA0jyawf7DPz3/5QG8AKcTPw7fC
ST0/sCZ4h7nHbBuqahrdxevyabptRguSSbURPOtIxy/7M6ZqgqKr+B5ffeO38v31
iKUJTaC89DvN0ovXVx+GO9I+pJIhsAIL6eDEHPF44linJl9MKcgj8G4SP72tRHsL
vdu6Y40Hxp3cRsxjQLpeRYLdmuVQ6OfXJ4j8bx2K51xJKKoQKXUox1Le+Q==
-----END CERTIFICATE-----

View file

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAy0X0FJv+ZIV5SjaNPdEn0Hw2KDDmc4BvfEkj0GwX5ETAd02a
wrwkhOOlTbrS2lF7oSoS1MAZVWksIictGvb8S3/py6g86Gm40k/eTlDi0HQwfEJa
rqqFpbFxTcl+hotijD4N4zvD9YELjGh5/r8Q+67sEUltZF4afbOSk06WGTqYBKdm
snRhLUETDKRUDSx4/bSj6Dd4mt76vC6oD2cUWM7Dh9UUDospfUgZsqn1tOivMiFn
FX5DUosgz584Q7/9yCR/UqOI8vFKFJEqbpFv+31qeMZtLt0eTCtjuzpDnJH539MI
E2OGfc7oRs/xbB/K90ze2Evg2rwG2YcP/5ZFhQIDAQABAoIBAQCjAro2PNLJMfCO
fyjNRgmzu6iCmpR0U68T8GN0JPsT576g7e8J828l0pkhuIyW33lRSThIvLSUNf9a
dChL032H3lBTLduKVh4NKleQXnVFzaeEPoISSFVdButiAhAhPW4OIUVp0OfY3V+x
fac3j2nDLAfL5SKAtqZv363Py9m66EBYm5BmGTQqT/frQWeCEBvlErQef5RIaU8p
e2zMWgSNNojVai8U3nKNRvYHWeWXM6Ck7lCvkHhMF+RpbmCZuqhbEARVnehU/Jdn
QHJ3nxeA2OWpoWKXvAHtSnno49yxq1UIstiQvY+ng5C5i56UlB60UiU2NJ6doZkB
uQ7/1MaBAoGBAORdcFtgdgRALjXngFWhpCp0CseyUehn1KhxDCG+D1pJ142/ymcf
oJOzKJPMRNDdDUBMnR1GBfy7rmwvYevI/SMNy2Qs7ofcXPbdtwwvTCToZ1V9/54k
VfuPBFT+3QzWRvG1tjTV3E4L2VV3nrl2qNPhE5DlfIaU3nQq5Fl0HprJAoGBAOPf
MWOTGev61CdODO5KN3pLAoamiPs5lEUlz3kM3L1Q52YLITxNDjRj9hWBUATJZOS2
pLOoYRwmhD7vrnimMc41+NuuFX+4T7hWPc8uSuOxX0VijYtULyNRK57mncG1Fq9M
RMLbOJ7FD+8jdXNsSMqpQ+pxLJRX/A10O2fOQnbdAoGAL5hV4YWSM0KZHvz332EI
ER0MXiCJN7HkPZMKH0I4eu3m8hEmAyYxVndBnsQ1F37q0xrkqAQ/HTSUntGlS/og
4Bxw5pkCwegoq/77tpto+ExDtSrEitYx4XMmSPyxX4qNULU5m3tzJgUML+b1etwD
Rd2kMU/TC02dq4KBAy/TbRkCgYAl1xN5iJz+XenLGR/2liZ+TWR+/bqzlU006mF4
pZUmbv/uJxz+yYD5XDwqOA4UrWjuvhG9r9FoflDprp2XdWnB556KxG7XhcDfSJr9
A5/2DadXe1Ur9O/a+oi2228JEsxQkea9QPA3FVxfBtFjOHEiDlez39VaUP4PMeUH
iO3qlQKBgFQhdTb7HeYnApYIDHLmd1PvjRvp8XKR1CpEN0nkw8HpHcT1q1MUjQCr
iT6FQupULEvGmO3frQsgVeRIQDbEdZK3C5xCtn6qOw70sYATVf361BbTtidmU9yV
THFxwDSVLiVZgFryoY/NtAc27sVdJnGsPRjjaeVgALAsLbmZ1K/H
-----END RSA PRIVATE KEY-----

View file

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

View file

@ -0,0 +1,27 @@
def test_redirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web1.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
)
assert r.status_code == 301
def test_redirect_acme_challenge_location_enabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web2.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
)
assert r.status_code == 200
def test_noredirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web3.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
)
assert r.status_code == 404
def test_noredirect_acme_challenge_location_enabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web4.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
)
assert r.status_code == 200

View file

@ -0,0 +1,40 @@
services:
nginx-proxy:
environment:
ACME_HTTP_CHALLENGE_LOCATION: "false"
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"
ACME_HTTP_CHALLENGE_LOCATION: "true"
web3:
image: web
expose:
- "83"
environment:
WEB_PORTS: "83"
VIRTUAL_HOST: "web3.nginx-proxy.tld"
HTTPS_METHOD: noredirect
web4:
image: web
expose:
- "84"
environment:
WEB_PORTS: "84"
VIRTUAL_HOST: "web4.nginx-proxy.tld"
HTTPS_METHOD: noredirect
ACME_HTTP_CHALLENGE_LOCATION: "true"

View file

@ -0,0 +1,27 @@
def test_redirect_acme_challenge_location_enabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web1.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
)
assert r.status_code == 200
def test_redirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web2.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
)
assert r.status_code == 301
def test_noredirect_acme_challenge_location_enabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web3.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
)
assert r.status_code == 200
def test_noredirect_acme_challenge_location_disabled(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web4.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
)
assert r.status_code == 404

View file

@ -0,0 +1,36 @@
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"
ACME_HTTP_CHALLENGE_LOCATION: "false"
web3:
image: web
expose:
- "83"
environment:
WEB_PORTS: "83"
VIRTUAL_HOST: "web3.nginx-proxy.tld"
HTTPS_METHOD: noredirect
web4:
image: web
expose:
- "84"
environment:
WEB_PORTS: "84"
VIRTUAL_HOST: "web4.nginx-proxy.tld"
HTTPS_METHOD: noredirect
ACME_HTTP_CHALLENGE_LOCATION: "false"

View file

@ -0,0 +1,13 @@
def test_redirect_acme_challenge_location_legacy(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web1.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
)
assert r.status_code == 200
def test_noredirect_acme_challenge_location_legacy(docker_compose, nginxproxy, acme_challenge_path):
r = nginxproxy.get(
f"http://web2.nginx-proxy.tld/{acme_challenge_path}",
allow_redirects=False
)
assert r.status_code == 404

View file

@ -0,0 +1,21 @@
services:
nginx-proxy:
environment:
ACME_HTTP_CHALLENGE_LOCATION: "legacy"
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"
HTTPS_METHOD: noredirect

View file

@ -0,0 +1,66 @@
"""
Test that nginx-proxy-tester can build successfully
"""
import pathlib
import re
import docker
import pytest
client = docker.from_env()
@pytest.fixture(scope = "session")
def docker_build(request):
# Define Dockerfile path
current_file_path = pathlib.Path(__file__)
dockerfile_path = current_file_path.parent.parent.joinpath("requirements")
dockerfile_name = "Dockerfile-nginx-proxy-tester"
# Build the Docker image
image, logs = client.images.build(
path = dockerfile_path.as_posix(),
dockerfile = dockerfile_name,
rm = True, # Remove intermediate containers
tag = "nginx-proxy-tester-ci", # Tag for the built image
)
# Check for build success
for log in logs:
if "stream" in log:
print(log["stream"].strip())
if "error" in log:
raise Exception(log["error"])
def teardown():
# Clean up after teardown
client.images.remove(image.id, force=True)
request.addfinalizer(teardown)
# Return the image name
return "nginx-proxy-tester-ci"
def test_build_nginx_proxy_tester(docker_build):
assert docker_build == "nginx-proxy-tester-ci"
def test_run_nginx_proxy_tester(docker_build):
# Run the container with 'pytest -v' command to output version info
container = client.containers.run("nginx-proxy-tester-ci",
command = "pytest -V",
detach = True,
)
# Wait for the container to finish and get the exit code
result = container.wait()
exit_code = result.get("StatusCode", 1) # Default to 1 (error) if not found
# Get the output logs from the container
output = container.logs().decode("utf-8").strip()
# Clean up: Remove the container
container.remove()
# Assertions
assert exit_code == 0, "Container exited with a non-zero exit code"
assert re.search(r"pytest\s\d+\.\d+\.\d+", output)

View file

@ -1,10 +0,0 @@
import pytest
def test_unknown_virtual_host(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503
def test_forwards_to_whoami(docker_compose, nginxproxy):
r = nginxproxy.get("http://web.nginx-proxy.example/port")
assert r.status_code == 200
assert r.text == "answer from port 81\n"

View file

@ -1,15 +0,0 @@
version: "2"
services:
nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
web:
image: web
expose:
- "81"
environment:
WEB_PORTS: 81
VIRTUAL_HOST: web.nginx-proxy.example

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html>
<head>
<title>Maintenance</title>
<style>
html {
color-scheme: light dark;
}
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif;
}
</style>
</head>
<body>
<h1>Damn, there's some maintenance in progress.</h1>
<p>
Our apologies for this temporary inconvenience. Regular service
performance will be re-established shortly.
</p>
</body>
</html>

View file

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

View file

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

View file

@ -1,5 +1,3 @@
import pytest
def test_custom_default_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy): def test_custom_default_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/") r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503 assert r.status_code == 503

View file

@ -1,19 +1,16 @@
version: "2"
services: services:
nginx-proxy: nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings.conf:/etc/nginx/vhost.d/default_location:ro - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/default_location:ro
- ./my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/web3.nginx-proxy.example_location:ro - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/web3.nginx-proxy.example_location:ro
web1: web1:
image: web image: web
expose: expose:
- "81" - "81"
environment: environment:
WEB_PORTS: 81 WEB_PORTS: "81"
VIRTUAL_HOST: web1.nginx-proxy.example VIRTUAL_HOST: web1.nginx-proxy.example
web2: web2:
@ -21,7 +18,7 @@ services:
expose: expose:
- "82" - "82"
environment: environment:
WEB_PORTS: 82 WEB_PORTS: "82"
VIRTUAL_HOST: web2.nginx-proxy.example VIRTUAL_HOST: web2.nginx-proxy.example
web3: web3:
@ -29,5 +26,5 @@ services:
expose: expose:
- "83" - "83"
environment: environment:
WEB_PORTS: 83 WEB_PORTS: "83"
VIRTUAL_HOST: web3.nginx-proxy.example VIRTUAL_HOST: web3.nginx-proxy.example

View file

@ -1,5 +1,3 @@
import pytest
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy): def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/") r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503 assert r.status_code == 503

View file

@ -1,18 +1,15 @@
version: "2"
services: services:
nginx-proxy: nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings.conf:/etc/nginx/proxy.conf:ro - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/proxy.conf:ro
web1: web1:
image: web image: web
expose: expose:
- "81" - "81"
environment: environment:
WEB_PORTS: 81 WEB_PORTS: "81"
VIRTUAL_HOST: web1.nginx-proxy.example VIRTUAL_HOST: web1.nginx-proxy.example
web2: web2:
@ -20,5 +17,5 @@ services:
expose: expose:
- "82" - "82"
environment: environment:
WEB_PORTS: 82 WEB_PORTS: "82"
VIRTUAL_HOST: web2.nginx-proxy.example VIRTUAL_HOST: web2.nginx-proxy.example

View file

@ -1,5 +1,3 @@
import pytest
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy): def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/") r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503 assert r.status_code == 503
@ -12,6 +10,13 @@ def test_custom_conf_applies_to_web1(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_conf_applies_to_regex(docker_compose, nginxproxy):
r = nginxproxy.get("http://regex.foo.nginx-proxy.example/port")
assert r.status_code == 200
assert r.text == "answer from port 83\n"
assert "X-test" in r.headers
assert "bar" == r.headers["X-test"]
def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy): def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy):
r = nginxproxy.get("http://web2.nginx-proxy.example/port") r = nginxproxy.get("http://web2.nginx-proxy.example/port")
assert r.status_code == 200 assert r.status_code == 200

View file

@ -1,18 +1,16 @@
version: "2"
services: services:
nginx-proxy: nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example_location:ro - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example_location:ro
- ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430_location:ro
web1: web1:
image: web image: web
expose: expose:
- "81" - "81"
environment: environment:
WEB_PORTS: 81 WEB_PORTS: "81"
VIRTUAL_HOST: web1.nginx-proxy.example VIRTUAL_HOST: web1.nginx-proxy.example
web2: web2:
@ -20,5 +18,13 @@ services:
expose: expose:
- "82" - "82"
environment: environment:
WEB_PORTS: 82 WEB_PORTS: "82"
VIRTUAL_HOST: web2.nginx-proxy.example VIRTUAL_HOST: web2.nginx-proxy.example
regex:
image: web
expose:
- "83"
environment:
WEB_PORTS: "83"
VIRTUAL_HOST: ~^regex.*\.nginx-proxy\.example$

View file

@ -1,5 +1,3 @@
import pytest
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy): def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/") r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503 assert r.status_code == 503
@ -12,6 +10,13 @@ def test_custom_conf_applies_to_web1(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_conf_applies_to_regex(docker_compose, nginxproxy):
r = nginxproxy.get("http://regex.foo.nginx-proxy.example/port")
assert r.status_code == 200
assert r.text == "answer from port 83\n"
assert "X-test" in r.headers
assert "bar" == r.headers["X-test"]
def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy): def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy):
r = nginxproxy.get("http://web2.nginx-proxy.example/port") r = nginxproxy.get("http://web2.nginx-proxy.example/port")
assert r.status_code == 200 assert r.status_code == 200

View file

@ -1,18 +1,16 @@
version: "2"
services: services:
nginx-proxy: nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example:ro - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/vhost.d/web1.nginx-proxy.example:ro
- ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_bar.conf:/etc/nginx/vhost.d/561032515ede3ab3a015edfb244608b72409c430:ro
web1: web1:
image: web image: web
expose: expose:
- "81" - "81"
environment: environment:
WEB_PORTS: 81 WEB_PORTS: "81"
VIRTUAL_HOST: web1.nginx-proxy.example VIRTUAL_HOST: web1.nginx-proxy.example
web2: web2:
@ -20,5 +18,13 @@ services:
expose: expose:
- "82" - "82"
environment: environment:
WEB_PORTS: 82 WEB_PORTS: "82"
VIRTUAL_HOST: web2.nginx-proxy.example VIRTUAL_HOST: web2.nginx-proxy.example
regex:
image: web
expose:
- "83"
environment:
WEB_PORTS: "83"
VIRTUAL_HOST: ~^regex.*\.nginx-proxy\.example$

View file

@ -1,5 +1,3 @@
import pytest
def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy): def test_custom_conf_does_not_apply_to_unknown_vhost(docker_compose, nginxproxy):
r = nginxproxy.get("http://nginx-proxy/") r = nginxproxy.get("http://nginx-proxy/")
assert r.status_code == 503 assert r.status_code == 503

View file

@ -1,18 +1,15 @@
version: "2"
services: services:
nginx-proxy: nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - /var/run/docker.sock:/tmp/docker.sock:ro
- ./my_custom_proxy_settings.conf:/etc/nginx/conf.d/my_custom_proxy_settings.conf:ro - ${PYTEST_MODULE_PATH}/my_custom_proxy_settings_f00.conf:/etc/nginx/conf.d/my_custom_proxy_settings_f00.conf:ro
web1: web1:
image: web image: web
expose: expose:
- "81" - "81"
environment: environment:
WEB_PORTS: 81 WEB_PORTS: "81"
VIRTUAL_HOST: web1.nginx-proxy.example VIRTUAL_HOST: web1.nginx-proxy.example
web2: web2:
@ -20,5 +17,5 @@ services:
expose: expose:
- "82" - "82"
environment: environment:
WEB_PORTS: 82 WEB_PORTS: "82"
VIRTUAL_HOST: web2.nginx-proxy.example VIRTUAL_HOST: web2.nginx-proxy.example

View file

@ -0,0 +1,48 @@
import json
import pytest
def test_debug_endpoint_is_enabled_globally(docker_compose, nginxproxy):
r = nginxproxy.get("http://enabled.debug.nginx-proxy.example/nginx-proxy-debug")
assert r.status_code == 200
r = nginxproxy.get("http://stripped.debug.nginx-proxy.example/nginx-proxy-debug")
assert r.status_code == 200
def test_debug_endpoint_response_contains_expected_values(docker_compose, nginxproxy):
r = nginxproxy.get("http://enabled.debug.nginx-proxy.example/nginx-proxy-debug")
assert r.status_code == 200
try:
jsonResponse = json.loads(r.text)
except ValueError as err:
pytest.fail("Failed to parse debug endpoint response as JSON: %s" % err, pytrace=False)
assert jsonResponse["global"]["enable_debug_endpoint"] == "true"
assert jsonResponse["vhost"]["enable_debug_endpoint"] == True
def test_debug_endpoint_paths_stripped_if_response_too_long(docker_compose, nginxproxy):
r = nginxproxy.get("http://stripped.debug.nginx-proxy.example/nginx-proxy-debug")
assert r.status_code == 200
try:
jsonResponse = json.loads(r.text)
except ValueError as err:
pytest.fail("Failed to parse debug endpoint response as JSON: %s" % err, pytrace=False)
if "paths" in jsonResponse["vhost"]:
pytest.fail("Expected paths to be stripped from debug endpoint response", pytrace=False)
assert jsonResponse["warning"] == "Virtual paths configuration for this hostname is too large and has been stripped from response."
def test_debug_endpoint_hostname_replaced_by_warning_if_regexp(docker_compose, nginxproxy):
r = nginxproxy.get("http://regexp.foo.debug.nginx-proxy.example/nginx-proxy-debug")
assert r.status_code == 200
try:
jsonResponse = json.loads(r.text)
except ValueError as err:
pytest.fail("Failed to parse debug endpoint response as JSON: %s" % err, pytrace=False)
assert jsonResponse["vhost"]["hostname"] == "Hostname is a regexp and unsafe to include in the debug response."
def test_debug_endpoint_is_disabled_per_container(docker_compose, nginxproxy):
r = nginxproxy.get("http://disabled.debug.nginx-proxy.example/nginx-proxy-debug")
assert r.status_code == 404

View file

@ -0,0 +1,59 @@
services:
nginx-proxy:
environment:
DEBUG_ENDPOINT: "true"
debug_enabled:
image: web
expose:
- "81"
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: enabled.debug.nginx-proxy.example
debug_stripped:
image: web
expose:
- "82"
environment:
WEB_PORTS: "82"
VIRTUAL_HOST_MULTIPORTS: |-
stripped.debug.nginx-proxy.example:
"/1":
"/2":
"/3":
"/4":
"/5":
"/6":
"/7":
"/8":
"/9":
"/10":
"/11":
"/12":
"/13":
"/14":
"/15":
"/16":
"/17":
"/18":
"/19":
"/20":
debug_regexp:
image: web
expose:
- "84"
environment:
WEB_PORTS: "84"
VIRTUAL_HOST: ~^regexp.*\.debug.nginx-proxy.example
debug_disabled:
image: web
expose:
- "83"
environment:
WEB_PORTS: "83"
VIRTUAL_HOST: disabled.debug.nginx-proxy.example
labels:
com.github.nginx-proxy.nginx-proxy.debug-endpoint: "false"

View file

@ -0,0 +1,26 @@
import json
import pytest
def test_debug_endpoint_is_disabled_globally(docker_compose, nginxproxy):
r = nginxproxy.get("http://disabled1.debug.nginx-proxy.example/nginx-proxy-debug")
assert r.status_code == 404
r = nginxproxy.get("http://disabled2.debug.nginx-proxy.example/nginx-proxy-debug")
assert r.status_code == 404
def test_debug_endpoint_is_enabled_per_container(docker_compose, nginxproxy):
r = nginxproxy.get("http://enabled.debug.nginx-proxy.example/nginx-proxy-debug")
assert r.status_code == 200
def test_debug_endpoint_response_contains_expected_values(docker_compose, nginxproxy):
r = nginxproxy.get("http://enabled.debug.nginx-proxy.example/nginx-proxy-debug")
assert r.status_code == 200
try:
jsonResponse = json.loads(r.text)
except ValueError as err:
pytest.fail("Failed to parse debug endpoint response as JSON:: %s" % err, pytrace=False)
assert jsonResponse["global"]["enable_debug_endpoint"] == "false"
assert jsonResponse["vhost"]["enable_debug_endpoint"] == True

View file

@ -0,0 +1,27 @@
services:
debug_disabled1:
image: web
expose:
- "81"
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: disabled1.debug.nginx-proxy.example
debug_disabled2:
image: web
expose:
- "82"
environment:
WEB_PORTS: "82"
VIRTUAL_HOST: disabled2.debug.nginx-proxy.example
debug_enabled:
image: web
expose:
- "83"
environment:
WEB_PORTS: "83"
VIRTUAL_HOST: enabled.debug.nginx-proxy.example
labels:
com.github.nginx-proxy.nginx-proxy.debug-endpoint: "true"

View file

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

View file

@ -1,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

@ -0,0 +1,12 @@
services:
nginx-proxy:
environment:
DEFAULT_HOST: web1.tld
web1:
image: web
expose:
- "81"
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: web1.tld

View file

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

View file

@ -1,12 +1,16 @@
version: "2"
services: services:
nginx-proxy:
volumes:
- /var/run/docker.sock:/f00.sock:ro
environment:
DOCKER_HOST: unix:///f00.sock
web1: web1:
image: web image: web
expose: expose:
- "81" - "81"
environment: environment:
WEB_PORTS: 81 WEB_PORTS: "81"
VIRTUAL_HOST: web1.nginx-proxy.tld VIRTUAL_HOST: web1.nginx-proxy.tld
web2: web2:
@ -14,12 +18,5 @@ services:
expose: expose:
- "82" - "82"
environment: environment:
WEB_PORTS: 82 WEB_PORTS: "82"
VIRTUAL_HOST: web2.nginx-proxy.tld 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 +0,0 @@
nginx.tmpl

View file

@ -1,13 +1,18 @@
version: "3" volumes:
nginx_conf:
services: services:
nginx: nginx-proxy-nginx:
image: nginx image: nginx
container_name: nginx container_name: nginx
volumes: volumes:
- nginx_conf:/etc/nginx/conf.d - nginx_conf:/etc/nginx/conf.d:ro
ports:
- "80:80"
- "443:443"
dockergen: nginx-proxy-dockergen:
image: nginxproxy/docker-gen image: nginxproxy/docker-gen
command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
volumes: volumes:
@ -21,8 +26,5 @@ services:
expose: expose:
- "80" - "80"
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,11 +1,11 @@
import docker import docker
import pytest import pytest
from distutils.version import LooseVersion from packaging.version import Version
raw_version = docker.from_env().version()["Version"] raw_version = docker.from_env().version()["Version"]
pytestmark = pytest.mark.skipif( pytestmark = pytest.mark.skipif(
LooseVersion(raw_version) < LooseVersion("1.13"), Version(raw_version) < Version("1.13"),
reason="Docker compose syntax v3 requires docker engine v1.13 or later (got {raw_version})" reason="Docker compose syntax v3 requires docker engine v1.13 or later (got {raw_version})"
) )

View file

@ -1,10 +0,0 @@
def test_unknown_virtual_host_is_503(docker_compose, nginxproxy):
r = nginxproxy.get("http://unknown.nginx.container.docker/")
assert r.status_code == 503
def test_forwards_to_whoami(docker_compose, nginxproxy):
r = nginxproxy.get("http://whoami.nginx.container.docker/")
assert r.status_code == 200
whoami_container = docker_compose.containers.get("whoami")
assert r.text == f"I'm {whoami_container.id[:12]}\n"

View file

@ -1,26 +0,0 @@
version: "2"
services:
nginx:
image: nginx
container_name: nginx
volumes:
- /etc/nginx/conf.d
dockergen:
image: nginxproxy/docker-gen
command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
volumes_from:
- nginx
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ../../nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl
web:
image: web
container_name: whoami
expose:
- "80"
environment:
WEB_PORTS: 80
VIRTUAL_HOST: whoami.nginx.container.docker

View file

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

View file

@ -0,0 +1,40 @@
services:
nginx-proxy:
environment:
ENABLE_HTTP_ON_MISSING_CERT: "false"
nohttp-missing-cert-disabled:
image: web
expose:
- "81"
environment:
WEB_PORTS: "81"
VIRTUAL_HOST: nohttp-missing-cert-disabled.nginx-proxy.tld
HTTPS_METHOD: nohttp
nohttp-missing-cert-enabled:
image: web
expose:
- "82"
environment:
WEB_PORTS: "82"
VIRTUAL_HOST: nohttp-missing-cert-enabled.nginx-proxy.tld
HTTPS_METHOD: nohttp
ENABLE_HTTP_ON_MISSING_CERT: "true"
redirect-missing-cert-disabled:
image: web
expose:
- "83"
environment:
WEB_PORTS: "83"
VIRTUAL_HOST: redirect-missing-cert-disabled.nginx-proxy.tld
redirect-missing-cert-enabled:
image: web
expose:
- "84"
environment:
WEB_PORTS: "84"
VIRTUAL_HOST: redirect-missing-cert-enabled.nginx-proxy.tld
ENABLE_HTTP_ON_MISSING_CERT: "true"

View file

@ -7,7 +7,7 @@ import pytest
from docker.errors import NotFound from docker.errors import NotFound
@pytest.fixture() @pytest.fixture
def web1(docker_compose): def web1(docker_compose):
""" """
pytest fixture creating a web container with `VIRTUAL_HOST=web1.nginx-proxy` listening on port 81. pytest fixture creating a web container with `VIRTUAL_HOST=web1.nginx-proxy` listening on port 81.
@ -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("test_events-net").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:
@ -30,7 +30,7 @@ def web1(docker_compose):
except NotFound: except NotFound:
pass pass
@pytest.fixture() @pytest.fixture
def web2(docker_compose): def web2(docker_compose):
""" """
pytest fixture creating a web container with `VIRTUAL_HOST=nginx-proxy`, `VIRTUAL_PATH=/web2/` and `VIRTUAL_DEST=/` listening on port 82. pytest fixture creating a web container with `VIRTUAL_HOST=nginx-proxy`, `VIRTUAL_PATH=/web2/` and `VIRTUAL_DEST=/` listening on port 82.
@ -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("test_events-net").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:

View file

@ -0,0 +1,3 @@
networks:
default:
name: test_events-net

View file

@ -1,17 +0,0 @@
version: "2"
services:
sut:
image: nginxproxy/nginx-proxy:test
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./custom-fallback.conf:/etc/nginx/conf.d/zzz-custom-fallback.conf:ro
http-only:
image: web
expose:
- "83"
environment:
WEB_PORTS: "83"
VIRTUAL_HOST: http-only.nginx-proxy.test
HTTPS_METHOD: nohttps

View file

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

View file

@ -1,12 +1,8 @@
version: "2"
services: services:
sut: nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - /var/run/docker.sock:/tmp/docker.sock:ro
environment: - ${PYTEST_MODULE_PATH}/test_fallback.data/custom-fallback.conf:/etc/nginx/conf.d/zzz-custom-fallback.conf:ro
HTTPS_METHOD: nohttps
http-only: http-only:
image: web image: web
@ -15,3 +11,4 @@ services:
environment: environment:
WEB_PORTS: "83" WEB_PORTS: "83"
VIRTUAL_HOST: http-only.nginx-proxy.test VIRTUAL_HOST: http-only.nginx-proxy.test
HTTPS_METHOD: nohttps

View file

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

View file

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

View file

@ -1,11 +1,8 @@
version: "2"
services: services:
sut: nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro - ${PYTEST_MODULE_PATH}/test_fallback.data/withdefault.certs:/etc/nginx/certs:ro
environment: environment:
HTTPS_METHOD: nohttp HTTPS_METHOD: nohttp
@ -24,3 +21,13 @@ services:
environment: environment:
WEB_PORTS: "84" WEB_PORTS: "84"
VIRTUAL_HOST: missing-cert.nginx-proxy.test VIRTUAL_HOST: missing-cert.nginx-proxy.test
missing-cert-default-untrusted:
image: web
expose:
- "85"
environment:
WEB_PORTS: "85"
VIRTUAL_HOST: missing-cert.default-untrusted.nginx-proxy.test
labels:
com.github.nginx-proxy.nginx-proxy.trust-default-cert: "false"

View file

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

View file

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

View file

@ -0,0 +1,12 @@
services:
nginx-proxy:
environment:
HTTPS_METHOD: nohttps
http-only:
image: web
expose:
- "83"
environment:
WEB_PORTS: "83"
VIRTUAL_HOST: http-only.nginx-proxy.test

View file

@ -1,11 +1,10 @@
version: "2"
services: services:
sut: nginx-proxy:
image: nginxproxy/nginx-proxy:test
volumes: volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro - /var/run/docker.sock:/tmp/docker.sock:ro
- ./withdefault.certs:/etc/nginx/certs:ro - ${PYTEST_MODULE_PATH}/test_fallback.data/withdefault.certs:/etc/nginx/certs:ro
environment:
TRUST_DEFAULT_CERT: "false"
https-and-http: https-and-http:
image: web image: web

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