Browse Source

Add support for load-balancing containers.

Closes csmith/docker-automatic-nginx-letsencrypt#8

This changes the generated config to create an `upstream` block for each
service and then reference that within the `server` block.

Multiple containers can be grouped together (so that all their hosts are
added within the same `upstream` block) by adding a new label to the container
with the key "com.chameth.proxy.loadbalance" and the value as the name of the
`upstream` block (This will be prefixed with lb_ for uniqueness)

If no `loadbalance` label is provided, then the container name is used for
the `upstream` block name (prefixed with `ct_` for uniqueness)

The `server` block (which defines the certificate name and the vhosts) is
built based on the first container found with a given `upstream` block name,
so it is reccomended that all containers that are being balanced together
should have the same vhosts.
pull/4/head
Shane Mc Cormack 6 years ago
parent
commit
eb038ebaa0
3 changed files with 25 additions and 10 deletions
  1. 2
    0
      README.md
  2. 15
    8
      generate.py
  3. 8
    2
      nginx.tpl

+ 2
- 0
README.md View File

@@ -26,6 +26,8 @@ are understood:
26 26
 * `com.chameth.vhost=<host>` -- the virtual host that the proxy will accept
27 27
   connections on. You can specify alternate hosts/aliases by separating them
28 28
   with commas.
29
+* `com.chameth.proxy.loadbalance=<gruop name>` -- Load balance this container
30
+  with other containers that have the same group name.
29 31
 
30 32
 ## Usage
31 33
 

+ 15
- 8
generate.py View File

@@ -22,23 +22,30 @@ fetcher = etcdlib.Connection(args.etcd_host, args.etcd_port, args.etcd_prefix)
22 22
 
23 23
 while True:
24 24
   wroteConfig = False;
25
-  services = []
25
+  services = {}
26 26
   domains = {k: v.split(',') for k, v in fetcher.get_label('com.chameth.vhost').items()}
27 27
   protocols = fetcher.get_label('com.chameth.proxy.protocol')
28 28
   defaults = fetcher.get_label('com.chameth.proxy.default')
29
+  loadbalance = fetcher.get_label('com.chameth.proxy.loadbalance')
29 30
   for container, values in fetcher.get_label('com.chameth.proxy').items():
30 31
     networks = fetcher.get_networks(container)
31 32
     certfile = args.cert_path % domains[container][0];
33
+    up = 'lb_' + loadbalance[container] if container in loadbalance else 'ct_' + container
32 34
     if os.path.isfile(certfile):
33
-      services.append({
34
-        'protocol': protocols[container] if container in protocols else 'http',
35
-        'vhosts': domains[container],
35
+      if not up in services:
36
+        services[up] = {
37
+          'protocol': protocols[container] if container in protocols else 'http',
38
+          'vhosts': domains[container],
39
+          'hosts': [],
40
+          'certificate': args.cert_path % domains[container][0],
41
+          'trusted_certificate': args.trusted_cert_path % domains[container][0],
42
+          'certificate_key': args.cert_key_path % domains[container][0],
43
+          'default': container in defaults,
44
+        }
45
+
46
+      services[up]['hosts'].append({
36 47
         'host': next(iter(networks.values())), # TODO: Pick a bridge sensibly?
37 48
         'port': values,
38
-        'certificate': args.cert_path % domains[container][0],
39
-        'trusted_certificate': args.trusted_cert_path % domains[container][0],
40
-        'certificate_key': args.cert_key_path % domains[container][0],
41
-        'default': container in defaults,
42 49
       })
43 50
 
44 51
   if wroteConfig or len(services) > 0 or not os.path.isfile('/nginx-config/vhosts.conf'):

+ 8
- 2
nginx.tpl View File

@@ -1,4 +1,10 @@
1
-{% for service in services %}
1
+{% for srvname, service in services.items() %}
2
+upstream {{ service.upstream }} {
3
+{% for upstream in service.hosts %}
4
+        server {{ upstream.host }}:{{ upstream.port }};
5
+{% endfor %}
6
+}
7
+
2 8
 server {
3 9
     server_name {{ ' '.join(service.vhosts) }};
4 10
     listen [::]:443{{ ' default_server' if service.default }} ssl http2;
@@ -11,7 +17,7 @@ server {
11 17
     include /etc/nginx/conf.d/{{ service.vhosts[0] }}/*.conf;
12 18
 
13 19
     location / {
14
-        proxy_pass {{ service.protocol }}://{{ service.host }}:{{ service.port }};
20
+        proxy_pass {{ service.protocol }}://{{ service.upstream }};
15 21
         proxy_set_header Host $host;
16 22
         proxy_set_header X-Forwarded-For $remote_addr;
17 23
     }

Loading…
Cancel
Save