You are here

Hands-On with NuoDB and Docker

Error message

Note: This blog was published over a year ago. Content may be out of date.

Docker is a perfect fit for demonstrating the strength of our product in a simple and foolproof manner because we can wrap up everything we need in a NuoDB host and recreate it in a 100% repeatable fashion. With the requirement that the customer run Linux and have Docker installed, we could easily set up a tour of NuoDB so that it was a very robust environment.

I had never played with Docker, so this project immediately intrigued me. Furthermore, we realized quickly that having Docker as part of our NuoDB Tour was an advantage because many users, like me, had never worked with it before. This way, they’re able to check out Docker and NuoDB at the same time!

The idea was that we would provide three Docker containers that would serve as virtual NuoDB hosts. Each Docker container would run Ubuntu. On each container we would install NuoDB 2.3.1 and Java JRE 7, create a user named nuodb and start the NuoDB Broker. That’s it. These would be three well defined hosts on which to run NuoDB. Our domain configuration was complete.  We would also ship a couple of the NuoDB tools that could be run on the Docker host (that is, the machine on which you are running your Docker containers) to access our virtual NuoDB hosts. This included nuodbmgr, nuosql, and the NuoDB JDBC driver. Finally we also bundled in some demo SQL scripts and Java clients.

In order to configure the most basic, simplest Docker container you can spin up to run as a NuoDB host, first you have to build the Docker container. This is done with the docker build command and a simple Dockerfile:

# for the purposes of this demo use ubuntu 14.04 & nuodb 2.3.1

FROM ubuntu:14.04

ENV nuodb_pkg nuodb_2.3.1.6_amd64.deb

 

# update the distro and install the JRE and supervisor

RUN /usr/bin/apt-get update && /usr/bin/apt-get -y install \

   default-jre-headless \

   supervisor

 

# add the nuodb package to the image and run the install

ADD http://download.nuohub.org/$nuodb_pkg /tmp/

RUN /usr/bin/dpkg -i /tmp/$nuodb_pkg

 

# copy the supervisor conf file into the image

ADD supervisord.conf /etc/supervisor/conf.d/supervisord.conf

 

# add a wrapper that will stage all properties and use it on entry

ADD run.sh /tmp/

RUN /bin/chmod +x /tmp/run.sh

CMD /tmp/run.sh

 

The Dockerfile says to create a Ubuntu Docker container. It sets the environment variable nuodb_pkg to the NuoDB package we want to install. It uses apt-get to get the Java JRE and the supervisor package. The Java JRE is required to run the NuoDB broker. The supervisor package will be used to manage processes running on the container. Next the Dockerfile specifies to download the NuoDB package and install it using dpkg. Finally, the Dockerfile lists two files to be copied into the Docker container: a file called supervisord.conf to /etc/supervisor/conf.d and a script called run.sh to /tmp and says to execute run.sh.

The superviorsd.conf file looks like this:

[supervisord]

nodaemon=true

 

[program:nuoagent]

user=nuodb

command=/opt/nuodb/etc/nuoagent start

 

This will tell the supervisor daemon on the container to start up the NuoDB broker called nuoagent. The supervisord server is invoked in the run.sh script which looks like this:

#!/bin/sh

# Wrapper script called on entry to the image that updates the agent's

# default.properties file, optionally updates the rest service config,

# and then passes on control to supervisor.

 

# setup the required agent properties

AGENT_PORT=${AGENT_PORT:-48004}

PORT_RANGE=$((AGENT_PORT+1))

AGENT_PEER=${AGENT_PEER:-''}

 

# fill out the the agent properties file

/bin/sed -ie "s/#domainPassword =/domainPassword = $DOMAIN_PASSWORD/" /opt/nuodb/etc/default.properties

/bin/sed -ie "s/#port = 48004/port = $AGENT_PORT/" /opt/nuodb/etc/default.properties

/bin/sed -ie "s/portRange = 48005/portRange = $PORT_RANGE/" /opt/nuodb/etc/default.properties

/bin/sed -ie "s/#peer =/peer = $AGENT_PEER/" /opt/nuodb/etc/default.properties

 

# optionally include the REST service under supervisor control

if [ -n "$START_REST_SVC" ]; then

   CONF_FILE=/etc/supervisor/conf.d/supervisord.conf

   echo "[program:nuorestsvc]"  >> $CONF_FILE

   echo "user=nuodb">> $CONF_FILE

   echo "command=/opt/nuodb/etc/nuorestsvc start">> $CONF_FILE

fi

 

/usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf

 

The run.sh script does all the necessary steps to run the container as a NuoDB host.  It modifies /opt/nuodb/etc/default.properties to set the domainPassword, port, portRange, and peer properties. This script expects some environment variables to be set at runtime. DOMAIN_PASSWORD will be your NuoDB domain password, AGENT_PORT will be the port on which the broker for this host will be listening, PORT_RANGE will be the range of ports available for two NuoDB processes (presumably 1 TE and 1 SM) to use, and AGENT_PEER will be the IP address of the broker to which the broker on this host will peer (for the first host, AGENT_PEER will not be set). START_REST_SVC should be set to true for the first host only; only one host need run the REST service.

To build the container:

$ docker build -t nuodb_eval/server .

 

