4

Given I have multiple web applications running in docker containers, I want to be able to let the user be redirected from on service to another service in his browser. I wonder how to achieve this - especially if I want my applications to be portable from one docker host to a different host.

Let's say we have a ServiceA which redirects the user to ServiceB. So we have a relationship

ServiceA --> ServiceB

One approach would be to statically assign ports and hostnames and set them as environment vars to my web services - which I would not prefer because I don't want to care about which service runs on which port.

A second approach would be to have a proxy like nginx and link the services and use the proxy host and port. But this would require to change the proxy configuration when moving a service to a different host.

The third approach that comes to mind, is to use etcd and ambassadors to register and resolve services. So ServiceA would use a ServiceB-Ambassador which looks up ServiceB in etcd. This results in many docker containers just to connect between services.

Which way would you prefer? Or are there different approaches?

Edit

The real problem is to inject the uri of ServiceB into ServiceA, so I can launch my ServiceA with an argument like -DserviceB.uri=<serviceUri>, so that serviceA can build the correct redirect header.

Christian Metzler
  • 2,971
  • 5
  • 24
  • 30
  • Christian, when you say "redirected from one service to another service in his browser" - doesn't that imply that second service must be publicly available somehow? Normally a docker container (service) is not public since it is on a private network. – wassgren Jan 09 '15 at 10:09
  • Sure, they are both accessible from the outside via a port mapping. For example docker run -p 8080 images/serviceA – Christian Metzler Jan 09 '15 at 10:22
  • possible duplicate of [How to link Docker services across hosts?](http://stackoverflow.com/questions/21283517/how-to-link-docker-services-across-hosts) – wassgren Jan 09 '15 at 10:30
  • Well it's not only about container linking - if I link to an ambassador within my serviceA container and use the generated environment vars, I cannot use them for redirects, because these hosts and ports refer to the private docker network. – Christian Metzler Jan 09 '15 at 10:39

1 Answers1

1

I use a setup with consul to connect tomcat containers to an apache http server (using mod_jk ). Consul is similar to etcd, i.e. it allows to register and discover services. This might be applicable to your question, but you are not restricted to consul.

Every time a new tomcat container is started, I assign a distinct public port to that container, register the tomcat container in consul with information about its IP and Ports and fire an event (the script is run on the docker host, and is reduced for readability)

#!/bin/bash
INTERNAL_PORT=8009
source ~/ports.properties
TOMCAT_PORT=$(( TOMCAT_PORT + 1))
echo "TOMCAT_PORT=$TOMCAT_PORT" > ~/ports.properties

CONTAINER_ID=$(docker run -d -p $TOMCAT_PORT:8009 -v `pwd`$WAR_DIR:/webapps rossbachp/tomcat8)
echo "Container started, CONTAINER_ID:  $CONTAINER_ID"

IP_ADDRESS=$(docker inspect -f '{{.NetworkSettings.IPAddress}}' $CONTAINER_ID )
echo "Container IP_ADDRESS:               $IP_ADDRESS "

echo "Register Container in Consul"
curl -X PUT -d '{"ID": "'$CONTAINER_ID'","Name":"'$CLUSTER_NAME'", "Tags": [ "IP_'$IP_ADDRESS'", "PORT_'$INTERNAL_PORT'"],"Port":'$TOMCAT_PORT'}' localhost:8500/v1/agent/service/register 

echo "Fire Event"
consul event -name "TomcatServiceUp"

In consul (on the docker host) I have defined a watch for the event "TomcatServiceUp" in File /etc/consul.d/bootstrap/watchTomcatServiceUp.json that executes a script

{
"watches":[    {
"type":"event",
"name":"TomcatServiceUp",
"handler": "/home/dude/docker/docker-http-withmodjk/callbackTomcatServiceUpEvent.sh"
   }  ]
}

and the script callbackTomcatServiceUpEvent.sh queries the services (mainly IPAddress and Port), creates a new workers.properties file, copies this file to the http docker instance (to its volume) and gracefully restarts the http server (in the docker container).

#!/bin/bash
SERVICE=$(curl localhost:8500/v1/agent/services)
java -jar /home/dude/docker/JSonParser.jar "$SERVICE" >> /tmp/workers.properties
cp workers.properties /home/dude/docker/docker-http-withmodjk/mod_jk_conf
# http graceful restart

Could you use an approach where your services register themselves in consul (or etcd) and discover each other via events and service lookup. Or use nginx to handle the events and do the service lookup?

christian
  • 9,412
  • 10
  • 41
  • 51