Fix discovery when some containers have no forwarded ports

In the new API, docker can return nil in the JSON to indicate a container
has no ports forwarded. This notably happens when you're using the 'docker build'
command, and breaks synapse's discovery for the duration.

If you have a long running container with no ports forwarded, then
it's just always broken.

This fixes that bug and breaks out rewrite_container_ports into it's own
method as it's complex enough to justify it. Tests are added for the
3 (old/new/nil) cases that this method deals with
Merge pull request #45 from bobtfish/fix_docker_discovery_nill_ports

Fix discovery when some containers have no forwarded ports
shared frontend stanzas in haproxy sections

For HTTP-only services, there is no need to dedicate a port to each service:
services which need to be co-located on a single IP address can, for instance,
share some sort of app container and route based on host or path names.

While haproxy can route on host headers, synapse currently assumes a 1:1
frontend:backend ratio.  But what we want here is a single frontend mapping
to multiple backends based on acl rules.  So herein, a simple stab at it:
if there is a "shared_frontend" key in the root haproxy config, we create
a "shared-frontend" frontend, read in any configuration lines, and then as
we iterate over the services, pluck out any shared_frontend lines like so:

  { "haproxy": {
      "shared_frontend": [
        "bind 127.0.0.1:8081"
      ],
      "global": [
        "daemon",
        "stats socket /var/run/haproxy.sock"
      ],
      "defaults": [
        "log      global",
      ],
    },
    "services": {
      "service1": {
        "haproxy": {
          "server_options": "check inter 2s rise 3 fall 2",
          "backend": [
            "mode http"
          ],
          "shared_frontend": [
            "acl is_service1 hdr_dom(host) -i service1.lb",
            "use_backend service1 if is_service1"
          ]
        }
      },
      "service2": {
        "haproxy": {
          "server_options": "check inter 2s rise 3 fall 2",
          "backend": [
            "mode http"
          ],
          "shared_frontend": [
            "acl is_service2 hdr_dom(host) -i service2.lb",
            "use_backend service2 if is_service2"
          ]
        }
      }
    }
  }

...produces a FE/BE config like this:

  frontend service1
        bind localhost:8086
        default_backend service1

  backend service1
        mode http
        server host1_service1:8101_20d8a0f6 10.73.132.39:8101 check inter 2s rise 3 fall 2
        server host1_service1:8101_4f48153f 10.181.203.244:8101 check inter 2s rise 3 fall 2

  backend service2
        mode http
        server host1_service2:8101_6f0a9d02 10.60.12.9:8101 check inter 2s rise 3 fall 2
        server host2_service2:8101_f3518f4f 10.81.23.44:8101 check inter 2s rise 3 fall 2

  frontend shared-frontend
        bind 127.0.0.1:8081
        acl is_service1 hdr_dom(host) -i service1.lb
        use_backend service1 if is_service1
        acl is_service2 hdr_dom(host) -i service2.lb
        use_backend service2 if is_service2
log when haproxy is restarted
Fix typo. Update broken link.
Merge pull request #51 from nanobeep/patch-1

Fix typo. Update broken link.
Merge pull request #30 from memory/shared_frontend

proposal: shared frontend stanzas in haproxy sections
Add docs badge to README
Merge pull request #54 from rrrene/patch-1

Add docs badge to README
Update README.md

Fixed typos
Merge pull request #57 from MikeChristensen/patch-1

Update README.md
synapse etcd service watcher