feat: pre bundled dockergen w/ nginx-proxy template image
This commit is contained in:
parent
c60eff5d16
commit
a67aff92e9
7 changed files with 131 additions and 31 deletions
21
.github/workflows/build-publish.yml
vendored
21
.github/workflows/build-publish.yml
vendored
|
@ -23,7 +23,7 @@ jobs:
|
|||
name: Build and publish image
|
||||
strategy:
|
||||
matrix:
|
||||
base: [alpine, debian]
|
||||
flavor: [alpine, debian, dockergen]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
@ -37,7 +37,7 @@ jobs:
|
|||
|
||||
- name: Retrieve docker-gen version
|
||||
id: docker-gen_version
|
||||
run: sed -n -e 's;^FROM nginxproxy/docker-gen:\([0-9.]*\).*;VERSION=\1;p' Dockerfile.${{ matrix.base }} >> "$GITHUB_OUTPUT"
|
||||
run: sed -n -e 's;^FROM docker.io/nginxproxy/docker-gen:\([0-9.]*\).*;VERSION=\1;p' Dockerfile.${{ matrix.flavor }} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Get Docker tags
|
||||
id: docker_meta
|
||||
|
@ -48,12 +48,15 @@ jobs:
|
|||
nginxproxy/nginx-proxy
|
||||
jwilder/nginx-proxy
|
||||
tags: |
|
||||
type=semver,pattern={{version}},enable=${{ matrix.base == 'debian' }}
|
||||
type=semver,pattern={{major}}.{{minor}},enable=${{ matrix.base == 'debian' }}
|
||||
type=semver,suffix=-alpine,pattern={{version}},enable=${{ matrix.base == 'alpine' }}
|
||||
type=semver,suffix=-alpine,pattern={{major}}.{{minor}},enable=${{ matrix.base == 'alpine' }}
|
||||
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' && matrix.base == 'debian' }}
|
||||
type=raw,value=alpine,enable=${{ github.ref == 'refs/heads/main' && matrix.base == 'alpine' }}
|
||||
type=semver,pattern={{version}},enable=${{ matrix.flavor == 'debian' }}
|
||||
type=semver,pattern={{major}}.{{minor}},enable=${{ matrix.flavor == 'debian' }}
|
||||
type=semver,suffix=-alpine,pattern={{version}},enable=${{ matrix.flavor == 'alpine' }}
|
||||
type=semver,suffix=-alpine,pattern={{major}}.{{minor}},enable=${{ matrix.flavor == 'alpine' }}
|
||||
type=semver,suffix=-dockergen,pattern={{version}},enable=${{ matrix.flavor == 'dockergen' }}
|
||||
type=semver,suffix=-dockergen,pattern={{major}}.{{minor}},enable=${{ matrix.flavor == 'dockergen' }}
|
||||
type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' && matrix.flavor == 'debian' }}
|
||||
type=raw,value=alpine,enable=${{ github.ref == 'refs/heads/main' && matrix.flavor == 'alpine' }}
|
||||
type=raw,value=dockergen,enable=${{ github.ref == 'refs/heads/main' && matrix.flavor == 'dockergen' }}
|
||||
labels: |
|
||||
org.opencontainers.image.authors=Nicolas Duchon <nicolas.duchon@gmail.com> (@buchdag), Jason Wilder
|
||||
org.opencontainers.image.version=${{ steps.nginx-proxy_version.outputs.VERSION }}
|
||||
|
@ -84,7 +87,7 @@ jobs:
|
|||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile.${{ matrix.base }}
|
||||
file: Dockerfile.${{ matrix.flavor }}
|
||||
build-args: |
|
||||
NGINX_PROXY_VERSION=${{ steps.nginx-proxy_version.outputs.VERSION }}
|
||||
DOCKER_GEN_VERSION=${{ steps.docker-gen_version.outputs.VERSION }}
|
||||
|
|
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
|
@ -20,7 +20,7 @@ jobs:
|
|||
|
||||
strategy:
|
||||
matrix:
|
||||
base_docker_image: [alpine, debian]
|
||||
flavor: [alpine, debian, dockergen]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
@ -43,8 +43,10 @@ jobs:
|
|||
run: make build-webserver
|
||||
|
||||
- name: Build Docker nginx proxy test image
|
||||
run: make build-nginx-proxy-test-${{ matrix.base_docker_image }}
|
||||
run: make build-nginx-proxy-test-${{ matrix.flavor }}
|
||||
|
||||
- name: Run tests
|
||||
run: pytest
|
||||
working-directory: test
|
||||
env:
|
||||
COMPOSE_PROFILES: ${{ matrix.flavor == 'dockergen' && 'separateContainers' || 'singleContainer' }}
|
||||
|
|
18
Dockerfile.dockergen
Normal file
18
Dockerfile.dockergen
Normal file
|
@ -0,0 +1,18 @@
|
|||
FROM docker.io/nginxproxy/docker-gen:0.14.4
|
||||
|
||||
ARG NGINX_PROXY_VERSION
|
||||
ENV NGINX_PROXY_VERSION=${NGINX_PROXY_VERSION} \
|
||||
DOCKER_HOST=unix:///tmp/docker.sock \
|
||||
DHPARAM_SKIP=true \
|
||||
NGINX_CONTAINER_NAME=nginx-proxy
|
||||
|
||||
# Install dependencies
|
||||
RUN apk add --no-cache --virtual .run-deps bash
|
||||
|
||||
RUN mkdir -p '/etc/nginx/conf.d'
|
||||
|
||||
COPY app nginx.tmpl LICENSE /app/
|
||||
WORKDIR /app/
|
||||
|
||||
ENTRYPOINT ["/app/docker-entrypoint.sh"]
|
||||
CMD ["docker-gen", "-notify-sighup", "$NGINX_CONTAINER_NAME", "-watch", "/app/nginx.tmpl", "/etc/nginx/conf.d/default.conf"]
|
11
Makefile
11
Makefile
|
@ -11,10 +11,19 @@ build-nginx-proxy-test-debian:
|
|||
build-nginx-proxy-test-alpine:
|
||||
docker build --pull --build-arg NGINX_PROXY_VERSION="test" -f Dockerfile.alpine -t nginxproxy/nginx-proxy:test .
|
||||
|
||||
build-nginx-proxy-test-dockergen:
|
||||
docker build --pull --build-arg NGINX_PROXY_VERSION="test" -f Dockerfile.dockergen -t nginxproxy/nginx-proxy:test-dockergen .
|
||||
|
||||
test-debian: export COMPOSE_PROFILES = singleContainer
|
||||
test-debian: build-webserver build-nginx-proxy-test-debian
|
||||
test/pytest.sh
|
||||
|
||||
test-alpine: export COMPOSE_PROFILES = singleContainer
|
||||
test-alpine: build-webserver build-nginx-proxy-test-alpine
|
||||
test/pytest.sh
|
||||
|
||||
test: test-debian test-alpine
|
||||
test-dockergen: export COMPOSE_PROFILES = separateContainers
|
||||
test-dockergen: build-webserver build-nginx-proxy-test-docker-gen
|
||||
test/pytest.sh
|
||||
|
||||
test: test-debian test-alpine test-dockergen
|
||||
|
|
|
@ -101,7 +101,7 @@ function _setup_dhparam() {
|
|||
}
|
||||
|
||||
# Run the init logic if the default CMD was provided
|
||||
if [[ $* == 'forego start -r' ]]; then
|
||||
if [[ $* == "forego start -r" ]] || [[ $* =~ "docker-gen -notify-sighup" ]]; then
|
||||
_print_version
|
||||
|
||||
_check_unix_socket
|
||||
|
@ -116,6 +116,11 @@ if [[ $* == 'forego start -r' ]]; then
|
|||
Warning: The default value of TRUST_DOWNSTREAM_PROXY might change to "false" in a future version of nginx-proxy. If you require TRUST_DOWNSTREAM_PROXY to be enabled, explicitly set it to "true".
|
||||
EOT
|
||||
fi
|
||||
|
||||
if [[ $3 == "\$NGINX_CONTAINER_NAME" && -n "$NGINX_CONTAINER_NAME" ]]; then
|
||||
# change the value of $3 to the expanded $NGINX_CONTAINER_NAME variable
|
||||
set -- "${@:1:2}" "$NGINX_CONTAINER_NAME" "${@:4}"
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
|
|
|
@ -27,6 +27,9 @@ PYTEST_RUNNING_IN_CONTAINER = os.environ.get('PYTEST_RUNNING_IN_CONTAINER') == "
|
|||
FORCE_CONTAINER_IPV6 = False # ugly global state to consider containers' IPv6 address instead of IPv4
|
||||
|
||||
DOCKER_COMPOSE = os.environ.get('DOCKER_COMPOSE', 'docker compose')
|
||||
COMPOSE_PROFILES = os.environ.get('COMPOSE_PROFILES', 'singleContainer')
|
||||
IMAGE_TAG = "test-dockergen" if COMPOSE_PROFILES == "separateContainers" else "test"
|
||||
|
||||
|
||||
docker_client = docker.from_env()
|
||||
|
||||
|
@ -75,11 +78,11 @@ class requests_for_docker(object):
|
|||
"""
|
||||
Return list of containers
|
||||
"""
|
||||
nginx_proxy_containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/nginx-proxy:test"})
|
||||
nginx_proxy_containers = docker_client.containers.list(filters={"ancestor": f"nginxproxy/nginx-proxy:{IMAGE_TAG}"})
|
||||
if len(nginx_proxy_containers) > 1:
|
||||
pytest.fail("Too many running nginxproxy/nginx-proxy:test containers", pytrace=False)
|
||||
pytest.fail(f"Too many running nginxproxy/nginx-proxy:{IMAGE_TAG} containers", pytrace=False)
|
||||
elif len(nginx_proxy_containers) == 0:
|
||||
pytest.fail("No running nginxproxy/nginx-proxy:test container", pytrace=False)
|
||||
pytest.fail(f"No running nginxproxy/nginx-proxy:{IMAGE_TAG} container", pytrace=False)
|
||||
return nginx_proxy_containers
|
||||
|
||||
def get_conf(self):
|
||||
|
@ -188,7 +191,7 @@ def container_ipv6(container):
|
|||
return net_info[network_name]["GlobalIPv6Address"]
|
||||
|
||||
|
||||
def nginx_proxy_dns_resolver(domain_name):
|
||||
def nginx_proxy_single_container_dns_resolver(domain_name):
|
||||
"""
|
||||
if "nginx-proxy" if found in host, return the ip address of the docker container
|
||||
issued from the docker image nginxproxy/nginx-proxy:test.
|
||||
|
@ -196,21 +199,44 @@ def nginx_proxy_dns_resolver(domain_name):
|
|||
:return: IP or None
|
||||
"""
|
||||
log = logging.getLogger('DNS')
|
||||
log.debug(f"nginx_proxy_dns_resolver({domain_name!r})")
|
||||
log.debug(f"nginx_proxy_single_container_dns_resolver({domain_name!r})")
|
||||
if 'nginx-proxy' in domain_name:
|
||||
nginxproxy_containers = docker_client.containers.list(filters={"status": "running", "ancestor": "nginxproxy/nginx-proxy:test"})
|
||||
if len(nginxproxy_containers) == 0:
|
||||
log.warn(f"no container found from image nginxproxy/nginx-proxy:test while resolving {domain_name!r}")
|
||||
log.info(f"no container found from image nginxproxy/nginx-proxy:test while resolving {domain_name!r}")
|
||||
exited_nginxproxy_containers = docker_client.containers.list(filters={"status": "exited", "ancestor": "nginxproxy/nginx-proxy:test"})
|
||||
if len(exited_nginxproxy_containers) > 0:
|
||||
exited_nginxproxy_container_logs = exited_nginxproxy_containers[0].logs()
|
||||
log.warn(f"nginxproxy/nginx-proxy:test container might have exited unexpectedly. Container logs: " + "\n" + exited_nginxproxy_container_logs.decode())
|
||||
log.warning(f"nginxproxy/nginx-proxy:test container might have exited unexpectedly. Container logs: " + "\n" + exited_nginxproxy_container_logs.decode())
|
||||
return
|
||||
nginxproxy_container = nginxproxy_containers[0]
|
||||
ip = container_ip(nginxproxy_container)
|
||||
log.info(f"resolving domain name {domain_name!r} as IP address {ip} of nginx-proxy container {nginxproxy_container.name}")
|
||||
return ip
|
||||
|
||||
def nginx_proxy_separate_containers_dns_resolver(domain_name):
|
||||
"""
|
||||
if "nginx-proxy" if found in host, return the ip address of the docker container
|
||||
labeled with "com.github.nginx-proxy.nginx-proxy.nginx".
|
||||
|
||||
:return: IP or None
|
||||
"""
|
||||
log = logging.getLogger('DNS')
|
||||
log.debug(f"nginx_proxy_separate_containers_dns_resolver({domain_name!r})")
|
||||
if 'nginx-proxy' in domain_name:
|
||||
nginx_containers = docker_client.containers.list(filters={"status": "running", "label": "com.github.nginx-proxy.nginx-proxy.nginx"})
|
||||
if len(nginx_containers) == 0:
|
||||
log.info(f"no container labeled with com.github.nginx-proxy.nginx-proxy.nginx found while resolving {domain_name!r}")
|
||||
exited_nginx_containers = docker_client.containers.list(filters={"status": "exited", "label": "com.github.nginx-proxy.nginx-proxy.nginx"})
|
||||
if len(exited_nginx_containers) > 0:
|
||||
exited_nginx_container_logs = exited_nginx_containers[0].logs()
|
||||
log.warning(f"nginx container might have exited unexpectedly. Container logs: " + "\n" + exited_nginx_container_logs.decode())
|
||||
return
|
||||
nginx_container = nginx_containers[0]
|
||||
ip = container_ip(nginx_container)
|
||||
log.info(f"resolving domain name {domain_name!r} as IP address {ip} of nginx container {nginx_container.name}")
|
||||
return ip
|
||||
|
||||
def docker_container_dns_resolver(domain_name):
|
||||
"""
|
||||
if domain name is of the form "XXX.container.docker" or "anything.XXX.container.docker", return the ip address of the docker container
|
||||
|
@ -231,7 +257,7 @@ def docker_container_dns_resolver(domain_name):
|
|||
try:
|
||||
container = docker_client.containers.get(container_name)
|
||||
except docker.errors.NotFound:
|
||||
log.warn(f"container named {container_name!r} not found while resolving {domain_name!r}")
|
||||
log.warning(f"container named {container_name!r} not found while resolving {domain_name!r}")
|
||||
return
|
||||
log.debug(f"container {container.name!r} found ({container.short_id})")
|
||||
|
||||
|
@ -244,7 +270,8 @@ def monkey_patch_urllib_dns_resolver():
|
|||
"""
|
||||
Alter the behavior of the urllib DNS resolver so that any domain name
|
||||
containing substring 'nginx-proxy' will resolve to the IP address
|
||||
of the container created from image 'nginxproxy/nginx-proxy:test'.
|
||||
of the container created from image 'nginxproxy/nginx-proxy:test' or
|
||||
labeled with 'com.github.nginx-proxy.nginx-proxy.nginx'.
|
||||
"""
|
||||
prv_getaddrinfo = socket.getaddrinfo
|
||||
dns_cache = {}
|
||||
|
@ -258,7 +285,9 @@ def monkey_patch_urllib_dns_resolver():
|
|||
pytest.skip("This system does not support IPv6")
|
||||
|
||||
# custom DNS resolvers
|
||||
ip = nginx_proxy_dns_resolver(args[0])
|
||||
ip = nginx_proxy_single_container_dns_resolver(args[0])
|
||||
if ip is None:
|
||||
ip = nginx_proxy_separate_containers_dns_resolver(args[0])
|
||||
if ip is None:
|
||||
ip = docker_container_dns_resolver(args[0])
|
||||
if ip is not None:
|
||||
|
@ -319,10 +348,11 @@ def docker_compose_down(compose_file='docker-compose.yml'):
|
|||
|
||||
def wait_for_nginxproxy_to_be_ready():
|
||||
"""
|
||||
If one (and only one) container started from image nginxproxy/nginx-proxy:test is found,
|
||||
wait for its log to contain substring "Watching docker events"
|
||||
If one (and only one) container started from image nginxproxy/nginx-proxy:test
|
||||
or nginxproxy/nginx-proxy:test-dockergen is found, wait for its log to contain
|
||||
substring "Watching docker events"
|
||||
"""
|
||||
containers = docker_client.containers.list(filters={"ancestor": "nginxproxy/nginx-proxy:test"})
|
||||
containers = docker_client.containers.list(filters={"ancestor": f"nginxproxy/nginx-proxy:{IMAGE_TAG}"})
|
||||
if len(containers) != 1:
|
||||
return
|
||||
container = containers[0]
|
||||
|
@ -371,7 +401,7 @@ def connect_to_network(network):
|
|||
try:
|
||||
my_container = docker_client.containers.get(test_container)
|
||||
except docker.errors.NotFound:
|
||||
logging.warn(f"container {test_container} not found")
|
||||
logging.warning(f"container {test_container} not found")
|
||||
return
|
||||
|
||||
# figure out our container networks
|
||||
|
@ -399,7 +429,7 @@ def disconnect_from_network(network=None):
|
|||
try:
|
||||
my_container = docker_client.containers.get(test_container)
|
||||
except docker.errors.NotFound:
|
||||
logging.warn(f"container {test_container} not found")
|
||||
logging.warning(f"container {test_container} not found")
|
||||
return
|
||||
|
||||
# figure out our container networks
|
||||
|
@ -527,7 +557,11 @@ def acme_challenge_path():
|
|||
def pytest_runtest_logreport(report):
|
||||
if report.failed:
|
||||
if isinstance(report.longrepr, ReprExceptionInfo):
|
||||
test_containers = docker_client.containers.list(all=True, filters={"ancestor": "nginxproxy/nginx-proxy:test"})
|
||||
nginx_containers = docker_client.containers.list(all=True, filters={"label": "com.github.nginx-proxy.nginx-proxy.nginx"})
|
||||
for container in nginx_containers:
|
||||
report.longrepr.addsection('nginx container logs', container.logs())
|
||||
|
||||
test_containers = docker_client.containers.list(all=True, filters={"ancestor": f"nginxproxy/nginx-proxy:{IMAGE_TAG}"})
|
||||
for container in test_containers:
|
||||
report.longrepr.addsection('nginx-proxy logs', container.logs())
|
||||
report.longrepr.addsection('nginx-proxy conf', get_nginx_conf_from_container(container))
|
||||
|
@ -553,9 +587,9 @@ def pytest_runtest_setup(item):
|
|||
###############################################################################
|
||||
|
||||
try:
|
||||
docker_client.images.get('nginxproxy/nginx-proxy:test')
|
||||
docker_client.images.get(f"nginxproxy/nginx-proxy:{IMAGE_TAG}")
|
||||
except docker.errors.ImageNotFound:
|
||||
pytest.exit("The docker image 'nginxproxy/nginx-proxy:test' is missing")
|
||||
pytest.exit(f"The docker image 'nginxproxy/nginx-proxy:{IMAGE_TAG}' is missing")
|
||||
|
||||
if Version(docker.__version__) < Version("7.0.0"):
|
||||
pytest.exit("This test suite is meant to work with the python docker module v7.0.0 or later")
|
||||
|
|
|
@ -2,8 +2,13 @@ networks:
|
|||
netA:
|
||||
netB:
|
||||
|
||||
volumes:
|
||||
nginx_conf:
|
||||
|
||||
services:
|
||||
reverseproxy:
|
||||
profiles:
|
||||
- singleContainer
|
||||
container_name: reverseproxy
|
||||
networks:
|
||||
- netA
|
||||
|
@ -11,6 +16,30 @@ services:
|
|||
volumes:
|
||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||
|
||||
reverseproxynginx:
|
||||
profiles:
|
||||
- separateContainers
|
||||
container_name: reverseproxy
|
||||
networks:
|
||||
- netA
|
||||
image: nginx:alpine
|
||||
volumes:
|
||||
- nginx_conf:/etc/nginx/conf.d:ro
|
||||
labels:
|
||||
- "com.github.nginx-proxy.nginx-proxy.nginx"
|
||||
|
||||
docker-gen:
|
||||
profiles:
|
||||
- separateContainers
|
||||
networks:
|
||||
- netA
|
||||
image: nginxproxy/nginx-proxy:test-dockergen
|
||||
volumes:
|
||||
- /var/run/docker.sock:/tmp/docker.sock:ro
|
||||
- nginx_conf:/etc/nginx/conf.d
|
||||
environment:
|
||||
NGINX_CONTAINER_NAME: reverseproxy
|
||||
|
||||
webA:
|
||||
networks:
|
||||
- netA
|
||||
|
|
Loading…
Reference in a new issue