A Simple Java EE Docker Example

read the asciidoc based version of this post here.

 

In this post we will play a bit with docker in the context of Java EE. Here is what we will do:

  • Create, build and run a docker image;
  • the image will start a wildfly server within a JavaEE sample application deployed;
  • show some docker commands;
  • start multiple containers to see the same app running on different ports.

Introduction

I will not introduce docker as there are already many good references on the subject. To create this post i’ve read the following tutorials:

  1.  Docker userguide;
  2. Working with docker images;
  3.  this great post: Docker begginers tutorial;
  4. Arun Gupta’s tech tips: #39, #57#61 and #65.

Pre requisites

To run this tutorial you will need:

  • A docker daemon running on your host machine
    •  after installing docker add this lines in ‘etc\default\docker‘ file: DOCKER_OPTS=”-H tcp://127.0.0.1:2375 -H unix:///var/run/docker.sock”
    •  after that, restart your machine and try to run the command:  docker -H tcp://127.0.0.1:2375 –version
      the output must be something like: Docker version 1.4.1, build 5bc2ff8
  • A wildfly 8.2.0 installation(unziped);
  • jdk-8u25-linux-x64.tar.gz file;
  • car-service.war available here;
  • Dockerfile available here.

Creating the Docker image

Docker images represent/describe the container itself. As i got limited internet access(3g from my cellphone) i have created an image using resources from my local machine. So the image will only work if it is build in a directory containing the following files:

  • wildfly-8.2.0.Final: the application server
  • car-service.war: the app we will deploy
  • Dockerfile: the file describing this container
  • jdk-8u25-linux-x64.tar.gz: the java version we will install in the container

NOTE: It is not good practice to use fixed resources in a docker container as it will only work if the files are present during the image build. The best approach is to install everything from scratch and download necessary files. Here is an example of docker file that download/install/deploy an app into wildfly 10 without using local files.

Here is the Dockerfile content:

FROM ubuntu
MAINTAINER Rafael Pestano <rmpestano@gmail.com>

# setup WildFly
COPY wildfly-8.2.0.Final /opt/wildfly

# install example app on wildfy
COPY car-service.war /opt/wildfly/standalone/deployments/

# setup Java

RUN mkdir /opt/java

COPY jdk-8u25-linux-x64.tar.gz /opt/java/

# change dir to Java installation dir

WORKDIR /opt/java/

RUN tar -zxf jdk-8u25-linux-x64.tar.gz

# setup environment variables

RUN update-alternatives --install /usr/bin/javac javac /opt/java/jdk1.8.0_25/bin/javac 100

RUN update-alternatives --install /usr/bin/java java /opt/java/jdk1.8.0_25/bin/java 100

RUN update-alternatives --display java

RUN java -version

# Expose the ports we're interested in
EXPOSE 8080 9990

# Set the default command to run on boot
# This will boot WildFly in the standalone mode and bind to all interface
CMD ["/opt/wildfly/bin/standalone.sh", "-c", "standalone-full.xml", "-b", "0.0.0.0"]

The image inherits from ubuntu, an image which installs Ubuntu OS. Ubuntu image is installed when you follow the docker instalation tutorial.

Next we copy the server to the folder /opt/wildfly inside the container we are creating. COPY is a command available in Dockerfile DSL. All commands can be found here.

Next we copy our app war inside the server with: COPY car-service.war /opt/wildfly/standalone/deployments/.

After, we setup Java by unziping it to /opt/java inside the container and setting up environment variables. A best approach would be apt-get but it requires (good)internet access which i didn’t had at the time of the writing. I used RUN command to execute java -version which will print the version during the image build (if java is correctly installed).

Later I use EXPOSE 8080 9990 to tell docker the ports that can be exposed by the container. A container is the instantiation of a Docker image. When we run an image (docker run) we can specify which ports are accessible to the host machine.

Finally we specify the default command using CMD [“/opt/wildfly/bin/standalone.sh”, “-c”, “standalone-full.xml”, “-b”, “0.0.0.0”]. This command will be fired everytime our container is stated.

Building the image

After describing our image we have to build it. Run the following command from the parent folder containing the Dockerfile:

docker -H tcp://127.0.0.1:2375 build -t javaee_sample java_ee/

  • -H flag specify docker daemon address(we are using tcp to communicate with daemon);
  • build is the command itself;
  • -t specify the name of the tag to identify the image (javaee_sample in this case);
  • java_ee/ is the folder containing the Dockerfile describing our image.

More docker commands can be found here. Here is the output of the command:

After that we can see the created image by listing images installed: docker -H tcp://127.0.0.1:2375 images :

 

Starting the container

The container can be started with the command: docker -H tcp://127.0.0.1:2375 run -p 8180:8080 javaee_sample

  • -p specifies the container port(8080) to be exposed on the host machine. Port 8180 in this case (EXPOSE Dockerfile command);
  • run is the command itself;
  • javaee_sample is the name of the image.

The output of command is wildfly starting because we set it as initial command (CMD Dockerfile command):

img4

Running multiple containers

We can instantiate many container as we want since their ports don’t conflict in the host machine. I will start two more containers exposing port 8080 to 8280 and 8380 respectively:

docker -H tcp://127.0.0.1:2375 run -p 8280:8080 javaee_sample
docker -H tcp://127.0.0.1:2375 run -p 8380:8080 javaee_sample

To list started containers we can use the command docker -H tcp://127.0.0.1:2375 ps, here is the output:

rmpestano@rmpestano-ubuntu:~/docker /images$ docker -H tcp://127.0.0.1:2375 ps
CONTAINER ID        IMAGE                  COMMAND                CREATED             STATUS              PORTS                              NAMES
7b9079806e69        javaee_sample:latest   "/opt/wildfly/bin/st   27 seconds ago      Up 27 seconds       9990/tcp, 0.0.0.0:8280->8080/tcp   suspicious_lovelace
d4975e825751        javaee_sample:latest   "/opt/wildfly/bin/st   28 seconds ago      Up 28 seconds       9990/tcp, 0.0.0.0:8380->8080/tcp   loving_hopper
96e58eb65126        javaee_sample:latest   "/opt/wildfly/bin/st   42 seconds ago      Up 42 seconds       9990/tcp, 0.0.0.0:8180->8080/tcp   clever_cori

And now we can access the three apps in the browser at the same time:

img5

You can stop the container by its ID or by name with docker -H tcp://127.0.0.1:2375 stop suspicious_lovelace

Remember that all data will be lost when the container is stopped. Use Docker volumes for persistent data.

Advertisements

4 thoughts on “A Simple Java EE Docker Example

  1. Pingback: 一个简单的Java EE&Docker示例 - Java吧
  2. Hey can you show your memory, CPU, and other related metrics when runnning these 3 containers. How big of a memory footprint are we talking about when using three JDK + wildflies for the host machine?

    Like

    • Hi Jose,the resources it consumes depends on the jvm params (xmx, xms) used to start the server. As i’m using the default settings you can start a Wildfly on your machine to have an idea of resource consumption. The only difference here is that the processes are isolated in docker containers. Don’t know if i’ve answered your question, fell free to detail it.

      Like

  3. Hi,

    I am getting error “FATA[0000] Error response from daemon: Cannot start container c33c6d5c04b37c5592e3c7659f4b1d31f6346742353d03f30f104bdf3827caa3: exec: “/opt/wildfly/bin/standalone.sh”: permission denied” after running docker -H tcp://127.0.0.1:2375 run -p 8180:8080 javaee_sample. Can you please help?

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s