fix template when running docker-gen and nginx in separate containers
Since commit 658e20f, the template makes the assumption that the container running docker-gen is the container running nginx while checking that upstream containers are reachable.
By introducint the `NGINX_CONTAINER` environment variable, users are now able to indicate which container is actually running nginx when running docker-gen and nginx in separated containers.
This commit is contained in:
parent
d5deff21c5
commit
5c2f50402a
17 changed files with 216 additions and 75 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,2 +1,3 @@
|
|||
**/__pycache__/
|
||||
**/.cache/
|
||||
*.pyc
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
22
nginx.tmpl
22
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 }}
|
||||
|
|
|
|||
1
test/.gitignore
vendored
Normal file
1
test/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/nginx.tmpl
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
1
test/test_dockergen/.gitignore
vendored
1
test/test_dockergen/.gitignore
vendored
|
|
@ -1 +0,0 @@
|
|||
nginx.tmpl
|
||||
|
|
@ -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]
|
||||
18
test/test_dockergen_v2/test_dockergen_v2.py
Normal file
18
test/test_dockergen_v2/test_dockergen_v2.py
Normal file
|
|
@ -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]
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -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:
|
||||
18
test/test_separate_no_net/test_no_network_for_dockergen.py
Normal file
18
test/test_separate_no_net/test_no_network_for_dockergen.py
Normal file
|
|
@ -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]
|
||||
50
test/test_separate_no_net/test_no_network_for_dockergen.yml
Normal file
50
test/test_separate_no_net/test_no_network_for_dockergen.yml
Normal file
|
|
@ -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
|
||||
18
test/test_separate_only_exposed/test_only-exposed.py
Normal file
18
test/test_separate_only_exposed/test_only-exposed.py
Normal file
|
|
@ -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]
|
||||
45
test/test_separate_only_exposed/test_only-exposed.yml
Normal file
45
test/test_separate_only_exposed/test_only-exposed.yml
Normal file
|
|
@ -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
|
||||
Loading…
Reference in a new issue