diff --git a/.gitignore b/.gitignore index 0b3700d..675cff8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ **/__pycache__/ **/.cache/ +*.pyc \ No newline at end of file diff --git a/README.md b/README.md index ed8540e..6a7701e 100644 --- a/README.md +++ b/README.md @@ -135,13 +135,17 @@ First start nginx with a volume: $ docker run -d -p 80:80 --name nginx -v /tmp/nginx:/etc/nginx/conf.d -t nginx -Then start the docker-gen container with the shared volume and template: +Then start the docker-gen container with: +- the `NGINX_CONTAINER` environment variable set to the name of the container running nginx +- the shared volume +- the template ``` $ docker run --volumes-from nginx \ + -e NGINX_CONTAINER=nginx \ -v /var/run/docker.sock:/tmp/docker.sock:ro \ -v $(pwd):/etc/docker-gen/templates \ - -t jwilder/docker-gen -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf + -t jwilder/docker-gen -notify-sighup nginx -only-exposed -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf ``` Finally, start your containers with `VIRTUAL_HOST` environment variables. diff --git a/docker-compose-separate-containers.yml b/docker-compose-separate-containers.yml index a4edb94..32e4169 100644 --- a/docker-compose-separate-containers.yml +++ b/docker-compose-separate-containers.yml @@ -10,12 +10,14 @@ services: dockergen: image: jwilder/docker-gen - command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf + command: -notify-sighup nginx -only-exposed -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf volumes_from: - nginx volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl + environment: + - NGINX_CONTAINER=nginx whoami: image: jwilder/whoami diff --git a/nginx.tmpl b/nginx.tmpl index a5b1d32..4c94adb 100644 --- a/nginx.tmpl +++ b/nginx.tmpl @@ -1,4 +1,23 @@ {{ $CurrentContainer := where $ "ID" .Docker.CurrentContainerID | first }} +{{ $NginxContainerName := coalesce $.Env.NGINX_CONTAINER $CurrentContainer.Name }} +{{ $NginxContainer := where $ "Name" $NginxContainerName | first }} +# ----------------------------------------------------------------------------- +# $.Env.NGINX_CONTAINER: {{ $.Env.NGINX_CONTAINER }} +# Docker-gen container name: {{ $CurrentContainer.Name }} +# Nginx container name: {{ $NginxContainerName }} +# Nginx container found: {{ if $NginxContainer }}yes{{ else }}no{{ end }} +# Nginx networks: {{ json $NginxContainer.Networks }} +# ----------------------------------------------------------------------------- + +{{ if not $NginxContainer }} +############################################################################### +# # +# Could not determine which container is running nginx. # +# Make sure to provide a correct value for the `NGINX_CONTAINER` environment # +# variable. # +# # +############################################################################### +{{ end }} {{ define "upstream" }} {{ if .Address }} @@ -106,7 +125,7 @@ upstream {{ $upstream_name }} { {{ range $container := $containers }} {{ $addrLen := len $container.Addresses }} - {{ range $knownNetwork := $CurrentContainer.Networks }} + {{ range $knownNetwork := $NginxContainer.Networks }} {{ range $containerNetwork := $container.Networks }} {{ if eq $knownNetwork.Name $containerNetwork.Name }} ## Can be connect with "{{ $containerNetwork.Name }}" network @@ -268,6 +287,5 @@ server { ssl_certificate_key /etc/nginx/certs/default.key; } {{ end }} - {{ end }} {{ end }} diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..ac9a9c5 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +/nginx.tmpl \ No newline at end of file diff --git a/test/README.md b/test/README.md index 9d7a57c..d91246f 100644 --- a/test/README.md +++ b/test/README.md @@ -47,6 +47,7 @@ This test suite uses [pytest](http://doc.pytest.org/en/latest/). The [conftest.p - docker_compose - nginxproxy +- nginx_tmpl ### docker_compose fixture @@ -96,6 +97,10 @@ Furthermore, the nginxproxy methods accept an additional keyword parameter: `ipv assert r.text == "answer from port 81\n" +### nginx_tmpl fixture + +The `nginx_tmpl` fixture extracts the `nginx.tmpl` template file from the `jwilder/nginx-proxy:test` image and copy it into the `test` directory. This is useful for tests which requires to mount the template file into a container as a volume. + ### The web docker image diff --git a/test/conftest.py b/test/conftest.py index fcff6ea..44df3f7 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -370,7 +370,8 @@ def disconnect_from_network(network=None): def connect_to_all_networks(): """ - If we are running from a container, connect our container to all current docker networks. + If we are running from a container, connect our container to all current docker networks but the 'bridge' and + 'none' networks. :return: a list of networks we connected to """ @@ -378,7 +379,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 = filter(lambda network: len(network.containers) > 0 and network.name not in ('bridge', 'none'), docker_client.networks.list()) return [connect_to_network(network) for network in networks] @@ -429,6 +430,27 @@ def nginxproxy(): yield requests_for_docker() +@pytest.yield_fixture(scope="module") +def nginx_tmpl(): + """ + pytest fixture which extracts the the nginx config template from + the jwilder/nginx-proxy:test image into the test directory + """ + script_dir = os.path.dirname(__file__) + logging.info("extracting nginx.tmpl from jwilder/nginx-proxy:test") + 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)) + yield os.path.join(script_dir, 'nginx.tmpl') + logging.info("removing nginx.tmpl") + os.remove(os.path.join(script_dir, "nginx.tmpl")) + + ############################################################################### # # Py.test hooks diff --git a/test/test_dockergen/.gitignore b/test/test_dockergen/.gitignore deleted file mode 100644 index 98c0b06..0000000 --- a/test/test_dockergen/.gitignore +++ /dev/null @@ -1 +0,0 @@ -nginx.tmpl \ No newline at end of file diff --git a/test/test_dockergen/test_dockergen_v2.py b/test/test_dockergen/test_dockergen_v2.py deleted file mode 100644 index c797d0c..0000000 --- a/test/test_dockergen/test_dockergen_v2.py +++ /dev/null @@ -1,38 +0,0 @@ -import os -import docker -import logging -import pytest - - -@pytest.yield_fixture(scope="module") -def nginx_tmpl(): - """ - pytest fixture which extracts the the nginx config template from - the jwilder/nginx-proxy:test image - """ - script_dir = os.path.dirname(__file__) - logging.info("extracting nginx.tmpl from jwilder/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)) - yield - logging.info("removing nginx.tmpl") - os.remove(os.path.join(script_dir, "nginx.tmpl")) - - -def test_unknown_virtual_host_is_503(nginx_tmpl, docker_compose, nginxproxy): - r = nginxproxy.get("http://unknown.nginx.container.docker/") - assert r.status_code == 503 - - -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] diff --git a/test/test_dockergen_v2/test_dockergen_v2.py b/test/test_dockergen_v2/test_dockergen_v2.py new file mode 100644 index 0000000..9eb6481 --- /dev/null +++ b/test/test_dockergen_v2/test_dockergen_v2.py @@ -0,0 +1,18 @@ +from time import sleep + + +def test_nginx_is_running(nginx_tmpl, docker_compose): + sleep(3) + assert docker_compose.containers.get("nginx").status == "running" + + +def test_unknown_virtual_host_is_503(nginx_tmpl, docker_compose, nginxproxy): + r = nginxproxy.get("http://unknown.nginx.container.docker/") + assert r.status_code == 503 + + +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] diff --git a/test/test_dockergen/test_dockergen_v2.yml b/test/test_dockergen_v2/test_dockergen_v2.yml similarity index 89% rename from test/test_dockergen/test_dockergen_v2.yml rename to test/test_dockergen_v2/test_dockergen_v2.yml index 0d2cab0..254afa5 100644 --- a/test/test_dockergen/test_dockergen_v2.yml +++ b/test/test_dockergen_v2/test_dockergen_v2.yml @@ -14,7 +14,7 @@ services: - nginx volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - - ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl + - ../nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl web: image: web diff --git a/test/test_dockergen/test_dockergen_v3.py b/test/test_dockergen_v3/test_dockergen_v3.py similarity index 53% rename from test/test_dockergen/test_dockergen_v3.py rename to test/test_dockergen_v3/test_dockergen_v3.py index 48b7bfa..466da07 100644 --- a/test/test_dockergen/test_dockergen_v3.py +++ b/test/test_dockergen_v3/test_dockergen_v3.py @@ -1,6 +1,5 @@ -import os +from time import sleep import docker -import logging import pytest @@ -27,26 +26,9 @@ pytestmark = pytest.mark.skipif( reason="Docker compose syntax v3 requires docker engine v1.13 or later (got %s)" % raw_version) -@pytest.yield_fixture(scope="module") -def nginx_tmpl(): - """ - pytest fixture which extracts the the nginx config template from - the jwilder/nginx-proxy:test image - """ - script_dir = os.path.dirname(__file__) - logging.info("extracting nginx.tmpl from jwilder/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)) - yield - logging.info("removing nginx.tmpl") - os.remove(os.path.join(script_dir, "nginx.tmpl")) +def test_nginx_is_running(nginx_tmpl, docker_compose): + sleep(3) + assert docker_compose.containers.get("nginx").status == "running" def test_unknown_virtual_host_is_503(nginx_tmpl, docker_compose, nginxproxy): @@ -59,8 +41,3 @@ def test_forwards_to_whoami(nginx_tmpl, docker_compose, nginxproxy): assert r.status_code == 200 whoami_container = docker_compose.containers.get("whoami") assert r.text == "I'm %s\n" % whoami_container.id[:12] - - -if __name__ == '__main__': - import doctest - doctest.testmod() diff --git a/test/test_dockergen/test_dockergen_v3.yml b/test/test_dockergen_v3/test_dockergen_v3.yml similarity index 90% rename from test/test_dockergen/test_dockergen_v3.yml rename to test/test_dockergen_v3/test_dockergen_v3.yml index 643f49b..e4d4140 100644 --- a/test/test_dockergen/test_dockergen_v3.yml +++ b/test/test_dockergen_v3/test_dockergen_v3.yml @@ -1,4 +1,5 @@ version: '3' + services: nginx: image: nginx @@ -11,7 +12,7 @@ services: command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf volumes: - /var/run/docker.sock:/tmp/docker.sock:ro - - ./nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl + - ../nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl - nginx_conf:/etc/nginx/conf.d web: diff --git a/test/test_separate_no_net/test_no_network_for_dockergen.py b/test/test_separate_no_net/test_no_network_for_dockergen.py new file mode 100644 index 0000000..9eb6481 --- /dev/null +++ b/test/test_separate_no_net/test_no_network_for_dockergen.py @@ -0,0 +1,18 @@ +from time import sleep + + +def test_nginx_is_running(nginx_tmpl, docker_compose): + sleep(3) + assert docker_compose.containers.get("nginx").status == "running" + + +def test_unknown_virtual_host_is_503(nginx_tmpl, docker_compose, nginxproxy): + r = nginxproxy.get("http://unknown.nginx.container.docker/") + assert r.status_code == 503 + + +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] diff --git a/test/test_separate_no_net/test_no_network_for_dockergen.yml b/test/test_separate_no_net/test_no_network_for_dockergen.yml new file mode 100644 index 0000000..2409689 --- /dev/null +++ b/test/test_separate_no_net/test_no_network_for_dockergen.yml @@ -0,0 +1,50 @@ +# In this compose file, we define a dockergen container which has no network. +# This should not be an issue since the docker-gen process is not binding to any port or isn't making any +# network connection to any other container. + +--- + +version: '2' + +networks: + nginx-net: {} + + +volumes: + nginx_conf: {} + nginx_certs: {} + +services: + nginx: + image: nginx + container_name: nginx + volumes: + - nginx_conf:/etc/nginx/conf.d + - nginx_certs:/etc/nginx/certs + networks: + - nginx-net + + dockergen: + image: jwilder/docker-gen + command: -notify-sighup nginx -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf + volumes_from: + - nginx + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - nginx_conf:/etc/nginx/conf.d + - nginx_certs:/etc/nginx/certs + - ../nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl + environment: + NGINX_CONTAINER: nginx + networks: [] + + web: + image: web + container_name: whoami + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: whoami.nginx.container.docker + networks: + - nginx-net \ No newline at end of file diff --git a/test/test_separate_only_exposed/test_only-exposed.py b/test/test_separate_only_exposed/test_only-exposed.py new file mode 100644 index 0000000..9eb6481 --- /dev/null +++ b/test/test_separate_only_exposed/test_only-exposed.py @@ -0,0 +1,18 @@ +from time import sleep + + +def test_nginx_is_running(nginx_tmpl, docker_compose): + sleep(3) + assert docker_compose.containers.get("nginx").status == "running" + + +def test_unknown_virtual_host_is_503(nginx_tmpl, docker_compose, nginxproxy): + r = nginxproxy.get("http://unknown.nginx.container.docker/") + assert r.status_code == 503 + + +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] diff --git a/test/test_separate_only_exposed/test_only-exposed.yml b/test/test_separate_only_exposed/test_only-exposed.yml new file mode 100644 index 0000000..1741cae --- /dev/null +++ b/test/test_separate_only_exposed/test_only-exposed.yml @@ -0,0 +1,45 @@ +# In this compose file we define a dockergen container which is running the docker-gen process with the +# `-only-exposed` option. This should not be an issue since the template for the nginx config file should only +# have to deal with upstream containers which are required to have at least one port exposed, and since the nginx +# container with no exposed port makes no sense. +--- + +version: '2' + +networks: + default: {} + + +volumes: + nginx_conf: {} + nginx_certs: {} + +services: + nginx: + image: nginx + container_name: nginx + volumes: + - nginx_conf:/etc/nginx/conf.d + - nginx_certs:/etc/nginx/certs + + dockergen: + image: jwilder/docker-gen + command: -notify-sighup nginx -only-exposed -watch /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf + volumes_from: + - nginx + volumes: + - /var/run/docker.sock:/tmp/docker.sock:ro + - nginx_conf:/etc/nginx/conf.d + - nginx_certs:/etc/nginx/certs + - ../nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl + environment: + NGINX_CONTAINER: nginx + + web: + image: web + container_name: whoami + expose: + - "80" + environment: + WEB_PORTS: 80 + VIRTUAL_HOST: whoami.nginx.container.docker \ No newline at end of file