A more concrete example of a complete web application with CherryPy, PostgreSQL and haproxy

In the previous post, I described how to setup a docker image to host your CherryPy application. In this installment, I will present a complete – although simple – web application made of a database, two web application servers and a load-balancer.

Setup a database service

We are going to create a docker image to host our database instance, but because we are lazy and because it has been done already, we will be using an official image of PostgreSQL.

As you can see, we run the official, latest, PostgreSQL image. By setting the POSTGRES_USER and POSTGRES_PASSWORD, we make sure the container creates the according account for us. We also set a name for this container, this will be useful when we link to it from another container as we will see later on.

A word of warning, this image is not necessarily secure. I would advise you to consider this question prior to using it in production.

Now that the server is running, let’s create a database for our application. Run a new container which will execute the psql shell:

We have connected to the server, we then create the “notes” database and connect to it.

How did this work? Well, the magic happens through the –link wedb:postgres we provided to the run command. This tells the new container we are linking to a container named webdb and that we create an alias for it inside that new container. That alias is used by docker to initialize a few environment variables such as:

Notice the POSTGRES_ prefix? This is exactly the alias we gave in the command’s argument. This is the mechanism by which you will link your containers so that they can talk to each other.

Note that there are alternatives, such as weave, that may be a little more complex but probably more powerful. Make sure to check them out at some point.

Setup our web application service

We are going to run a very basic web application. It will be a form to take notes. The application will display them and you will be able to delete each note. The notes are posted via javascript through a simple REST API. Nothing fancy. Here is a screenshot for you:

notes_screen

By the way, the application uses Yahoo’s Pure.css framework to change from bootstrap.

Simply clone the mercurial repository to fetch the code.

This will download the whole repository but fear not, it’s rather lightweight. You can review the Dockerfile which is rather similar to what was described in my previous post. Notice how we copy the webapp subdirectory onto the image.

We can now create our image from that directory:

As usual, change the tag to whatever suits you.

Let’s now run two containers from that image:

We link those two containers with the container running our database. We can therefore use that knowledge to connect to the database via SQLAlchemy. We also publish the application’s port to two distinct ports on the host. Finally, we name our containers so that can we reference them in the next container we will be creating.

At this stage, you ought to see that your application is running by going either to http://localhost:8080/ or http://localhost:8081/.

Setup a load balancer service

Our last service – microservice should I say – is a simple load-balancer between our two web applications. To support this feature, we will be using haproxy. Well-known, reliable and lean component for such a task.

Tak some time to review the Dockerfile. Notice how we copy the local haproxy.cfg file as the configuration for our load-balancer. Build your image like this:

And now run it to start load balancing between your two web application containers:

In this case, we will be executing the container in the background because we are blocking on haproxy and it won’t lok to the console anyway.

Notice how we link to both web application containers. We set short alias just by pure lazyness. We publish two ports to the host. The 8090 port will be necessary to access the stats page of the haproxy server itself. The 8091 port will be used to access our application.

To understand how we reuse the the aliases, please refer to the the haproxy.cfg configuration. More precisely to those two lines:

We load-balance between our two backend servers and we do not have to know their address at the time when we build the image, but only when the container is started.

That’s about it really. At this stage, you ought to connect to http://localhost:8091/ to see use your application. Each request will be sent to each web application’s instances in turn. You may check the status of your load-balancing by connecting to http://localhost:8090/.

Obviously, this just a basic example. For instance, you could extend it by setting another service to manage your syslog and configure haproxy to send its log to it.

Next time, we will be exploring the world of CoreOS and clustering before moving on to service and resource management via Kubernetes and MesOS.

One thought on “A more concrete example of a complete web application with CherryPy, PostgreSQL and haproxy”

  1. Hello , I am relatively new to cherrypy. Found this article very interesting in understanding the usage of cherrypy and load balancing! thanks for posting the article.

    I tried to build the docker image with this command “docker build -t lawouach/haproxy:latest .” but ran into errors :

    rr http://archive.ubuntu.com utopic/main Sources
    404 Not Found [IP: 91.189.88.149 80]
    Err http://archive.ubuntu.com utopic/restricted Sources
    404 Not Found [IP: 91.189.88.149 80]
    Err http://archive.ubuntu.com utopic/universe Sources
    404 Not Found [IP: 91.189.88.149 80]
    Err http://archive.ubuntu.com utopic/universe amd64 Packages
    404 Not Found [IP: 91.189.88.149 80]
    Err http://archive.ubuntu.com utopic-updates/main Sources
    404 Not Found [IP: 91.189.88.149 80]
    Err http://archive.ubuntu.com utopic-updates/restricted Sources
    404 Not Found [IP: 91.189.88.149 80]

    Any ideas what might be going on here? Will be great if you could please share any suggestions on fixing this.

    Thanks!
    Mark

Leave a Reply

Your email address will not be published. Required fields are marked *