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.
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:
- Docker userguide;
- Working with docker images;
- this great post: Docker begginers tutorial;
- Arun Gupta’s tech tips: #39, #57, #61 and #65.
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 &lt;email@example.com&gt; # 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 [&quot;/opt/wildfly/bin/standalone.sh&quot;, &quot;-c&quot;, &quot;standalone-full.xml&quot;, &quot;-b&quot;, &quot;0.0.0.0&quot;]
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):
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 &quot;/opt/wildfly/bin/st 27 seconds ago Up 27 seconds 9990/tcp, 0.0.0.0:8280-&gt;8080/tcp suspicious_lovelace d4975e825751 javaee_sample:latest &quot;/opt/wildfly/bin/st 28 seconds ago Up 28 seconds 9990/tcp, 0.0.0.0:8380-&gt;8080/tcp loving_hopper 96e58eb65126 javaee_sample:latest &quot;/opt/wildfly/bin/st 42 seconds ago Up 42 seconds 9990/tcp, 0.0.0.0:8180-&gt;8080/tcp clever_cori
And now we can access the three apps in the browser at the same time:
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.