A few words about Docker

Perform repetitive tasks, are the way to succeed or hit boredom. For example, practice guitar everyday can make you better, don’t learn anything new, boring.

On AeroGear, contributions come from different platforms: Android, iOS, JavaScript, Windows Mobile and hybrid like Apache Cordova. Specialists or not, everyone should be able to run each other’s project.

Most of these projects send HTTP requests to the application server for sending push messages. The minimum set up below is required for testing:

  • JDK 1.7
  • Maven 3.1.1 or superior
  • JBoss AS 7 or Wildfly 8.1 Final
  • Node.js, npm and bower
  • Git
  • Set the environment variables properly
  • Configure SSL certificates

It’s near to impossible to configure everything in less than an hour — Java is tricky sometimes. Minutes later, it starts to get boring. Automation scripts can be helpful, but does not guarantee any portability. This is where Docker comes into play.

The Moby Dock

Docker provides an uniform environment through lightweight containers. The website have very simple installation instructions and also a 10-minute tutorial with the basics, to see how it works.


On OSx, additional steps are required, because Docker engine have specific features tied to the Linux kernel. For this reason, VirtualBox and boot2docker are required. There are two alternatives to install: download from GitHub, which already contains the whole environment required or make use of Homebrew.

On Homebrew, ensure that everything is up to date and the system is ready to brew before getting started:

$ brew update && brew doctor

Next, install boot2docker:

$ brew install boot2docker -y

Assuming the installation went well, docker and boot2docker should be available through command line. Now, let’s create a new VM:

$ boot2docker init
Downloading boot2docker ISO image...
Latest release is v1.2.0
Success: downloaded https://github.com/boot2docker/boot2docker/releases/download/v1.2.0/boot2docker.iso

The ISO image can be found at $HOME/.boot2docker folder and visualized on VirtualBox

We are all set to start with Docker. As time goes by, the following commands will start become part of routine:

$ boot2docker up

Waiting for VM and Docker daemon to start...

To connect the Docker client to the Docker daemon, please set:
    export DOCKER_HOST=tcp://

$ $(boot2docker shellinit)

Eventually your VM may run into issues like successively timeouts or aborting, that’s the reason why shellinit so important. It’s responsible for configure DOCKER_HOST and TLS variable (if configured).

For shutting down the image:

$ boot2docker down

To save time, create the following aliases with the basic commands like this:

$ alias -g b2d-up='boot2docker up && $(boot2docker shellinit)'
$ alias -g b2d-down='boot2docker down'

Eventually upgrade the ISO image is needed for improvements:

$ boot2docker upgrade

Docker Hub and the basics

Most of the official repositories contain images like: Ubuntu, Fedora, Debian and popular application servers easily found at Docker Hub.

Before start, sign up with the GitHub account on Docker Hub. Then attempt to login:

$ docker login

After being prompted for your credentials, you will be able to search for images:

$ docker search fedora
NAME      DESCRIPTION                             STARS   OFFICIAL   AUTOMATED
fedora    (Semi) Official Fedora base image.      73      [OK]

Let’s suppose that something must be tested on Fedora:

//Run interactively
$ docker run -it fedora bash
Unable to find image 'fedora' locally
Pulling repository fedora
88b42ffd1f7c: Download complete
//You are now able to try Fedora

Visualize the downloaded images:

$ docker images
fedora        latest      88b42ffd1f7c        8 weeks ago      373.7 MB
Keep in mind is that Docker won't save the state of your containers. Until you *commit* the changes, nothing will be persisted to the local container. In other words, if you exit from console, everything will be lost.

Erratum: Is possible to retrive the state of your container, using the ID. Thanks Marc for correcting me. Use commit to save, update and manage the changes into the Docker image.

For testing, run and install some dependencies like Git:

$ docker run -it fedora bash
bash-4.2# yum update && yum install git

Open a new console to visualize the running containers:

$ docker ps
7ebd5f9abfa1    fedora:latest    "bash"      13 minutes ago     Up 13 minutes

To guarantee that nothing will be lost, persist latest changes:

$ docker commit docker commit 7ebd5f9abfa1 golum
$ docker images
REPOSITORY     TAG          IMAGE ID            CREATED             VIRTUAL SIZE
golum          latest       ac16c9177afa        2 minutes ago       373.7 MB
fedora         latest       88b42ffd1f7c        8 weeks ago         373.7 MB
$ docker run -it golum bash

Build your own image

