diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index cfaa367..d09ea82 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,9 +1,5 @@ # !!!PLEASE READ!!! -## Questions - -If you have a question, DO NOT SUBMIT a new issue. Please ask the question on the Q&A Group: https://groups.google.com/forum/#!forum/nginx-proxy - ## Bugs or Features If you are logging a bug or feature request, please search the current open issues to see if there is already a bug or feature opened. diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..d99307f --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + + # Maintain dependencies for Docker + - package-ecosystem: "docker" + directory: "/" + schedule: + interval: "daily" + labels: + - "area/chore" + - "area/dockerfile" diff --git a/.github/workflows/dockerhub.yml b/.github/workflows/dockerhub.yml new file mode 100644 index 0000000..8eaacf7 --- /dev/null +++ b/.github/workflows/dockerhub.yml @@ -0,0 +1,114 @@ +name: DockerHub + +on: + workflow_dispatch: + schedule: + - cron: '0 0 * * 1' + push: + branches: + - main + tags: + - '*.*.*' + paths-ignore: + - 'test/*' + - '.gitignore' + - '.travis.yml' + - 'docker-compose-separate-containers.yml' + - 'docker-compose.yml' + - 'LICENSE' + - 'Makefile' + - '*.md' + +jobs: + multiarch-build-debian: + runs-on: ubuntu-latest + steps: + + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Get Docker tags for Debian based image + id: docker_meta_debian + uses: crazy-max/ghaction-docker-meta@v2 + with: + images: | + nginxproxy/nginx-proxy + jwilder/nginx-proxy + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push the Debian based image + id: docker_build_debian + uses: docker/build-push-action@v2 + with: + file: Dockerfile + platforms: linux/amd64,linux/arm64,linux/arm/v7 + push: true + tags: ${{ steps.docker_meta_debian.outputs.tags }} + labels: ${{ steps.docker_meta_debian.outputs.labels }} + + - name: Images digests + run: echo ${{ steps.docker_build_debian.outputs.digest }} + + multiarch-build-alpine: + runs-on: ubuntu-latest + steps: + + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Get Docker tags for Alpine based image + id: docker_meta_alpine + uses: crazy-max/ghaction-docker-meta@v2 + with: + images: | + nginxproxy/nginx-proxy + jwilder/nginx-proxy + tags: | + type=semver,suffix=-alpine,pattern={{version}} + type=semver,suffix=-alpine,pattern={{major}}.{{minor}} + type=raw,value=alpine,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }} + flavor: latest=false + + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v1 + + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push the Alpine based image + id: docker_build_alpine + uses: docker/build-push-action@v2 + with: + file: Dockerfile.alpine + platforms: linux/amd64,linux/arm64,linux/arm/v7 + push: true + tags: ${{ steps.docker_meta_alpine.outputs.tags }} + labels: ${{ steps.docker_meta_alpine.outputs.labels }} + + - name: Images digests + run: echo ${{ steps.docker_build_alpine.outputs.digest }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..cde7ff3 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,37 @@ +name: Test + +on: [push, pull_request] + +jobs: + unit: + name: Unit Test + runs-on: ubuntu-latest + + strategy: + fail-fast: true + matrix: + base_docker_image: [alpine, debian] + + steps: + - uses: actions/checkout@v2 + + - name: Set up Python 3.9 + uses: actions/setup-python@v2 + with: + python-version: 3.9 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r python-requirements.txt + working-directory: test/requirements + + - name: Build Docker web server image + run: make build-webserver + + - name: Build Docker nginx proxy test image + run: make build-nginx-proxy-test-${{ matrix.base_docker_image }} + + - name: Run tests + run: pytest + working-directory: test \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 7a1c66f..0000000 --- a/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -dist: trusty -sudo: required - -env: - matrix: - - TEST_TARGET: test-debian - - TEST_TARGET: test-alpine - -before_install: - - sudo apt-get -y remove docker docker-engine docker-ce - - sudo rm /etc/apt/sources.list.d/docker.list - - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - - - sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" - - sudo apt-get update - - sudo apt-get -y install docker-ce - - docker version - - docker info - # prepare docker test requirements - - make update-dependencies - -script: - - make $TEST_TARGET diff --git a/Dockerfile b/Dockerfile index c528481..7206c5f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,46 @@ -FROM nginx:1.19.3 -LABEL maintainer="Jason Wilder mail@jasonwilder.com" +# setup build arguments for version of dependencies to use +ARG DOCKER_GEN_VERSION=0.7.6 +ARG FOREGO_VERSION=0.16.1 + +# Use a specific version of golang to build both binaries +FROM golang:1.15.10 as gobuilder + +# Build docker-gen from scratch +FROM gobuilder as dockergen + +ARG DOCKER_GEN_VERSION + +RUN git clone https://github.com/jwilder/docker-gen \ + && cd /go/docker-gen \ + && git -c advice.detachedHead=false checkout $DOCKER_GEN_VERSION \ + && go mod download \ + && CGO_ENABLED=0 GOOS=linux go build -ldflags "-X main.buildVersion=${DOCKER_GEN_VERSION}" ./cmd/docker-gen \ + && go clean -cache \ + && mv docker-gen /usr/local/bin/ \ + && cd - \ + && rm -rf /go/docker-gen + +# Build forego from scratch +# Because this relies on golang workspaces, we need to use go < 1.8. +FROM gobuilder as forego + +# Download the sources for the given version +ARG FOREGO_VERSION +ADD https://github.com/jwilder/forego/archive/v${FOREGO_VERSION}.tar.gz sources.tar.gz + +# Move the sources into the right directory +RUN tar -xzf sources.tar.gz && \ + mkdir -p /go/src/github.com/ddollar/ && \ + mv forego-* /go/src/github.com/ddollar/forego + +# Install the dependencies and make the forego executable +WORKDIR /go/src/github.com/ddollar/forego/ +RUN go get -v ./... && \ + CGO_ENABLED=0 GOOS=linux go build -o forego . + +# Build the final image +FROM nginx:1.19.10 +LABEL maintainer="Nicolas Duchon (@buchdag)" # Install wget and install/updates certificates RUN apt-get update \ @@ -12,17 +53,17 @@ RUN apt-get update \ # Configure Nginx and apply fix for very long server names RUN echo "daemon off;" >> /etc/nginx/nginx.conf \ - && sed -i 's/worker_processes 1/worker_processes auto/' /etc/nginx/nginx.conf + && sed -i 's/worker_processes 1/worker_processes auto/' /etc/nginx/nginx.conf \ + && sed -i 's/worker_connections 1024/worker_connections 10240/' /etc/nginx/nginx.conf -# Install Forego -ADD https://github.com/jwilder/forego/releases/download/v0.16.1/forego /usr/local/bin/forego -RUN chmod u+x /usr/local/bin/forego +# Install Forego + docker-gen +COPY --from=forego /go/src/github.com/ddollar/forego/forego /usr/local/bin/forego +COPY --from=dockergen /usr/local/bin/docker-gen /usr/local/bin/docker-gen -ENV DOCKER_GEN_VERSION 0.7.4 - -RUN wget https://github.com/jwilder/docker-gen/releases/download/$DOCKER_GEN_VERSION/docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \ - && tar -C /usr/local/bin -xvzf docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \ - && rm /docker-gen-linux-amd64-$DOCKER_GEN_VERSION.tar.gz +# Add DOCKER_GEN_VERSION environment variable +# Because some external projects rely on it +ARG DOCKER_GEN_VERSION +ENV DOCKER_GEN_VERSION=${DOCKER_GEN_VERSION} COPY network_internal.conf /etc/nginx/ diff --git a/Dockerfile.alpine b/Dockerfile.alpine index 4b5545b..97856fb 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -1,5 +1,46 @@ -FROM nginx:1.19.3-alpine -LABEL maintainer="Jason Wilder mail@jasonwilder.com" +# setup build arguments for version of dependencies to use +ARG DOCKER_GEN_VERSION=0.7.6 +ARG FOREGO_VERSION=0.16.1 + +# Use a specific version of golang to build both binaries +FROM golang:1.15.10-alpine as gobuilder +RUN apk add --no-cache git + +# Build docker-gen from scratch +FROM gobuilder as dockergen + +ARG DOCKER_GEN_VERSION + +RUN git clone https://github.com/jwilder/docker-gen \ + && cd /go/docker-gen \ + && git -c advice.detachedHead=false checkout $DOCKER_GEN_VERSION \ + && go mod download \ + && CGO_ENABLED=0 go build -ldflags "-X main.buildVersion=${DOCKER_GEN_VERSION}" ./cmd/docker-gen \ + && go clean -cache \ + && mv docker-gen /usr/local/bin/ \ + && cd - \ + && rm -rf /go/docker-gen + +# Build forego from scratch +FROM gobuilder as forego + +# Download the sources for the given version +ARG FOREGO_VERSION +ADD https://github.com/jwilder/forego/archive/v${FOREGO_VERSION}.tar.gz sources.tar.gz + +# Move the sources into the right directory +RUN tar -xzf sources.tar.gz && \ + mkdir -p /go/src/github.com/ddollar/ && \ + mv forego-* /go/src/github.com/ddollar/forego + +# Install the dependencies and make the forego executable +WORKDIR /go/src/github.com/ddollar/forego/ +RUN go get -v ./... && \ + CGO_ENABLED=0 GOOS=linux go build -o forego . + +# Build the final image +FROM nginx:1.19.10-alpine +LABEL maintainer="Nicolas Duchon (@buchdag)" # Install wget and install/updates certificates RUN apk add --no-cache --virtual .run-deps \ @@ -9,17 +50,17 @@ RUN apk add --no-cache --virtual .run-deps \ # Configure Nginx and apply fix for very long server names RUN echo "daemon off;" >> /etc/nginx/nginx.conf \ - && sed -i 's/worker_processes 1/worker_processes auto/' /etc/nginx/nginx.conf + && sed -i 's/worker_processes 1/worker_processes auto/' /etc/nginx/nginx.conf \ + && sed -i 's/worker_connections 1024/worker_connections 10240/' /etc/nginx/nginx.conf -# Install Forego -ADD https://github.com/jwilder/forego/releases/download/v0.16.1/forego /usr/local/bin/forego -RUN chmod u+x /usr/local/bin/forego +# Install Forego + docker-gen +COPY --from=forego /go/src/github.com/ddollar/forego/forego /usr/local/bin/forego +COPY --from=dockergen /usr/local/bin/docker-gen /usr/local/bin/docker-gen -ENV DOCKER_GEN_VERSION 0.7.4 - -RUN wget --quiet https://github.com/jwilder/docker-gen/releases/download/$DOCKER_GEN_VERSION/docker-gen-alpine-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \ - && tar -C /usr/local/bin -xvzf docker-gen-alpine-linux-amd64-$DOCKER_GEN_VERSION.tar.gz \ - && rm /docker-gen-alpine-linux-amd64-$DOCKER_GEN_VERSION.tar.gz +# Add DOCKER_GEN_VERSION environment variable +# Because some external projects rely on it +ARG DOCKER_GEN_VERSION +ENV DOCKER_GEN_VERSION=${DOCKER_GEN_VERSION} COPY network_internal.conf /etc/nginx/ diff --git a/Makefile b/Makefile index 5f965f7..18fcd33 100644 --- a/Makefile +++ b/Makefile @@ -2,15 +2,19 @@ .PHONY : test-debian test-alpine test -update-dependencies: - test/requirements/build.sh +build-webserver: + docker build -t web test/requirements/web -test-debian: update-dependencies - docker build -t jwilder/nginx-proxy:test . +build-nginx-proxy-test-debian: + docker build -t nginxproxy/nginx-proxy:test . + +build-nginx-proxy-test-alpine: + docker build -f Dockerfile.alpine -t nginxproxy/nginx-proxy:test . + +test-debian: build-webserver build-nginx-proxy-test-debian test/pytest.sh -test-alpine: update-dependencies - docker build -f Dockerfile.alpine -t jwilder/nginx-proxy:test . +test-alpine: build-webserver build-nginx-proxy-test-alpine test/pytest.sh test: test-debian test-alpine diff --git a/README.md b/README.md index 595b461..af93cdb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ -![latest 0.8.0](https://img.shields.io/badge/latest-0.8.0-green.svg?style=flat) -![nginx 1.19.3](https://img.shields.io/badge/nginx-1.19.3-brightgreen.svg) ![License MIT](https://img.shields.io/badge/license-MIT-blue.svg) [![Build Status](https://travis-ci.org/jwilder/nginx-proxy.svg?branch=master)](https://travis-ci.org/jwilder/nginx-proxy) [![](https://img.shields.io/docker/stars/jwilder/nginx-proxy.svg)](https://hub.docker.com/r/jwilder/nginx-proxy 'DockerHub') [![](https://img.shields.io/docker/pulls/jwilder/nginx-proxy.svg)](https://hub.docker.com/r/jwilder/nginx-proxy 'DockerHub') +[![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) +![nginx 1.19.10](https://img.shields.io/badge/nginx-1.19.10-brightgreen.svg) +[![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 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][1]. docker-gen generates reverse proxy configs for nginx and reloads nginx when containers are started and stopped. @@ -10,7 +14,7 @@ See [Automated Nginx Reverse Proxy for Docker][2] for why you might want to use To run it: - $ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy Then start any containers you want proxied with an env var `VIRTUAL_HOST=subdomain.youdomain.com` @@ -24,17 +28,17 @@ Provided your DNS is setup to forward foo.bar.com to the host running nginx-prox The nginx-proxy images are available in two flavors. -#### jwilder/nginx-proxy:latest +#### nginxproxy/nginx-proxy:latest -This image uses the debian:jessie based nginx image. +This image uses the debian:buster based nginx image. - $ docker pull jwilder/nginx-proxy:latest + $ docker pull nginxproxy/nginx-proxy:latest -#### jwilder/nginx-proxy:alpine +#### nginxproxy/nginx-proxy:alpine -This image is based on the nginx:alpine image. Use this image to fully support HTTP/2 (including ALPN required by recent Chrome versions). A valid certificate is required as well (see eg. below "SSL Support using letsencrypt" for more info). +This image is based on the nginx:alpine image. Use this image to fully support HTTP/2 (including ALPN required by recent Chrome versions). A valid certificate is required as well (see eg. below "SSL Support using an ACME CA" for more info). - $ docker pull jwilder/nginx-proxy:alpine + $ docker pull nginxproxy/nginx-proxy:alpine ### Docker Compose @@ -43,7 +47,7 @@ version: '2' services: nginx-proxy: - image: jwilder/nginx-proxy + image: nginxproxy/nginx-proxy ports: - "80:80" volumes: @@ -51,8 +55,11 @@ services: whoami: image: jwilder/whoami + expose: + - "8000" environment: - VIRTUAL_HOST=whoami.local + - VIRTUAL_PORT=8000 ``` ```shell @@ -65,7 +72,7 @@ I'm 5b129ab83266 You can activate the IPv6 support for the nginx-proxy container by passing the value `true` to the `ENABLE_IPV6` environment variable: - $ docker run -d -p 80:80 -e ENABLE_IPV6=true -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -e ENABLE_IPV6=true -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy #### Scoped IPv6 Resolvers @@ -98,7 +105,7 @@ If you want your `nginx-proxy` container to be attached to a different network, ```console $ docker run -d -p 80:80 -v /var/run/docker.sock:/tmp/docker.sock:ro \ - --name my-nginx-proxy --net my-network jwilder/nginx-proxy + --name my-nginx-proxy --net my-network nginxproxy/nginx-proxy $ docker network connect my-other-network my-nginx-proxy ``` @@ -119,7 +126,7 @@ allow 172.16.0.0/12; deny all; ``` -When internal-only access is enabled, external clients with be denied with an `HTTP 403 Forbidden` +When internal-only access is enabled, external clients will be denied with an `HTTP 403 Forbidden` > If there is a load-balancer / reverse proxy in front of `nginx-proxy` that hides the client IP (example: AWS Application/Elastic Load Balancer), you will need to use the nginx `realip` module (already installed) to extract the client's IP from the HTTP request headers. Please see the [nginx realip module configuration](http://nginx.org/en/docs/http/ngx_http_realip_module.html) for more details. This configuration can be added to a new config file and mounted in `/etc/nginx/conf.d/`. @@ -150,8 +157,11 @@ If you use fastcgi,you can set `VIRTUAL_ROOT=xxx` for your root directory To set the default host for nginx use the env var `DEFAULT_HOST=foo.bar.com` for example - $ docker run -d -p 80:80 -e DEFAULT_HOST=foo.bar.com -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -e DEFAULT_HOST=foo.bar.com -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy +nginx-proxy will then redirect all requests to a container where `VIRTUAL_HOST` is set to `DEFAULT_HOST`, if they don't match any (other) `VIRTUAL_HOST`. Using the example above requests without matching `VIRTUAL_HOST` will be redirected to a plain nginx instance after running the following command: + + $ docker run -d -e VIRTUAL_HOST=foo.bar.com nginx ### Separate Containers @@ -168,7 +178,7 @@ $ curl -H "Host: whoami.local" localhost I'm 5b129ab83266 ``` -To run nginx proxy as a separate container you'll need to have [nginx.tmpl](https://github.com/jwilder/nginx-proxy/blob/master/nginx.tmpl) on your host system. +To run nginx proxy as a separate container you'll need to have [nginx.tmpl](https://github.com/nginx-proxy/nginx-proxy/blob/main/nginx.tmpl) on your host system. First start nginx with a volume: @@ -187,9 +197,9 @@ $ docker run --volumes-from nginx \ Finally, start your containers with `VIRTUAL_HOST` environment variables. $ docker run -e VIRTUAL_HOST=foo.bar.com ... -### SSL Support using letsencrypt +### SSL Support using an ACME CA -[letsencrypt-nginx-proxy-companion](https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion) is a lightweight companion container for the nginx-proxy. It allows the creation/renewal of Let's Encrypt certificates automatically. +[acme-companion](https://github.com/nginx-proxy/acme-companion) is a lightweight companion container for the nginx-proxy. It allows the automated creation/renewal of SSL certificates using the ACME protocol. Set `DHPARAM_GENERATION` environment variable to `false` to disabled Diffie-Hellman parameters completely. This will also ignore auto-generation made by `nginx-proxy`. The default value is `true` @@ -202,7 +212,7 @@ certificates or optionally specifying a cert name (for SNI) as an environment va To enable SSL: - $ docker run -d -p 80:80 -p 443:443 -v /path/to/certs:/etc/nginx/certs -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -p 443:443 -v /path/to/certs:/etc/nginx/certs -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy The contents of `/path/to/certs` should contain the certificates and private keys for any virtual hosts in use. The certificate and keys should be named after the virtual host with a `.crt` and @@ -226,7 +236,7 @@ at startup. Since it can take minutes to generate a new `dhparam.pem`, it is do background. Once generation is complete, the `dhparam.pem` is saved on a persistent volume and nginx is reloaded. This generation process only occurs the first time you start `nginx-proxy`. -> COMPATIBILITY WARNING: The default generated `dhparam.pem` key is 2048 bits for A+ security. Some +> COMPATIBILITY WARNING: The default generated `dhparam.pem` key is 4096 bits for A+ security. Some > older clients (like Java 6 and 7) do not support DH keys with over 1024 bits. In order to support these > clients, you must either provide your own `dhparam.pem`, or tell `nginx-proxy` to generate a 1024-bit > key on startup by passing `-e DHPARAM_BITS=1024`. @@ -234,7 +244,7 @@ is reloaded. This generation process only occurs the first time you start `ngin In the separate container setup, no pregenerated key will be available and neither the [jwilder/docker-gen](https://hub.docker.com/r/jwilder/docker-gen) image nor the offical [nginx](https://registry.hub.docker.com/_/nginx/) image will generate one. If you still want A+ security -in a separate container setup, you'll have to generate a 2048 bits DH key file manually and mount it on the +in a separate container setup, you'll have to generate a 2048 or 4096 bits DH key file manually and mount it on the nginx container, at `/etc/nginx/dhparam/dhparam.pem`. #### Wildcard Certificates @@ -276,7 +286,7 @@ and the [AWS ELB Security Policies](https://docs.aws.amazon.com/elasticloadbalan `AWS-TLS-1-2-2017-01`, `AWS-TLS-1-1-2017-01`, `AWS-2016-08`, `AWS-2015-05`, `AWS-2015-03` and `AWS-2015-02`. Note that the `Mozilla-Old` policy should use a 1024 bits DH key for compatibility but this container generates -a 2048 bits key. The [Diffie-Hellman Groups](#diffie-hellman-groups) section details different methods of bypassing +a 4096 bits key. The [Diffie-Hellman Groups](#diffie-hellman-groups) section details different methods of bypassing this, either globally or per virtual-host. The default behavior for the proxy when port 80 and 443 are exposed is as follows: @@ -317,7 +327,7 @@ $ docker run -d -p 80:80 -p 443:443 \ -v /path/to/htpasswd:/etc/nginx/htpasswd \ -v /path/to/certs:/etc/nginx/certs \ -v /var/run/docker.sock:/tmp/docker.sock:ro \ - jwilder/nginx-proxy + nginxproxy/nginx-proxy ``` You'll need apache2-utils on the machine where you plan to create the htpasswd file. Follow these [instructions](http://httpd.apache.org/docs/2.2/programs/htpasswd.html) @@ -359,7 +369,7 @@ To add settings on a proxy-wide basis, add your configuration file under `/etc/n This can be done in a derived image by creating the file in a `RUN` command or by `COPY`ing the file into `conf.d`: ```Dockerfile -FROM jwilder/nginx-proxy +FROM nginxproxy/nginx-proxy RUN { \ echo 'server_tokens off;'; \ echo 'client_max_body_size 100m;'; \ @@ -368,7 +378,7 @@ RUN { \ Or it can be done by mounting in your custom configuration in your `docker run` command: - $ docker run -d -p 80:80 -p 443:443 -v /path/to/my_proxy.conf:/etc/nginx/conf.d/my_proxy.conf:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -p 443:443 -v /path/to/my_proxy.conf:/etc/nginx/conf.d/my_proxy.conf:ro -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy #### Per-VIRTUAL_HOST @@ -378,7 +388,7 @@ In order to allow virtual hosts to be dynamically configured as backends are add For example, if you have a virtual host named `app.example.com`, you could provide a custom configuration for that host as follows: - $ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy $ { echo 'server_tokens off;'; echo 'client_max_body_size 100m;'; } > /path/to/vhost.d/app.example.com If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink: @@ -398,7 +408,7 @@ just like the previous section except with the suffix `_location`. For example, if you have a virtual host named `app.example.com` and you have configured a proxy_cache `my-cache` in another custom file, you could tell it to use a proxy cache as follows: - $ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro jwilder/nginx-proxy + $ docker run -d -p 80:80 -p 443:443 -v /path/to/vhost.d:/etc/nginx/vhost.d:ro -v /var/run/docker.sock:/tmp/docker.sock:ro nginxproxy/nginx-proxy $ { echo 'proxy_cache my-cache;'; echo 'proxy_cache_valid 200 302 60m;'; echo 'proxy_cache_valid 404 1m;' } > /path/to/vhost.d/app.example.com_location If you are using multiple hostnames for a single container (e.g. `VIRTUAL_HOST=example.com,www.example.com`), the virtual host configuration file must exist for each hostname. If you would like to use the same configuration for multiple virtual host names, you can use a symlink: @@ -417,26 +427,15 @@ Before submitting pull requests or issues, please check github to make sure an e #### Running Tests Locally -To run tests, you need to prepare the docker image to test which must be tagged `jwilder/nginx-proxy:test`: - - docker build -t jwilder/nginx-proxy:test . # build the Debian variant image - -and call the [test/pytest.sh](test/pytest.sh) script. - -Then build the Alpine variant of the image: - - docker build -f Dockerfile.alpine -t jwilder/nginx-proxy:test . # build the Alpline variant image - -and call the [test/pytest.sh](test/pytest.sh) script again. - - -If your system has the `make` command, you can automate those tasks by calling: +To run tests, you just need to run the command below: make test +This commands run tests on two variants of the nginx-proxy docker image: Debian and Alpine. + +You can run the tests for each of these images with their respective commands: + + make test-debian + make test-alpine You can learn more about how the test suite works and how to write new tests in the [test/README.md](test/README.md) file. - -### Need help? - -If you have questions on how to use the image, please ask them on the [Q&A Group](https://groups.google.com/forum/#!forum/nginx-proxy) diff --git a/docker-compose.yml b/docker-compose.yml index b76f0c0..138f396 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: '2' services: nginx-proxy: - image: jwilder/nginx-proxy + image: nginxproxy/nginx-proxy container_name: nginx-proxy ports: - "80:80" diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 6eeada9..0e42880 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -4,10 +4,10 @@ set -e # Warn if the DOCKER_HOST socket does not exist if [[ $DOCKER_HOST = unix://* ]]; then socket_file=${DOCKER_HOST#unix://} - if ! [ -S $socket_file ]; then + if ! [ -S "$socket_file" ]; then cat >&2 <<-EOT ERROR: you need to share your Docker host socket with a volume at $socket_file - Typically you should run your jwilder/nginx-proxy with: \`-v /var/run/docker.sock:$socket_file:ro\` + Typically you should run your nginxproxy/nginx-proxy with: \`-v /var/run/docker.sock:$socket_file:ro\` See the documentation at http://git.io/vZaGJ EOT socketMissing=1 @@ -15,26 +15,24 @@ if [[ $DOCKER_HOST = unix://* ]]; then fi # Generate dhparam file if required -# Note: if $DHPARAM_BITS is not defined, generate-dhparam.sh will use 2048 as a default -# Note2: if $DHPARAM_GENERATION is set to false in environment variable, dh param generator will skip completely -/app/generate-dhparam.sh $DHPARAM_BITS $DHPARAM_GENERATION +/app/generate-dhparam.sh # Compute the DNS resolvers for use in the templates - if the IP contains ":", it's IPv6 and must be enclosed in [] -export RESOLVERS=$(awk '$1 == "nameserver" {print ($2 ~ ":")? "["$2"]": $2}' ORS=' ' /etc/resolv.conf | sed 's/ *$//g') +RESOLVERS=$(awk '$1 == "nameserver" {print ($2 ~ ":")? "["$2"]": $2}' ORS=' ' /etc/resolv.conf | sed 's/ *$//g'); export RESOLVERS SCOPED_IPV6_REGEX="\[fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}\]" -if [ "x$RESOLVERS" = "x" ]; then +if [ "$RESOLVERS" = "" ]; then echo "Warning: unable to determine DNS resolvers for nginx" >&2 unset RESOLVERS elif [[ $RESOLVERS =~ $SCOPED_IPV6_REGEX ]]; then echo -n "Warning: Scoped IPv6 addresses removed from resolvers: " >&2 - echo $RESOLVERS | grep -Eo $SCOPED_IPV6_REGEX | paste -s -d ' ' >&2 - export RESOLVERS=$(echo $RESOLVERS | sed -r "s/$SCOPED_IPV6_REGEX//g" | xargs echo -n) + echo "$RESOLVERS" | grep -Eo "$SCOPED_IPV6_REGEX" | paste -s -d ' ' >&2 + RESOLVERS=$(echo "$RESOLVERS" | sed -r "s/$SCOPED_IPV6_REGEX//g" | xargs echo -n); export RESOLVERS fi # If the user has run the default command and the socket doesn't exist, fail -if [ "$socketMissing" = 1 -a "$1" = forego -a "$2" = start -a "$3" = '-r' ]; then +if [ "$socketMissing" = 1 ] && [ "$1" = forego ] && [ "$2" = start ] && [ "$3" = '-r' ]; then exit 1 fi diff --git a/generate-dhparam.sh b/generate-dhparam.sh index 03b828c..397fab0 100755 --- a/generate-dhparam.sh +++ b/generate-dhparam.sh @@ -1,8 +1,9 @@ #!/bin/bash -e -# The first argument is the bit depth of the dhparam, or 4096 if unspecified -DHPARAM_BITS=${1:-4096} -GENERATE_DHPARAM=${2:-true} +# DHPARAM_BITS is the bit depth of the dhparam, or 4096 if unspecified +DHPARAM_BITS=${DHPARAM_BITS:-4096} +# DHPARAM_GENERATION=false skips dhparam generation +DHPARAM_GENERATION=${DHPARAM_GENERATION:-true} # If a dhparam file is not available, use the pre-generated one and generate a new one in the background. # Note that /etc/nginx/dhparam is a volume, so this dhparam will persist restarts. @@ -14,7 +15,7 @@ GEN_LOCKFILE="/tmp/dhparam_generating.lock" PREGEN_HASH=$(md5sum $PREGEN_DHPARAM_FILE | cut -d" " -f1) if [[ -f $DHPARAM_FILE ]]; then CURRENT_HASH=$(md5sum $DHPARAM_FILE | cut -d" " -f1) - if [[ $PREGEN_HASH != $CURRENT_HASH ]]; then + if [[ $PREGEN_HASH != "$CURRENT_HASH" ]]; then # There is already a dhparam, and it's not the default echo "Custom dhparam.pem file found, generation skipped" exit 0 @@ -26,7 +27,7 @@ if [[ -f $DHPARAM_FILE ]]; then fi fi -if [[ $GENERATE_DHPARAM =~ ^[Ff][Aa][Ll][Ss][Ee]$ ]]; then +if [[ $DHPARAM_GENERATION =~ ^[Ff][Aa][Ll][Ss][Ee]$ ]]; then echo "Skipping Diffie-Hellman parameters generation and Ignoring pre-generated dhparam.pem" exit 0 fi @@ -43,10 +44,10 @@ touch $GEN_LOCKFILE # Generate a new dhparam in the background in a low priority and reload nginx when finished (grep removes the progress indicator). ( ( - nice -n +5 openssl dhparam -dsaparam -out $DHPARAM_FILE.tmp $DHPARAM_BITS 2>&1 \ + nice -n +5 openssl dhparam -dsaparam -out $DHPARAM_FILE.tmp "$DHPARAM_BITS" 2>&1 \ && mv $DHPARAM_FILE.tmp $DHPARAM_FILE \ && echo "dhparam generation complete, reloading nginx" \ && nginx -s reload ) | grep -vE '^[\.+]+' rm $GEN_LOCKFILE -) &disown +) & disown diff --git a/nginx.tmpl b/nginx.tmpl index 07e2b50..1e03182 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -172,7 +172,7 @@ server { {{ $host := trim $host }} {{ $is_regexp := hasPrefix "~" $host }} -{{ $upstream_name := when $is_regexp (sha1 $host) $host }} +{{ $upstream_name := (print (when $is_regexp (sha1 $host) $host) "-upstream") }} # {{ $host }} upstream {{ $upstream_name }} { @@ -253,8 +253,9 @@ server { {{ $access_log }} # Do not HTTPS redirect Let'sEncrypt ACME challenge - location /.well-known/acme-challenge/ { + location ^~ /.well-known/acme-challenge/ { auth_basic off; + auth_request off; allow all; root /usr/share/nginx/html; try_files $uri =404; diff --git a/test/README.md b/test/README.md index 9d7a57c..df7c214 100644 --- a/test/README.md +++ b/test/README.md @@ -4,25 +4,20 @@ Nginx proxy test suite Install requirements -------------------- -You need [python 2.7](https://www.python.org/) and [pip](https://pip.pypa.io/en/stable/installing/) installed. Then run the commands: +You need [python 3.9](https://www.python.org/) and [pip](https://pip.pypa.io/en/stable/installing/) installed. Then run the commands: - requirements/build.sh pip install -r requirements/python-requirements.txt -If you can't install those requirements on your computer, you can alternatively use the _pytest.sh_ script which will run the tests from a Docker container which has those requirements. Prepare the nginx-proxy test image ---------------------------------- - docker build -t jwilder/nginx-proxy:test .. + make build-nginx-proxy-test-debian or if you want to test the alpine flavor: - docker build -t jwilder/nginx-proxy:test -f Dockerfile.alpine .. - -make sure to tag that test image exactly `jwilder/nginx-proxy:test` or the test suite won't work. - + make build-nginx-proxy-test-alpine Run the test suite ------------------ @@ -61,11 +56,11 @@ The fixture will run the _docker-compose_ command with the `-f` option to load t 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 your tests, you can use the `docker_compose` variable to query and command the docker daemon as it provides you with a [client from the docker python module](https://docker-py.readthedocs.io/en/2.0.2/client.html#client-reference). +In your tests, you can use the `docker_compose` variable to query and command the docker daemon as it provides you with a [client from the docker python module](https://docker-py.readthedocs.io/en/4.4.4/client.html#client-reference). 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 `jwilder/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 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: - `nginx-proxy` - `nginx-proxy.com` - `www.nginx-proxy.com` @@ -99,9 +94,8 @@ Furthermore, the nginxproxy methods accept an additional keyword parameter: `ipv ### The web docker image -When you ran the `requirements/build.sh` script earlier, you built a [`web`](requirements/README.md) docker image which is convenient for running a small web server in a container. This image can produce containers that listens on multiple ports at the same time. - +When you run the `make build-webserver` command, you built a [`web`](requirements/README.md) docker image which is convenient for running a small web server in a container. This image can produce containers that listens on multiple ports at the same time. ### Testing TLS -If you need to create server certificates, use the [`certs/create_server_certificate.sh`](certs/) script. Pytest will be able to validate any certificate issued from this script. \ No newline at end of file +If you need to create server certificates, use the [`certs/create_server_certificate.sh`](certs/) script. Pytest will be able to validate any certificate issued from this script. diff --git a/test/conftest.py b/test/conftest.py index 6bd172a..aa398e6 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,4 +1,3 @@ -from __future__ import print_function import contextlib import logging import os @@ -68,11 +67,11 @@ class requests_for_docker(object): """ Return the nginx config file """ - nginx_proxy_containers = docker_client.containers.list(filters={"ancestor": "jwilder/nginx-proxy:test"}) + nginx_proxy_containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/nginx-proxy:test"}) if len(nginx_proxy_containers) > 1: - pytest.fail("Too many running jwilder/nginx-proxy:test containers", pytrace=False) + pytest.fail("Too many running nginxproxy/nginx-proxy:test containers", pytrace=False) elif len(nginx_proxy_containers) == 0: - pytest.fail("No running jwilder/nginx-proxy:test container", pytrace=False) + pytest.fail("No running nginxproxy/nginx-proxy:test container", pytrace=False) return get_nginx_conf_from_container(nginx_proxy_containers[0]) def get(self, *args, **kwargs): @@ -133,7 +132,7 @@ def container_ip(container): pytest.skip("This system does not support IPv6") ip = container_ipv6(container) if ip == '': - pytest.skip("Container %s has no IPv6 address" % container.name) + pytest.skip(f"Container {container.name} has no IPv6 address") else: return ip else: @@ -142,7 +141,7 @@ def container_ip(container): return net_info["bridge"]["IPAddress"] # not default bridge network, fallback on first network defined - network_name = net_info.keys()[0] + network_name = list(net_info.keys())[0] return net_info[network_name]["IPAddress"] @@ -155,27 +154,27 @@ def container_ipv6(container): return net_info["bridge"]["GlobalIPv6Address"] # not default bridge network, fallback on first network defined - network_name = net_info.keys()[0] + network_name = list(net_info.keys())[0] return net_info[network_name]["GlobalIPv6Address"] def nginx_proxy_dns_resolver(domain_name): """ if "nginx-proxy" if found in host, return the ip address of the docker container - issued from the docker image jwilder/nginx-proxy:test. + issued from the docker image nginxproxy/nginx-proxy:test. :return: IP or None """ log = logging.getLogger('DNS') - log.debug("nginx_proxy_dns_resolver(%r)" % domain_name) + log.debug(f"nginx_proxy_dns_resolver({domain_name!r})") if 'nginx-proxy' in domain_name: - nginxproxy_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "jwilder/nginx-proxy:test"}) + nginxproxy_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginxproxy/nginx-proxy:test"}) if len(nginxproxy_containers) == 0: - log.warn("no container found from image jwilder/nginx-proxy:test while resolving %r", domain_name) + log.warn(f"no container found from image nginxproxy/nginx-proxy:test while resolving {domain_name!r}") return nginxproxy_container = nginxproxy_containers[0] ip = container_ip(nginxproxy_container) - log.info("resolving domain name %r as IP address %s of nginx-proxy container %s" % (domain_name, ip, 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 def docker_container_dns_resolver(domain_name): @@ -186,24 +185,24 @@ def docker_container_dns_resolver(domain_name): :return: IP or None """ log = logging.getLogger('DNS') - log.debug("docker_container_dns_resolver(%r)" % domain_name) + log.debug(f"docker_container_dns_resolver({domain_name!r})") - match = re.search('(^|.+\.)(?P[^.]+)\.container\.docker$', domain_name) + match = re.search(r'(^|.+\.)(?P[^.]+)\.container\.docker$', domain_name) if not match: - log.debug("%r does not match" % domain_name) + log.debug(f"{domain_name!r} does not match") return container_name = match.group('container') - log.debug("looking for container %r" % container_name) + log.debug(f"looking for container {container_name!r}") try: container = docker_client.containers.get(container_name) except docker.errors.NotFound: - log.warn("container named %r not found while resolving %r" % (container_name, domain_name)) + log.warn(f"container named {container_name!r} not found while resolving {domain_name!r}") return - log.debug("container %r found (%s)" % (container.name, container.short_id)) + log.debug(f"container {container.name!r} found ({container.short_id})") ip = container_ip(container) - log.info("resolving domain name %r as IP address %s of container %s" % (domain_name, ip, container.name)) + log.info(f"resolving domain name {domain_name!r} as IP address {ip} of container {container.name}") return ip @@ -211,12 +210,12 @@ def monkey_patch_urllib_dns_resolver(): """ Alter the behavior of the urllib DNS resolver so that any domain name containing substring 'nginx-proxy' will resolve to the IP address - of the container created from image 'jwilder/nginx-proxy:test'. + of the container created from image 'nginxproxy/nginx-proxy:test'. """ prv_getaddrinfo = socket.getaddrinfo dns_cache = {} def new_getaddrinfo(*args): - logging.getLogger('DNS').debug("resolving domain name %s" % repr(args)) + logging.getLogger('DNS').debug(f"resolving domain name {repr(args)}") _args = list(args) # custom DNS resolvers @@ -244,7 +243,7 @@ def remove_all_containers(): for container in docker_client.containers.list(all=True): if I_AM_RUNNING_INSIDE_A_DOCKER_CONTAINER and container.id.startswith(socket.gethostname()): continue # pytest is running within a Docker container, so we do not want to remove that particular container - logging.info("removing container %s" % container.name) + logging.info(f"removing container {container.name}") container.remove(v=True, force=True) @@ -253,40 +252,43 @@ def get_nginx_conf_from_container(container): return the nginx /etc/nginx/conf.d/default.conf file content from a container """ import tarfile - from cStringIO import StringIO - strm, stat = container.get_archive('/etc/nginx/conf.d/default.conf') - with tarfile.open(fileobj=StringIO(strm.read())) as tf: + from io import BytesIO + + strm_generator, stat = container.get_archive('/etc/nginx/conf.d/default.conf') + strm_fileobj = BytesIO(b"".join(strm_generator)) + + with tarfile.open(fileobj=strm_fileobj) as tf: conffile = tf.extractfile('default.conf') return conffile.read() def docker_compose_up(compose_file='docker-compose.yml'): - logging.info('docker-compose -f %s up -d' % compose_file) + logging.info(f'docker-compose -f {compose_file} up -d') try: - subprocess.check_output(shlex.split('docker-compose -f %s up -d' % compose_file), stderr=subprocess.STDOUT) - except subprocess.CalledProcessError, e: - pytest.fail("Error while runninng 'docker-compose -f %s up -d':\n%s" % (compose_file, e.output), pytrace=False) + subprocess.check_output(shlex.split(f'docker-compose -f {compose_file} up -d'), stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + pytest.fail(f"Error while runninng 'docker-compose -f {compose_file} up -d':\n{e.output}", pytrace=False) def docker_compose_down(compose_file='docker-compose.yml'): - logging.info('docker-compose -f %s down' % compose_file) + logging.info(f'docker-compose -f {compose_file} down') try: - subprocess.check_output(shlex.split('docker-compose -f %s down' % compose_file), stderr=subprocess.STDOUT) - except subprocess.CalledProcessError, e: - pytest.fail("Error while runninng 'docker-compose -f %s down':\n%s" % (compose_file, e.output), pytrace=False) + subprocess.check_output(shlex.split(f'docker-compose -f {compose_file} down'), stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + pytest.fail(f"Error while runninng 'docker-compose -f {compose_file} down':\n{e.output}", pytrace=False) def wait_for_nginxproxy_to_be_ready(): """ - If one (and only one) container started from image jwilder/nginx-proxy:test is found, + If one (and only one) container started from image nginxproxy/nginx-proxy:test is found, wait for its log to contain substring "Watching docker events" """ - containers = docker_client.containers.list(filters={"ancestor": "jwilder/nginx-proxy:test"}) + containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/nginx-proxy:test"}) if len(containers) != 1: return container = containers[0] for line in container.logs(stream=True): - if "Watching docker events" in line: + if b"Watching docker events" in line: logging.debug("nginx-proxy ready") break @@ -307,7 +309,7 @@ def find_docker_compose_file(request): if docker_compose_file_module_variable is not None: docker_compose_file = os.path.join( test_module_dir, docker_compose_file_module_variable) if not os.path.isfile(docker_compose_file): - raise ValueError("docker compose file %r could not be found. Check your test module `docker_compose_file` variable value." % docker_compose_file) + raise ValueError(f"docker compose file {docker_compose_file!r} could not be found. Check your test module `docker_compose_file` variable value.") else: if os.path.isfile(yml_file): docker_compose_file = yml_file @@ -319,7 +321,7 @@ def find_docker_compose_file(request): if not os.path.isfile(docker_compose_file): logging.error("Could not find any docker-compose file named either '{0}.yml', '{0}.yaml' or 'docker-compose.yml'".format(request.module.__name__)) - logging.debug("using docker compose file %s" % docker_compose_file) + logging.debug(f"using docker compose file {docker_compose_file}") return docker_compose_file @@ -333,15 +335,15 @@ def connect_to_network(network): try: my_container = docker_client.containers.get(socket.gethostname()) except docker.errors.NotFound: - logging.warn("container %r not found" % socket.gethostname()) + logging.warn(f"container {socket.gethostname()!r} not found") return # figure out our container networks - my_networks = my_container.attrs["NetworkSettings"]["Networks"].keys() + my_networks = list(my_container.attrs["NetworkSettings"]["Networks"].keys()) # make sure our container is connected to the nginx-proxy's network if network not in my_networks: - logging.info("Connecting to docker network: %s" % network.name) + logging.info(f"Connecting to docker network: {network.name}") network.connect(my_container) return network @@ -356,15 +358,15 @@ def disconnect_from_network(network=None): try: my_container = docker_client.containers.get(socket.gethostname()) except docker.errors.NotFound: - logging.warn("container %r not found" % socket.gethostname()) + logging.warn(f"container {socket.gethostname()!r} not found") return # figure out our container networks - my_networks_names = my_container.attrs["NetworkSettings"]["Networks"].keys() + my_networks_names = list(my_container.attrs["NetworkSettings"]["Networks"].keys()) # disconnect our container from the given network if network.name in my_networks_names: - logging.info("Disconnecting from network %s" % network.name) + logging.info(f"Disconnecting from network {network.name}") network.disconnect(my_container) @@ -378,7 +380,7 @@ def connect_to_all_networks(): return [] else: # find the list of docker networks - networks = filter(lambda network: len(network.containers) > 0 and network.name != 'bridge', docker_client.networks.list()) + networks = [network for network in docker_client.networks.list() if len(network.containers) > 0 and network.name != 'bridge'] return [connect_to_network(network) for network in networks] @@ -388,7 +390,7 @@ def connect_to_all_networks(): # ############################################################################### -@pytest.yield_fixture(scope="module") +@pytest.fixture(scope="module") def docker_compose(request): """ pytest fixture providing containers described in a docker compose file. After the tests, remove the created containers @@ -412,7 +414,7 @@ def docker_compose(request): restore_urllib_dns_resolver(original_dns_resolver) -@pytest.yield_fixture() +@pytest.fixture() def nginxproxy(): """ Provides the `nginxproxy` object that can be used in the same way the requests module is: @@ -439,7 +441,7 @@ def nginxproxy(): def pytest_runtest_logreport(report): if report.failed: if isinstance(report.longrepr, ReprExceptionInfo): - test_containers = docker_client.containers.list(all=True, filters={"ancestor": "jwilder/nginx-proxy:test"}) + test_containers = docker_client.containers.list(all=True, filters={"ancestor": "nginxproxy/nginx-proxy:test"}) for container in test_containers: report.longrepr.addsection('nginx-proxy logs', container.logs()) report.longrepr.addsection('nginx-proxy conf', get_nginx_conf_from_container(container)) @@ -456,7 +458,7 @@ def pytest_runtest_makereport(item, call): def pytest_runtest_setup(item): previousfailed = getattr(item.parent, "_previousfailed", None) if previousfailed is not None: - pytest.xfail("previous test failed (%s)" % previousfailed.name) + pytest.xfail(f"previous test failed ({previousfailed.name})") ############################################################################### # @@ -465,9 +467,9 @@ def pytest_runtest_setup(item): ############################################################################### try: - docker_client.images.get('jwilder/nginx-proxy:test') + docker_client.images.get('nginxproxy/nginx-proxy:test') except docker.errors.ImageNotFound: - pytest.exit("The docker image 'jwilder/nginx-proxy:test' is missing") + pytest.exit("The docker image 'nginxproxy/nginx-proxy:test' is missing") -if docker.__version__ != "2.1.0": - pytest.exit("This test suite is meant to work with the python docker module v2.1.0") +if docker.__version__ != "4.4.4": + pytest.exit("This test suite is meant to work with the python docker module v4.4.4") diff --git a/test/pytest.ini b/test/pytest.ini index 30f3e19..9ca7667 100644 --- a/test/pytest.ini +++ b/test/pytest.ini @@ -1,3 +1,5 @@ [pytest] # disable the creation of the `.cache` folders -addopts = -p no:cacheprovider --ignore=requirements --ignore=certs -r s -v \ No newline at end of file +addopts = -p no:cacheprovider --ignore=requirements --ignore=certs -r s -v +markers = + incremental: mark a test as incremental. \ No newline at end of file diff --git a/test/requirements/Dockerfile-nginx-proxy-tester b/test/requirements/Dockerfile-nginx-proxy-tester index 27d0538..3c25c0c 100644 --- a/test/requirements/Dockerfile-nginx-proxy-tester +++ b/test/requirements/Dockerfile-nginx-proxy-tester @@ -1,7 +1,4 @@ -FROM python:2.7-alpine - -# Note: we're using alpine because it has openssl 1.0.2, which we need for testing -RUN apk add --update bash openssl curl && rm -rf /var/cache/apk/* +FROM python:3.9 COPY python-requirements.txt /requirements.txt RUN pip install -r /requirements.txt diff --git a/test/requirements/README.md b/test/requirements/README.md index 3a0c389..394c9b1 100644 --- a/test/requirements/README.md +++ b/test/requirements/README.md @@ -2,7 +2,7 @@ This directory contains resources to build Docker images tests depend on # Build images - ./build.sh + make build-webserver # python-requirements.txt diff --git a/test/requirements/build.sh b/test/requirements/build.sh deleted file mode 100755 index f29897a..0000000 --- a/test/requirements/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -set -e - -DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -docker build -t web $DIR/web \ No newline at end of file diff --git a/test/requirements/python-requirements.txt b/test/requirements/python-requirements.txt index ba95455..11f8665 100644 --- a/test/requirements/python-requirements.txt +++ b/test/requirements/python-requirements.txt @@ -1,5 +1,5 @@ -backoff==1.3.2 -docker-compose==1.11.2 -docker==2.1.0 -pytest==3.0.5 -requests==2.11.1 +backoff==1.10.0 +docker-compose==1.28.5 +docker==4.4.4 +pytest==6.2.2 +requests==2.25.1 diff --git a/test/requirements/web/webserver.py b/test/requirements/web/webserver.py index 9334657..b8e81c0 100755 --- a/test/requirements/web/webserver.py +++ b/test/requirements/web/webserver.py @@ -13,13 +13,13 @@ class Handler(http.server.SimpleHTTPRequestHandler): if self.path == "/headers": response_body += self.headers.as_string() elif self.path == "/port": - response_body += "answer from port %s\n" % PORT + response_body += f"answer from port {PORT}\n" elif re.match("/status/(\d+)", self.path): result = re.match("/status/(\d+)", self.path) response_code = int(result.group(1)) - response_body += "answer with response code %s\n" % response_code + response_body += f"answer with response code {response_code}\n" elif self.path == "/": - response_body += "I'm %s\n" % os.environ['HOSTNAME'] + response_body += f"I'm {os.environ['HOSTNAME']}\n" else: response_body += "No route for this path!\n" response_code = 404 diff --git a/test/stress_tests/test_deleted_cert/docker-compose.yml b/test/stress_tests/test_deleted_cert/docker-compose.yml index 06a61b9..33c92a7 100644 --- a/test/stress_tests/test_deleted_cert/docker-compose.yml +++ b/test/stress_tests/test_deleted_cert/docker-compose.yml @@ -8,7 +8,7 @@ web: reverseproxy: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test container_name: reverseproxy environment: DEBUG: "true" diff --git a/test/stress_tests/test_deleted_cert/test_restart_while_missing_cert.py b/test/stress_tests/test_deleted_cert/test_restart_while_missing_cert.py index 2b74acd..0ec36c7 100644 --- a/test/stress_tests/test_deleted_cert/test_restart_while_missing_cert.py +++ b/test/stress_tests/test_deleted_cert/test_restart_while_missing_cert.py @@ -12,7 +12,7 @@ script_dir = os.path.dirname(__file__) pytestmark = pytest.mark.xfail() # TODO delete this marker once those issues are fixed -@pytest.yield_fixture(scope="module", autouse=True) +@pytest.fixture(scope="module", autouse=True) def certs(): """ pytest fixture that provides cert and key files into the tmp_certs directory @@ -43,7 +43,7 @@ def test_http_web_is_301(docker_compose, nginxproxy): 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 + assert "answer from port 81\n" in r.text @pytest.mark.incremental diff --git a/test/stress_tests/test_unreachable_network/README.md b/test/stress_tests/test_unreachable_network/README.md index aa09c4d..550b289 100644 --- a/test/stress_tests/test_unreachable_network/README.md +++ b/test/stress_tests/test_unreachable_network/README.md @@ -6,7 +6,7 @@ Furthermore, if the nginx-proxy in such state is restarted, the nginx process wi In the generated nginx config file, we can notice the presence of an empty `upstream {}` block. -This can be fixed by merging [PR-585](https://github.com/jwilder/nginx-proxy/pull/585). +This can be fixed by merging [PR-585](https://github.com/nginx-proxy/nginx-proxy/pull/585). ## How to reproduce diff --git a/test/stress_tests/test_unreachable_network/docker-compose.yml b/test/stress_tests/test_unreachable_network/docker-compose.yml index 0ca4f99..9666d29 100644 --- a/test/stress_tests/test_unreachable_network/docker-compose.yml +++ b/test/stress_tests/test_unreachable_network/docker-compose.yml @@ -9,7 +9,7 @@ services: container_name: reverseproxy networks: - netA - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_DOCKER_HOST_unix_socket.yml b/test/test_DOCKER_HOST_unix_socket.yml index dff75a8..d1aba4b 100644 --- a/test/test_DOCKER_HOST_unix_socket.yml +++ b/test/test_DOCKER_HOST_unix_socket.yml @@ -16,7 +16,7 @@ web2: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/f00.sock:ro - ./lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_composev2.yml b/test/test_composev2.yml index ef4df8d..283e070 100644 --- a/test/test_composev2.yml +++ b/test/test_composev2.yml @@ -1,7 +1,7 @@ version: '2' services: nginx-proxy: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_custom/test_defaults-location.yml b/test/test_custom/test_defaults-location.yml index a5b0c44..3069273 100644 --- a/test/test_custom/test_defaults-location.yml +++ b/test/test_custom/test_defaults-location.yml @@ -1,5 +1,5 @@ nginx-proxy: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_custom/test_defaults.yml b/test/test_custom/test_defaults.yml index 2cfddf0..165264c 100644 --- a/test/test_custom/test_defaults.yml +++ b/test/test_custom/test_defaults.yml @@ -1,7 +1,7 @@ version: '2' services: nginx-proxy: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_custom/test_location-per-vhost.py b/test/test_custom/test_location-per-vhost.py index b99996e..f67b501 100644 --- a/test/test_custom/test_location-per-vhost.py +++ b/test/test_custom/test_location-per-vhost.py @@ -19,4 +19,4 @@ def test_custom_conf_does_not_apply_to_web2(docker_compose, nginxproxy): assert "X-test" not in r.headers def test_custom_block_is_present_in_nginx_generated_conf(docker_compose, nginxproxy): - assert "include /etc/nginx/vhost.d/web1.nginx-proxy.local_location;" in nginxproxy.get_conf() \ No newline at end of file + assert b"include /etc/nginx/vhost.d/web1.nginx-proxy.local_location;" in nginxproxy.get_conf() \ No newline at end of file diff --git a/test/test_custom/test_location-per-vhost.yml b/test/test_custom/test_location-per-vhost.yml index 988181c..3622325 100644 --- a/test/test_custom/test_location-per-vhost.yml +++ b/test/test_custom/test_location-per-vhost.yml @@ -1,7 +1,7 @@ version: '2' services: nginx-proxy: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_custom/test_per-vhost.yml b/test/test_custom/test_per-vhost.yml index 61ae02b..256c207 100644 --- a/test/test_custom/test_per-vhost.yml +++ b/test/test_custom/test_per-vhost.yml @@ -1,7 +1,7 @@ version: '2' services: nginx-proxy: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_custom/test_proxy-wide.yml b/test/test_custom/test_proxy-wide.yml index 602f344..1715b8b 100644 --- a/test/test_custom/test_proxy-wide.yml +++ b/test/test_custom/test_proxy-wide.yml @@ -1,7 +1,7 @@ version: '2' services: nginx-proxy: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_default-host.yml b/test/test_default-host.yml index f195f58..47b8525 100644 --- a/test/test_default-host.yml +++ b/test/test_default-host.yml @@ -10,7 +10,7 @@ web1: # WHEN nginx-proxy runs with DEFAULT_HOST set to web1.tld sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_dockergen/test_dockergen_v2.py b/test/test_dockergen/test_dockergen_v2.py index c797d0c..43b1431 100644 --- a/test/test_dockergen/test_dockergen_v2.py +++ b/test/test_dockergen/test_dockergen_v2.py @@ -4,23 +4,27 @@ import logging import pytest -@pytest.yield_fixture(scope="module") +@pytest.fixture(scope="module") def nginx_tmpl(): """ pytest fixture which extracts the the nginx config template from - the jwilder/nginx-proxy:test image + the nginxproxy/nginx-proxy:test image """ script_dir = os.path.dirname(__file__) - logging.info("extracting nginx.tmpl from jwilder/nginx-proxy:test") + logging.info("extracting nginx.tmpl from nginxproxy/nginx-proxy:test") docker_client = docker.from_env() - print(docker_client.containers.run( - image='jwilder/nginx-proxy:test', - remove=True, - volumes=['{current_dir}:{current_dir}'.format(current_dir=script_dir)], - entrypoint='sh', - command='-xc "cp /app/nginx.tmpl {current_dir} && chmod 777 {current_dir}/nginx.tmpl"'.format( - current_dir=script_dir), - stderr=True)) + print( + docker_client.containers.run( + image="nginxproxy/nginx-proxy:test", + remove=True, + volumes=["{current_dir}:{current_dir}".format(current_dir=script_dir)], + entrypoint="sh", + command='-xc "cp /app/nginx.tmpl {current_dir} && chmod 777 {current_dir}/nginx.tmpl"'.format( + current_dir=script_dir + ), + stderr=True, + ) + ) yield logging.info("removing nginx.tmpl") os.remove(os.path.join(script_dir, "nginx.tmpl")) @@ -35,4 +39,4 @@ def test_forwards_to_whoami(nginx_tmpl, 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 == "I'm %s\n" % whoami_container.id[:12] + assert r.text == f"I'm {whoami_container.id[:12]}\n" diff --git a/test/test_dockergen/test_dockergen_v3.py b/test/test_dockergen/test_dockergen_v3.py index 808949b..67561bf 100644 --- a/test/test_dockergen/test_dockergen_v3.py +++ b/test/test_dockergen/test_dockergen_v3.py @@ -3,47 +3,37 @@ import docker import logging import pytest import re - -def versiontuple(v): - """ - >>> versiontuple("1.12.3") - (1, 12, 3) - - >>> versiontuple("1.13.0") - (1, 13, 0) - - >>> versiontuple("17.03.0-ce") - (17, 3, 0) - - >>> versiontuple("17.03.0-ce") < (1, 13) - False - """ - return tuple(map(int, (v.split('-')[0].split(".")))) +from distutils.version import LooseVersion -raw_version = docker.from_env().version()['Version'] +raw_version = docker.from_env().version()["Version"] pytestmark = pytest.mark.skipif( - versiontuple(raw_version) < (1, 13), - reason="Docker compose syntax v3 requires docker engine v1.13 or later (got %s)" % raw_version) + LooseVersion(raw_version) < LooseVersion("1.13"), + reason="Docker compose syntax v3 requires docker engine v1.13 or later (got {raw_version})" +) -@pytest.yield_fixture(scope="module") +@pytest.fixture(scope="module") def nginx_tmpl(): """ pytest fixture which extracts the the nginx config template from - the jwilder/nginx-proxy:test image + the nginxproxy/nginx-proxy:test image """ script_dir = os.path.dirname(__file__) - logging.info("extracting nginx.tmpl from jwilder/nginx-proxy:test") + logging.info("extracting nginx.tmpl from nginxproxy/nginx-proxy:test") docker_client = docker.from_env() - print(docker_client.containers.run( - image='jwilder/nginx-proxy:test', - remove=True, - volumes=['{current_dir}:{current_dir}'.format(current_dir=script_dir)], - entrypoint='sh', - command='-xc "cp /app/nginx.tmpl {current_dir} && chmod 777 {current_dir}/nginx.tmpl"'.format( - current_dir=script_dir), - stderr=True)) + print( + docker_client.containers.run( + image="nginxproxy/nginx-proxy:test", + remove=True, + volumes=["{current_dir}:{current_dir}".format(current_dir=script_dir)], + entrypoint="sh", + command='-xc "cp /app/nginx.tmpl {current_dir} && chmod 777 {current_dir}/nginx.tmpl"'.format( + current_dir=script_dir + ), + stderr=True, + ) + ) yield logging.info("removing nginx.tmpl") os.remove(os.path.join(script_dir, "nginx.tmpl")) @@ -58,9 +48,9 @@ def test_forwards_to_whoami(nginx_tmpl, 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 == "I'm %s\n" % whoami_container.id[:12] + assert r.text == f"I'm {whoami_container.id[:12]}\n" -if __name__ == '__main__': +if __name__ == "__main__": import doctest doctest.testmod() diff --git a/test/test_events.py b/test/test_events.py index fa97f84..201917f 100644 --- a/test/test_events.py +++ b/test/test_events.py @@ -7,7 +7,7 @@ import pytest from docker.errors import NotFound -@pytest.yield_fixture() +@pytest.fixture() def web1(docker_compose): """ pytest fixture creating a web container with `VIRTUAL_HOST=web1.nginx-proxy` listening on port 81. diff --git a/test/test_events.yml b/test/test_events.yml index 87b7c01..dcaaafc 100644 --- a/test/test_events.yml +++ b/test/test_events.yml @@ -1,5 +1,5 @@ nginxproxy: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_headers/test_http.yml b/test/test_headers/test_http.yml index 8cc2e09..f8069c6 100644 --- a/test/test_headers/test_http.yml +++ b/test/test_headers/test_http.yml @@ -8,7 +8,7 @@ web: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_headers/test_https.yml b/test/test_headers/test_https.yml index 131f61c..406e433 100644 --- a/test/test_headers/test_https.yml +++ b/test/test_headers/test_https.yml @@ -8,7 +8,7 @@ web: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./certs/web.nginx-proxy.tld.crt:/etc/nginx/certs/web.nginx-proxy.tld.crt:ro diff --git a/test/test_ipv6.yml b/test/test_ipv6.yml index a0b504e..8da3347 100644 --- a/test/test_ipv6.yml +++ b/test/test_ipv6.yml @@ -16,7 +16,7 @@ web2: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_multiple-hosts.yml b/test/test_multiple-hosts.yml index 70269c8..bdc2804 100644 --- a/test/test_multiple-hosts.yml +++ b/test/test_multiple-hosts.yml @@ -8,7 +8,7 @@ web: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_multiple-networks.yml b/test/test_multiple-networks.yml index da3277b..1cc6d30 100644 --- a/test/test_multiple-networks.yml +++ b/test/test_multiple-networks.yml @@ -6,7 +6,7 @@ networks: services: nginx-proxy: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_multiple-ports/test_VIRTUAL_PORT.yml b/test/test_multiple-ports/test_VIRTUAL_PORT.yml index 4eb95ea..3ee2d1a 100644 --- a/test/test_multiple-ports/test_VIRTUAL_PORT.yml +++ b/test/test_multiple-ports/test_VIRTUAL_PORT.yml @@ -9,7 +9,7 @@ web: VIRTUAL_PORT: 90 sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_multiple-ports/test_default-80.yml b/test/test_multiple-ports/test_default-80.yml index f06ccb8..ca61286 100644 --- a/test/test_multiple-ports/test_default-80.yml +++ b/test/test_multiple-ports/test_default-80.yml @@ -8,7 +8,7 @@ web: VIRTUAL_HOST: "web.nginx-proxy.tld" sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_multiple-ports/test_single-port-not-80.yml b/test/test_multiple-ports/test_single-port-not-80.yml index 15f230a..fbb5b6a 100644 --- a/test/test_multiple-ports/test_single-port-not-80.yml +++ b/test/test_multiple-ports/test_single-port-not-80.yml @@ -8,7 +8,7 @@ web: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_nominal.yml b/test/test_nominal.yml index d436499..7c49801 100644 --- a/test/test_nominal.yml +++ b/test/test_nominal.yml @@ -16,7 +16,7 @@ web2: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_ssl/test_dhparam.py b/test/test_ssl/test_dhparam.py index 40339a1..acb4269 100644 --- a/test/test_ssl/test_dhparam.py +++ b/test/test_ssl/test_dhparam.py @@ -26,7 +26,7 @@ def assert_log_contains(expected_log_line): """ sut_container = docker_client.containers.get("nginxproxy") docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False) - assert expected_log_line in docker_logs + assert bytes(expected_log_line, encoding="utf8") in docker_logs def require_openssl(required_version): @@ -42,7 +42,7 @@ def require_openssl(required_version): """ def versiontuple(v): - clean_v = re.sub("[^\d\.]", "", v) + clean_v = re.sub(r"[^\d\.]", "", v) return tuple(map(int, (clean_v.split(".")))) try: @@ -52,10 +52,10 @@ def require_openssl(required_version): else: if not command_output: raise Exception("Could not get openssl version") - openssl_version = command_output.split()[1] + openssl_version = str(command_output.split()[1]) return pytest.mark.skipif( versiontuple(openssl_version) < versiontuple(required_version), - reason="openssl v%s is less than required version %s" % (openssl_version, required_version)) + reason=f"openssl v{openssl_version} is less than required version {required_version}") ############################################################################### @@ -71,8 +71,8 @@ def test_dhparam_is_not_generated_if_present(docker_compose): assert_log_contains("Custom dhparam.pem file found, generation skipped") # Make sure the dhparam in use is not the default, pre-generated one - default_checksum = sut_container.exec_run("md5sum /app/dhparam.pem.default").split() - current_checksum = sut_container.exec_run("md5sum /etc/nginx/dhparam/dhparam.pem").split() + default_checksum = sut_container.exec_run("md5sum /app/dhparam.pem.default").output.split() + current_checksum = sut_container.exec_run("md5sum /etc/nginx/dhparam/dhparam.pem").output.split() assert default_checksum[0] != current_checksum[0] @@ -87,7 +87,7 @@ def test_web5_dhparam_is_used(docker_compose): sut_container = docker_client.containers.get("nginxproxy") assert sut_container.status == "running" - host = "%s:443" % sut_container.attrs["NetworkSettings"]["IPAddress"] + host = f"{sut_container.attrs['NetworkSettings']['IPAddress']}:443" r = subprocess.check_output( - "echo '' | openssl s_client -connect %s -cipher 'EDH' | grep 'Server Temp Key'" % host, shell=True) - assert "Server Temp Key: X25519, 253 bits\n" == r + f"echo '' | openssl s_client -connect {host} -cipher 'EDH' | grep 'Server Temp Key'", shell=True) + assert b"Server Temp Key: X25519, 253 bits\n" == r diff --git a/test/test_ssl/test_dhparam.yml b/test/test_ssl/test_dhparam.yml index 66b1a61..9b29842 100644 --- a/test/test_ssl/test_dhparam.yml +++ b/test/test_ssl/test_dhparam.yml @@ -8,7 +8,7 @@ web5: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test container_name: nginxproxy volumes: - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_ssl/test_dhparam_generation.py b/test/test_ssl/test_dhparam_generation.py index 0f5398b..ec1c90e 100644 --- a/test/test_ssl/test_dhparam_generation.py +++ b/test/test_ssl/test_dhparam_generation.py @@ -22,7 +22,7 @@ def assert_log_contains(expected_log_line): """ sut_container = docker_client.containers.get("nginxproxy") docker_logs = sut_container.logs(stdout=True, stderr=True, stream=False, follow=False) - assert expected_log_line in docker_logs + assert bytes(expected_log_line, encoding="utf8") in docker_logs ############################################################################### @@ -35,10 +35,10 @@ def test_dhparam_is_generated_if_missing(docker_compose): sut_container = docker_client.containers.get("nginxproxy") assert sut_container.status == "running" - assert_log_contains("Generating DH parameters") + assert_log_contains("Generating DSA parameters") assert_log_contains("dhparam generation complete, reloading nginx") # Make sure the dhparam in use is not the default, pre-generated one - default_checksum = sut_container.exec_run("md5sum /app/dhparam.pem.default").split() - generated_checksum = sut_container.exec_run("md5sum /etc/nginx/dhparam/dhparam.pem").split() + default_checksum = sut_container.exec_run("md5sum /app/dhparam.pem.default").output.split() + generated_checksum = sut_container.exec_run("md5sum /etc/nginx/dhparam/dhparam.pem").output.split() assert default_checksum[0] != generated_checksum[0] diff --git a/test/test_ssl/test_dhparam_generation.yml b/test/test_ssl/test_dhparam_generation.yml index 35f3067..6df55c1 100644 --- a/test/test_ssl/test_dhparam_generation.yml +++ b/test/test_ssl/test_dhparam_generation.yml @@ -1,5 +1,5 @@ sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test container_name: nginxproxy volumes: - /var/run/docker.sock:/tmp/docker.sock:ro diff --git a/test/test_ssl/test_hsts.py b/test/test_ssl/test_hsts.py index 12bbcc4..16dffd2 100644 --- a/test/test_ssl/test_hsts.py +++ b/test/test_ssl/test_hsts.py @@ -8,7 +8,7 @@ def test_web1_HSTS_default(docker_compose, nginxproxy): assert "max-age=31536000" == r.headers["Strict-Transport-Security"] # Regression test to ensure HSTS is enabled even when the upstream sends an error in response -# Issue #1073 https://github.com/jwilder/nginx-proxy/pull/1073 +# Issue #1073 https://github.com/nginx-proxy/nginx-proxy/pull/1073 def test_web1_HSTS_error(docker_compose, nginxproxy): r = nginxproxy.get("https://web1.nginx-proxy.tld/status/500", allow_redirects=False) assert "Strict-Transport-Security" in r.headers @@ -26,7 +26,7 @@ def test_web3_HSTS_custom(docker_compose, nginxproxy): assert "max-age=86400; includeSubDomains; preload" == r.headers["Strict-Transport-Security"] # Regression test for issue 1080 -# https://github.com/jwilder/nginx-proxy/issues/1080 +# https://github.com/nginx-proxy/nginx-proxy/issues/1080 def test_web4_HSTS_off_noredirect(docker_compose, nginxproxy): r = nginxproxy.get("https://web4.nginx-proxy.tld/port", allow_redirects=False) assert "answer from port 81\n" in r.text diff --git a/test/test_ssl/test_hsts.yml b/test/test_ssl/test_hsts.yml index f6f39a7..779dc07 100644 --- a/test/test_ssl/test_hsts.yml +++ b/test/test_ssl/test_hsts.yml @@ -35,7 +35,7 @@ web4: HTTPS_METHOD: "noredirect" sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_ssl/test_nohttp.yml b/test/test_ssl/test_nohttp.yml index 51d63c2..7a7ea08 100644 --- a/test/test_ssl/test_nohttp.yml +++ b/test/test_ssl/test_nohttp.yml @@ -9,7 +9,7 @@ web2: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_ssl/test_nohttps.yml b/test/test_ssl/test_nohttps.yml index 14140b4..0a6a9a5 100644 --- a/test/test_ssl/test_nohttps.yml +++ b/test/test_ssl/test_nohttps.yml @@ -9,7 +9,7 @@ web: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_ssl/test_noredirect.yml b/test/test_ssl/test_noredirect.yml index 9149a87..9ac7169 100644 --- a/test/test_ssl/test_noredirect.yml +++ b/test/test_ssl/test_noredirect.yml @@ -9,7 +9,7 @@ web3: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_ssl/test_wildcard.py b/test/test_ssl/test_wildcard.py index 9885d94..202ba24 100644 --- a/test/test_ssl/test_wildcard.py +++ b/test/test_ssl/test_wildcard.py @@ -3,21 +3,21 @@ import pytest @pytest.mark.parametrize("subdomain", ["foo", "bar"]) def test_web1_http_redirects_to_https(docker_compose, nginxproxy, subdomain): - r = nginxproxy.get("http://%s.nginx-proxy.tld/" % subdomain, allow_redirects=False) + r = nginxproxy.get(f"http://{subdomain}.nginx-proxy.tld/", allow_redirects=False) assert r.status_code == 301 assert "Location" in r.headers - assert "https://%s.nginx-proxy.tld/" % subdomain == r.headers['Location'] + assert f"https://{subdomain}.nginx-proxy.tld/" == r.headers['Location'] @pytest.mark.parametrize("subdomain", ["foo", "bar"]) def test_web1_https_is_forwarded(docker_compose, nginxproxy, subdomain): - r = nginxproxy.get("https://%s.nginx-proxy.tld/port" % subdomain, allow_redirects=False) + r = nginxproxy.get(f"https://{subdomain}.nginx-proxy.tld/port", allow_redirects=False) assert r.status_code == 200 assert "answer from port 81\n" in r.text @pytest.mark.parametrize("subdomain", ["foo", "bar"]) def test_web1_HSTS_policy_is_active(docker_compose, nginxproxy, subdomain): - r = nginxproxy.get("https://%s.nginx-proxy.tld/port" % subdomain, allow_redirects=False) + r = nginxproxy.get(f"https://{subdomain}.nginx-proxy.tld/port", allow_redirects=False) assert "answer from port 81\n" in r.text assert "Strict-Transport-Security" in r.headers diff --git a/test/test_ssl/test_wildcard.yml b/test/test_ssl/test_wildcard.yml index 4c77796..6168084 100644 --- a/test/test_ssl/test_wildcard.yml +++ b/test/test_ssl/test_wildcard.yml @@ -7,7 +7,7 @@ web1: VIRTUAL_HOST: "*.nginx-proxy.tld" sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ../lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro diff --git a/test/test_ssl/wildcard_cert_and_nohttps/docker-compose.yml b/test/test_ssl/wildcard_cert_and_nohttps/docker-compose.yml index 20cd1b2..6257aee 100644 --- a/test/test_ssl/wildcard_cert_and_nohttps/docker-compose.yml +++ b/test/test_ssl/wildcard_cert_and_nohttps/docker-compose.yml @@ -3,7 +3,7 @@ version: "3" services: proxy: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./certs:/etc/nginx/certs:ro diff --git a/test/test_ssl/wildcard_cert_and_nohttps/test_wildcard_cert_nohttps.py b/test/test_ssl/wildcard_cert_and_nohttps/test_wildcard_cert_nohttps.py index 2808dee..03af625 100644 --- a/test/test_ssl/wildcard_cert_and_nohttps/test_wildcard_cert_nohttps.py +++ b/test/test_ssl/wildcard_cert_and_nohttps/test_wildcard_cert_nohttps.py @@ -1,5 +1,5 @@ import pytest -from backports.ssl_match_hostname import CertificateError +from ssl import CertificateError from requests.exceptions import SSLError @@ -9,19 +9,19 @@ from requests.exceptions import SSLError (3, False), ]) def test_http_redirects_to_https(docker_compose, nginxproxy, subdomain, should_redirect_to_https): - r = nginxproxy.get("http://%s.web.nginx-proxy.tld/port" % subdomain) + r = nginxproxy.get(f"http://{subdomain}.web.nginx-proxy.tld/port") if should_redirect_to_https: assert len(r.history) > 0 assert r.history[0].is_redirect - assert r.history[0].headers.get("Location") == "https://%s.web.nginx-proxy.tld/port" % subdomain - assert "answer from port 8%s\n" % subdomain == r.text + assert r.history[0].headers.get("Location") == f"https://{subdomain}.web.nginx-proxy.tld/port" + assert f"answer from port 8{subdomain}\n" == r.text @pytest.mark.parametrize("subdomain", [1, 2]) def test_https_get_served(docker_compose, nginxproxy, subdomain): - r = nginxproxy.get("https://%s.web.nginx-proxy.tld/port" % subdomain, allow_redirects=False) + r = nginxproxy.get(f"https://{subdomain}.web.nginx-proxy.tld/port", allow_redirects=False) assert r.status_code == 200 - assert "answer from port 8%s\n" % subdomain == r.text + assert f"answer from port 8{subdomain}\n" == r.text def test_web3_https_is_500_and_SSL_validation_fails(docker_compose, nginxproxy): diff --git a/test/test_wildcard_host.py b/test/test_wildcard_host.py index eb8428e..a5b6633 100644 --- a/test/test_wildcard_host.py +++ b/test/test_wildcard_host.py @@ -18,9 +18,9 @@ import pytest ("web4.whatever.nginx-proxy.regexp", 84), ]) def test_wildcard_prefix(docker_compose, nginxproxy, host, expected_port): - r = nginxproxy.get("http://%s/port" % host) + r = nginxproxy.get(f"http://{host}/port") assert r.status_code == 200 - assert r.text == "answer from port %s\n" % expected_port + assert r.text == f"answer from port {expected_port}\n" @pytest.mark.parametrize("host", [ @@ -28,5 +28,5 @@ def test_wildcard_prefix(docker_compose, nginxproxy, host, expected_port): "web4.whatever.nginx-proxy.regexp-to-infinity-and-beyond" ]) def test_non_matching_host_is_503(docker_compose, nginxproxy, host): - r = nginxproxy.get("http://%s/port" % host) + r = nginxproxy.get(f"http://{host}/port") assert r.status_code == 503, r.text diff --git a/test/test_wildcard_host.yml b/test/test_wildcard_host.yml index 742a8ac..d39dad4 100644 --- a/test/test_wildcard_host.yml +++ b/test/test_wildcard_host.yml @@ -32,7 +32,7 @@ web4: sut: - image: jwilder/nginx-proxy:test + image: nginxproxy/nginx-proxy:test volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./lib/ssl/dhparam.pem:/etc/nginx/dhparam/dhparam.pem:ro