docker-flow-proxy

command module
v0.0.0-...-840e791 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 8, 2016 License: MIT Imports: 9 Imported by: 0

README

Docker Flow: Proxy

The goal of the Docker Flow: Proxy project is to provide an easy way to reconfigure proxy every time a new service is deployed, or when a service is scaled. It does not try to "reinvent the wheel", but to leverage the existing leaders and combine them through an easy to use integration. It uses HAProxy as a proxy and Consul as service registry. On top of those two, it adds custom logic that allows on-demand reconfiguration of the proxy.

Prerequisite for the Docker Flow: Proxy container is, at least, one Consul instance and the ability to put services information. The easiest way to store services data in Consul is through Registrator. That does not mean that Registrator is the requirement. Any other method that will put the information into Consul will do.

Examples

For a more detailed example, please read the Docker Flow: Proxy – On-Demand HAProxy Service Discovery and Reconfiguration article. Besides providing more information, the article has a benefit or being OS agnostic. It will work on Linux, OS X, and Windows and do not have any requirement besides Vagrant.

The examples that follow assume that you have Docker Machine and Docker Compose installed. The easiest way to get them is through Docker Toolbox. The examples will not run on Windows. Please see the Docker Flow: Proxy – On-Demand HAProxy Service Discovery and Reconfiguration article for an OS agnostic walkthrough.

To setup an example environment using Docker Machine, please run the commands that follow.

git clone https://github.com/vfarcic/docker-flow-proxy.git

cd docker-flow-proxy

chmod +x docker-flow-proxy-demo-environments.sh

./docker-flow-proxy-demo-environments.sh

Right now we have four machines running. The first one is called proxy and runs the containers Consul and Docker Flow: Proxy. The other three machines constitute the Docker Swarm cluster. Each of the machines in the cluster runs Registrator that monitors Docker events and puts data to Consul whenever a new container is run. It works the other way as well. If a container is stopped or removed, Registrator will eliminate its data from Consul. In other words, thanks to Registrator, Consul will always have up-to-date information regarding all containers running on the cluster.

Now we're ready to deploy a service.

eval "$(docker-machine env --swarm swarm-master)"

docker-compose \
    -p books-ms \
    -f docker-compose-demo.yml \
    up -d

The details of the service we deployed are irrelevant for this exercise. What matters is that it was deployed somewhere inside the cluster and is running on a random port.

The only thing missing now is to reconfigure the proxy so that our newly deployed service is accessible on a standard HTTP port 80. That is the problem Docker Flow: Proxy is solving.

eval "$(docker-machine env proxy)"

export PROXY_IP=$(docker-machine ip proxy)

curl "$PROXY_IP:8080/v1/docker-flow-proxy/reconfigure?serviceName=books-ms&servicePath=/api/v1/books"

That's it. All we had to do is send an HTTP request to reconfigure the proxy. The serviceName query contains the name of the service we want to integrate with the proxy. The servicePath is the unique URL that identifies the service.

The output of the curl command is as follows (formatted for better readability).

{
  "Status": "OK",
  "Message": "",
  "ServiceName": "books-ms",
  "ServicePath": "/api/v1/books"
}

Docker Flow: Proxy responded saying that reconfiguration of the service books-ms running on the path /api/v1/books was performed successfully.

Let's see whether the service is indeed accessible through the proxy.

curl -I $PROXY_IP/api/v1/books

The output of the curl command is as follows.

HTTP/1.1 200 OK
Server: spray-can/1.3.1
Date: Mon, 14 Mar 2016 22:08:11 GMT
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=UTF-8
Content-Length: 2

The response is 200 OK, meaning that our service is indeed accessible through the proxy. All we had to do is tell docker-flow-proxy the name of the service.

Docker Flow: Proxy is not limited to a single instance. It will reconfigure proxy to perform load balancing among all currently deployed instances.

eval "$(docker-machine env --swarm swarm-master)"

docker-compose \
    -f docker-compose-demo.yml \
    -p books-ms \
    scale app=3

curl "$PROXY_IP:8080/v1/docker-flow-proxy/reconfigure?serviceName=books-ms&servicePath=/api/v1/books"

curl -I $PROXY_IP/api/v1/books

Docker Flow: Proxy reconfiguration is not limited to a single service path. Multiple values can be divided by comma (,). For example, our service might expose multiple versions of the API. In such a case, an example reconfiguration request could look as follows.

curl "$PROXY_IP:8080/v1/docker-flow-proxy/reconfigure?serviceName=books-ms&servicePath=/api/v1/books,/api/v2/books" \
     | jq '.'

The result from the curl request is the reconfiguration of the HAProxy so that the books-ms service can be accessed through both the /api/v1/books and the /api/v2/books paths.

Optionally, serviceDomain can be used as well. If specified, the proxy will allow access only to requests coming from that domain. The example that follows sets serviceDomain to my-domain-com. After the proxy is reconfigured, only requests for that domain will be redirected to the destination service.

curl "$PROXY_IP:8080/v1/docker-flow-proxy/reconfigure?serviceName=books-ms&servicePath=/&serviceDomain=my-domain.com" \
     | jq '.'

For a more detailed example, please read the Docker Flow: Proxy – On-Demand HAProxy Service Discovery and Reconfiguration article.

Containers Definition

The complete definition of the containers we run can be found in the docker-compose.yml file. The content is as follows.

version: '2'

services:
  consul:
    container_name: consul
    image: progrium/consul
    ports:
      - 8500:8500
      - 8301:8301
      - 8300:8300
    command: -server -bootstrap

  registrator:
    container_name: registrator
    image: gliderlabs/registrator
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock
    command: -ip $DOCKER_IP consul://$CONSUL_IP:8500

  proxy:
    container_name: docker-flow-proxy
    image: vfarcic/docker-flow-proxy
    environment:
      CONSUL_ADDRESS: $CONSUL_IP:8500
    ports:
      - 80:80
      - 443:443
      - 8080:8080

Please note that this definition is compatible only with Docker Compose version 1.6+.

As you can see, all three targets are pretty simple and straightforward. In the examples, Consul was run on the proxy node. However, in production, you should probably run it on all servers in the cluster. Registrator was deployed to all Swarm nodes. Its command points to the Consul instance. Please note that consul and registrator targets are for demonstration purposes only. The only important requirement for the proxy target is the CONSUL_ADDRESS variable.

Finally, proxy target was also deployed to the proxy node. In production, you might want to run two instances of the docker-flow-proxy container and make sure that your DNS registries point to both of them. That way your traffic will not get affected in case one of those two nodes fail. The CONSUL_ADDRESS environment variable is mandatory and should contain the address of the Consul instance. Internal ports 80, 443, and 8080 can be exposed to any other port you prefer. HAProxy (inside the docker-flow-proxy container) is listening Ports 80 (HTTP) and 443 (HTTPS). The port 8080 is used to send reconfigure requests.

Feedback and Contributions

I'd appreciate any feedback you might give (both positive and negative). Feel fee to create a new issue, send a pull request, or tell me about any feature you might be missing. You can find my contact information in the About section of my blog.

Documentation

The Go Gopher

There is no documentation for this package.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL