Simple client/server architecture with Docker Compose

This post builds on the previous one to create a simple client/server architecture for a web-app developed with Flask, for the back-end, and RequireJS, for the front-end. These two components will be incapsulated with Docker Compose in order to be ready for deployment.


The web-app is composed by a back-end, made of a main Flask REST service and an additional Blueprint, and a front-end module developed with RequireJS. A Docker module will be created for both the client and the server side of the application.

Docker compose 1

The two will be linked together through Docker Compose and the final user experience will be not affected by this setup.

Docker compose 2

Source code

The source code of all the projects used in this tutorial is available on GitHub: feel free to download, fork and/or star it!

Project URL
Simple Flask UI
Simple Flask Docker Composer

RequireJS client

RequireJS is a JavaScript file and module loader that implements the AMD. The simple client module implemented for this example has a main.js file, that defines the required libraries and starts the component, and an application.js script that implements the business logic of the front-end. The filesystem of the project is shown in the following schema:

simple_flask_ui/ ├── css │ ├── bootstrap.min.css │ ├── select2.min.css │ ├── simple-flask-ui.css │ └── sweet-alert.css ├── html │ └── templates.hbs ├── index.html ├── js │ ├── application.js │ ├── main.js │ └── libs │ └── 3rd Party JavaScript Libraries └── nls └── JavaScript files to implement I18N

As specified in the index.html file, the application loads RequireJS and execute the main.js file:

<script data-main="js/main" src="js/libs/require.js"></script>

This script declares the implemented modules (in paths), loads the required libraries (through the baseUrl), specifies their mutual dependencies (in shim) and starts the application.js module:

require.config({ baseUrl: "js/libs", paths: { application: "../../", APPLICATION: "../application", }, shim: { bootstrap: ["jquery"], backbone: { deps: ["jquery", "underscore"], exports: "Backbone", }, highcharts: ["jquery"], underscore: { exports: "_", }, }, }); require(["APPLICATION"], function (APP) { /* Initiate components. */ var app = new APP(); /* Initiate the application. */ app.init(); });

The application.js module loads a Handlebars template containing an input field and two buttons: the first one will invoke the main REST service, while the second is linked to the Blueprint. The base URL for the AJAX calls has been set to http://localhost:5000/, that is the address exposed by Docker for Flask, as seen in the previous post. The business logic of the front-end is very simple and is described in the schema below:

Docker compose 3

Docker Compose

As per the official documentation "Compose is a tool for defining and running multi-container applications with Docker". The Simple Flask Docker Composer project contains two folders, one with the definition of the front-end Docker image, one for the back-end, and a docker-compose.yml file that tells Docker Compose how to handle the two images. The client side image is built starting from Ubuntu, to which Apache and the source code are then added:

# Create a container from Ubuntu. FROM ubuntu:14.04 # Update Ubuntu repositories. RUN apt-get update # Install Apache. RUN apt-get -y install apache2 # Install unzip. RUN apt-get -y install wget RUN apt-get -y install unzip # Get and unzip sources. RUN wget RUN unzip RUN mv simple_flask_ui-master/ /var/www/html/simple_flask_ui

The final step is the definition of the docker-compose.yml file, in which we specify that there are two volumes called client and server. For each module Docker Compose will run the Docker build:

build: ./server


build: ./client

Each volume specifies which are the ports that need to be exposed: 5000 for the server and 9999 for the client. In addition to that for each volume there is a command instruction specified, that will be executed once Docker Compose is up. Finally, the links directive tells Docker Compose to link the server and the client volumes. The complete docker-compose.yml file is shown below:

server: build: ./server ports: - "5000:5000" command: "/deployment/env/bin/python /deployment/" links: - client client: build: ./client ports: - "9999:80" command: "/usr/sbin/apache2ctl -D FOREGROUND"

Time to build the project:

docker-compose build

and finally run it:

docker-compose up

Once the project is up and running it is possible to visit the UI at the following URL: http://localhost:9999/simple_flask_ui.