After play with Docker, is not that hard to realize that’s nearly impossible to memorize all the steps and configuration required to create a custom image. It is recommended to include the instructions in a Dockerfile — the descriptor for building images.

Back to Java, we wanted UPS up and running on Fedora with WildFly. Before create everything from scratch, let’s see if an image already exists:

$ docker search wildfly
NAME               DESCRIPTION                          STARS   OFFICIAL   AUTOMATED
jboss/wildfly      WildFly application server image     27                 [OK]

With the base image already there, is possible to extend it on Dockerfile, just providing parameters to FROM:

FROM jboss/wildfly

Our image will have to deal with multiple environment variables to run Java and Node.js, ENV can make it easy. Also, it can also be used on Dockerfile to specify repository names and software versions. Here’s an example:

ENV REPO_NAME aerogear-unifiedpush-server
ENV JAVA_HOME /usr/lib/jvm/java-1.7.0-openjdk

For command line instructions like yum install, execution of shell scripts or downloading files RUN is widely used:

RUN sudo yum -q -y install java-1.7.0-openjdk-devel nodejs npm gcc make libpng libpng-devel git && yum -q clean all

By default everything on Dockerfile is executed as root, is strongly encouraged to use non-root credentials instead. Modify the current user quite simple:

RUN useradd -m aerogear -d /opt/aerogear -s /sbin/nologin
USER aerogear
//Execute all the commands below as aerogear
RUN sudo yum install -q -y nodejs npm gcc make libpng libpng-devel git && yum -q clean all

Other commands like WORKDIR, EXPOSE and ENTRYPOINT are particularly handy for the boot time definition. For example, copy the project to /opt/aerogear, expose SSL ports and start WildFly:

For example:

# Switch to the working dir /opt/aerogear
WORKDIR /opt/aerogear
# Clone the official repository
RUN git clone https://github.com/aerogear/$REPO_NAME.git
# Expose SSL default port
# Set the default command to run on boot
ENTRYPOINT ["/opt/aerogear/server/bin/standalone.sh", "-b", "", "-bmanagement", ""]

Sharing is caring

There are many ways to distribute Docker images: GitHub, Amazon S3, e-mail, FTP, carrier pigeon or Docker Hub. In most cases, a combination of GitHub with Docker Hub is enough.

For automated builds, the documentation has a detailed explanation about it. If you prefer to build the image by yourself, from the directory where Dockerfile is located run:

$ docker build -t abstractj/wildfly .
Sending build context to Docker daemon 53.25 kB
Sending build context to Docker daemon
Step 0 : FROM jboss/wildfly
Pulling repository jboss/wildfly

Check if the image is there:

$ docker images
REPOSITORY          TAG         IMAGE ID        CREATED             VIRTUAL SIZE
abstractj/wildfly   latest      d775c6675b27    3 minutes ago       1.192 GB

The interaction with Docker Hub through command line interface is pretty much close to Git. If you are already familiar with it:

$ docker push abstractj/wildfly

The default tag is always latest, depending on how many changes are done into your image, might be interesting to tag it:

$ docker tag abstractj/wildfly abstractj/wildfly:0.0.1

Now with the image available for download everyone can take advantage of it, no matter the experience level with Java. But how to test?

Downloading and exposing the SSL port 8443:

$ docker run -it -p 8443:8443 abstractj/unifiedpush-wildfly

Exposing to the private network

For accessing the image, is necessary to discover its IP address:

$ boot2docker ip
The VM's Host only interface IP address is:

Opening the following URL in the browser UPS page should be displayed.

The host machine (computer with running image) will always have access to Docker containers. But what about other devices?

Consider the following scenario:

  • computer, mobile devices:
  • VirtualBox:

It can be accessible via internal network IP address, if we properly configure the port forwarding:

$ boot2docker stop
$ VBoxManage modifyvm "boot2docker-vm" --natpf1 "tcp-port8443,tcp,,8443,,8443"
$ boot2docker up && $(boot2docker shellinit)

Now the application server will be accessible to the network.

What else?

Docker provides a lot of features for people easily get started with application servers and Linux distros. On AeroGear it helped a lot to put client and server side developers on the same page.

Most of the snippets discussed here are available into this repository. Also, the JBoss images are available here.

If you’re looking for more information, please subscribe to the weekly newsletter and therefore read Marek Goldmann’s blog.

For questions, feel free to contact me. I hope I didn’t bore you too much.