In Part 1, I showed how to install Docker and generate a basic image and container. In this post, we’ll go ahead and install the database and servers into different containers based on this original image and configure everything.

Add tools to the base system

I personally prefer to use nano over vim, just a preference thing. We should also probably install our VCS tools (mercurial in this case). Mercurial isn’t in the default repo “ubuntu-minimal” repo, so we also have to add the universe repository.

So lets spin up our xenial container and install everything.

chris:~/ docker run --name xenial -it xenial bash
root@940e2696940c:/# echo "deb xenial universe" >> /etc/apt/sources.list
root@940e2696940c:/# apt-get update
root@940e2696940c:/# apt-get install nano mercurial
root@940e2696940c:/# exit
chris:~/ docker commit xenial xenial:latest

The Database

The Acadiana Software Group site uses a postgres backend with at least UUID type support (9.1 or greater preferred). We’ll turn on the updated xenial container with nano and mercurial and install postgresql 9.5. While we’re at it, we’re gonna configure this postgres instance to accept any connections from any host using passwords.

chris:~/ docker run --name augdb -it xenial bash
root@e4d6bc9c723a:/# apt-get install postgresql

In /etc/postgresql/9.5/main/postgresql.conf, change the line

#listen_address = 'localhost'


listen_address = '*'

and in /etc/postgresql/9.5/main/pg_hba.conf, change the line

host   all     all    md5


host   all     all     *               md5

Now we should have a nice wide-open next-to-no-security postgres daemon to play around with. Let’s add a user account and a database:

root@e4d6bc9c723a:/# /etc/init.d/postgresql start
root@e4d6bc9c723a:/# su - postgres
postgres@e4d6bc9c723a:/# createuser augdb -P
postgres@e4d6bc9c723a:/# createdb augdb -O augdb
postgres@e4d6bc9c723a:/# exit
root@e4d6bc9c723a:/# /etc/init.d/postgresql stop
root@e4d6bc9c723a:/# exit

I’m lazy so I set the password (createuser -P) to augdb. This gives us a basic database instance with a jdbc connection string of jdbc:postgresql://augdb:augdb@localhost:5432/augdb if we’re trying to connect from our augdb container.

Now that our database is installed and configured, lets generate a new image.

chris:~/ docker commit augdb augdb

The Servers

ASG’s site uses a micro-service architecture with each major site component broken out into its own server and respective tables. A static Angular SPA sits in a directory and runs a dynamic client-side web application to render everything. I won’t go into the why’s of this system other than “just because”, but there’s lots of configuration involved. There should be more configuration, I just haven’t gotten around to building it in yet.

Step 1

Using the xenial image, install all our dependencies:

chris:~/ docker run --name augserv -it xenial bash
root@617368e4c702:/# apt-get install openjdk-8-jdk tomcat8 tomcat8-admin libpostgresql-jdbc-java maven openssl

Step 2

We’re not particularly worried about account security on this local container, so we’ll just use the root user to do everything from mercurial to deployment. This will also make it a little easier to manage the html stuff for nginx’s www-data account.

We’ll need

  • Maven’s settings.xml
  • Tomcat’s tomcat-users.xml
  • ASG’s plethora of config files

ASG uses the tomcat-maven plugin to deploy individual services. To keep the POM files from becomming server-specific, ASG uses a server identifier that maven retrieves from /root/.m2/settings.xml file:

<?xml version="1.0" encoding="UTF-8"?>

The localhost id is what ASG service POMs look for when deploying. The <username/> and <password/> tags should match a user in /etc/tomcat8/tomcat-users.xml with the manager-script role:

<?xml version='1.0' encoding='utf-8'?>
    <role rolename="manager-script"/>
    <user username="admin-username" password="admin-password" roles="manager-script"/>

Now let’s clone and configure ASG services.

root@617368e4c702:/# mkdir -p ~/asg
root@617368e4c702:/# cd ~/asg
root@617368e4c702:/# hg clone
root@617368e4c702:/# hg clone
root@617368e4c702:/# hg clone
root@617368e4c702:/# hg clone
root@617368e4c702:/# mkdir conf
root@617368e4c702:/# cd conf
root@617368e4c702:/# cp ../aug-auth/src/main/resources/ 
root@617368e4c702:/# cp ../aug-auth/src/main/resources/
root@617368e4c702:/# cp ../aug-auth/src/main/resources/email.html.template email.html
root@617368e4c702:/# cp ../aug-auth/src/main/resources/
root@617368e4c702:/# cp ../aug-bb/src/main/resources/
root@617368e4c702:/# cp ../aug-bb/src/main/resources/
root@617368e4c702:/# cp ../aug-cal/src/main/resources/
root@617368e4c702:/# cp ../aug-cms/src/main/resources/

We also need to generate an RSA keypair that tomcat knows how to read. This keypair is used in the authorization engine of aug-auth.

root@617368e4c702:/# openssl genrsa -out private_key.pem 1024
root@617368e4c702:/# openssl pkcs8 -topk8 -inform PEM -outform DER -in private_key.pem -out private_key.der -nocrypt
root@617368e4c702:/# openssl rsa -in private_key.pem -pubout -outform DER -out public_key.der

Go ahead and configure all the template files you copied, each should be pretty self explanatory. For the postgres connection line, you’ll want to use augdb as the database hostname.

Once we’ve done that, let’s build and deploy one of our services.

root@617368e4c702:/# cd ~/asg/aug-cms
root@617368e4c702:/# mvn clean install tomcat8:deploy

If you kept the default tomcat port, you should now have the Content API sitting at http://localhost:8080/api/cms. Unfortunately, it won’t work since we haven’t set up our database schema or joined our containers together. Go ahead and deploy the rest of the APIs. The Auth API (/api/user) requires a google captcha to be setup in the client and host, so you’ll probably have trouble creating users until the client SPA is setup. I’ll update this post later with a test data creation script to generate users and passwords and other things.

We’ve configured the server and services, let’s commit our new container.

chris:~/ docker commit augserv augserv

In the next part, we’ll setup the SPA and Nginx into a third container and use docker-compose to link all three containers. We’ll also look into offloading the database storage so we can have some persistent data between startups.