Then, make sure THP is disabled on your host and then the first Docker container can be started with:

$ docker run --name nuodb1 -h nuodb1 -P  -p 48005:48006 \

   -e DOMAIN_PASSWORD=domain_pwd \

   -e AGENT_PORT=48004 \

   -e START_REST_SVC=true \

   nuodb_eval/server> docker_run.log 2>&1 &

 

The -e parameter is used to set environment variables. Here we set the domain password, the port on which the broker should listen (AGENT_PORT) and we say to start the REST service.

In order to access your NuoDB domain, which now consists of just one host, you will need to know the IP address of the Docker container. To get this, run docker ps -a to get the Docker container ID:

$ docker ps -a

CONTAINER ID        IMAGE...

266c53c10c2c        nuodb_eval/server:latest...

 

And use the container id to get the IP address as follows:

 

$ docker inspect --format '{{ .NetworkSettings.IPAddress}}' 266c53c10c2c

172.17.0.14

 

Now you can connect to your domain using nuodbmgr on the Docker host:

 

$ nuodbmgr --broker 172.17.0.14 --password domain_pwd

NuoDB host version: 2.3.1-6: Professional Edition

nuodb [domain]> show domain summary

 

Hosts:

[broker] * nuodb1/172.17.0.14:48004 (DEFAULT_REGION) CONNECTED

 

Now you have one NuoDB host in your domain which is running in a Docker container.

We can now add two more hosts by tweaking the environment variables we pass into the docker run  command.

$ docker run --name nuodb2 -h nuodb2 --link nuodb1:nuodb1 \

   -P -p 48008:48009  \

   -e DOMAIN_PASSWORD=domain_pwd \

   -e AGENT_PORT=48007 \

   -e AGENT_PEER=nuodb1 \

   nuodb_eval/server> docker_run2.log 2>&1 &

$ docker run --name nuodb3 -h nuodb3 --link nuodb1:nuodb1 \

   -P -p 48011:48012 \

   -e DOMAIN_PASSWORD=domain_pwd \

   -e AGENT_PORT=48010 \

   -e AGENT_PEER=nuodb1 \

   nuodb_eval/server> docker_run3.log 2>&1 &

 

Here we specify the port range as 48008:48009 for the nuodb2 TE and SM and 48011:48012 for nuodb3 TE and SM, the port for the broker to listen on as 48007 for nuodb2 and 48010 for nuodb3 and that both these containers would peer back to the initial nuodb1 container.

 

Now our domain looks like this:

$ nuodbmgr --broker 172.17.0.14 --password domain_pwd

NuoDB host version: 2.3.1-6: Professional Edition

nuodb [domain]> show domain summary

 

Hosts:

[broker] * nuodb1/172.17.0.14:48004 (DEFAULT_REGION) CONNECTED

[broker] nuodb2/172.17.0.15:48007 (DEFAULT_REGION) CONNECTED

[broker] nuodb3/172.17.0.16:48010 (DEFAULT_REGION) CONNECTED

 

Let’s create a database:

nuodb [domain]> create database

Database Name: db1

DBA User: dba

DBA Password: dba

Template Name (Single Host, Minimally Redundant, Multi Host, Geo-distributed): Minimally Redundant

Template Variables (optional):

Database Options (optional):

Timeout (ms/s/m/h/d/w) (optional):

Template Variable REGION (default: DEFAULT_REGION):

Database Options for SMs (optional):

Tag Constraints for SMs (optional):

Database Options for TEs (optional):

Tag Constraints for TEs (optional):

nuodb [domain]> show domain summary

 

Hosts:

[broker] * nuodb1/172.17.0.14:48004 (DEFAULT_REGION) CONNECTED

[broker] nuodb2/172.17.0.15:48007 (DEFAULT_REGION) CONNECTED

[broker] nuodb3/172.17.0.16:48010 (DEFAULT_REGION) CONNECTED

 

Database: db1, template [Minimally Redundant] MET, processes [2 TE, 2 SM], ACTIVE

[SM] nuodb1/172.17.0.14:48007 (DEFAULT_REGION) [ pid = 366 ] [ nodeId = 1 ] RUNNING

[TE] nuodb2/172.17.0.15:48008 (DEFAULT_REGION) [ pid = 127 ] [ nodeId = 2 ] RUNNING

[SM] nuodb3/172.17.0.16:48011 (DEFAULT_REGION) [ pid = 126 ] [ nodeId = 3 ] RUNNING

[TE] nuodb3/172.17.0.16:48012 (DEFAULT_REGION) [ pid = 154 ] [ nodeId = 4 ] RUNNING

 

We now have a NuoDB database called db1 that is running on all three of our NuoDB hosts, that is, on all three of our Docker containers. It is running one Storage Manager (SM) on nuodb1, one Transaction Engine (TE) on nuodb2, and a TE/SM pair on nuodb3.

Of course, using Docker containers like this on a single laptop won't allow you to see how NuoDB truly scales on a multi-host environment, but you'll quickly see the potential. But you will get to see redundancy and when one TE becomes unavailable, another TE will automatically start up so there is no interruption of service for your database.

This experiment shows that Docker is a great way to simplify testing and generate repeatable build environments.

To learn more about NuoDB and Docker, check out our the post written by our CTO Seth Proctor on the subject!

Add new comment