Running Websphere Liberty Profile in a Docker Container

Share this post:

I will be demonstrating how to set up a Websphere Liberty Profile (WLP) application server inside of a Docker container. The end result will be one command that runs a custom Docker image with WLP installed and a sample application deployed on it.

Things required for this demonstration:

Now that we have collected all of our resources, we can begin to build our custom Docker image, using a Dockerfile.

The Dockerfile

First, we will select an existing Docker image to use as a starting place. A simple one is Ubuntu 12.04, so the first line of our Dockerfile will read:

FROM ubuntu:12.04

The next step will be to add the required files for this Docker image. This will be the WLP .jar files, the JAXWSEJBSample.jar file. So your next portion of your Dockerfile will look like this:

 # add the files we require, jar + WLP files
ADD wlp-developers-extended- /root/
ADD wlp-developers-runtime- /root/
ADD JAXWSEJBSample.jar /root/

Now we can include the steps for installing the WLP .jar files and priming our Docker image for running. This will simply be the commands you would run in Linux to install WLP, per the documentation. So the next chunk of your Dockerfile should look like this:

 # install the WLP
RUN apt-get update
RUN apt-get install -y default-jre
RUN java -jar /root/wlp-developers-runtime- --acceptLicense /root/
RUN java -jar /root/wlp-developers-extended- --acceptLicense /root/
RUN cd /root/wlp && java -jar ../JAXWSEJBSample.jar /root/wlp

We first update our packages to ensure that the components we require for the Java Runtime Environment are there. Then we install the default JRE and proceed to run the specified .jar files. The last command is per the documentation on running the jpaSample.jar file.

So, just a few finishing touches to our Dockerfile and then we can move on to the next step:

CMD /root/wlp/bin/server run JAXWSEJBSample

In just two lines, we have a lot going on. The first line exposes the container’s ports. We expose 9080 because that is the port that WLP uses. The second line defines the command that will be run when the Docker image is run in a container. We have placed the command from the documentation on our sample application as the command to run when our container starts.

Putting it all together

Now that we have all our resources in addition to our Dockerfile sitting in our working directory, we can get to actually running some Docker commands. We will start by building the image we just defined with our Dockerfile.

docker build -t name/wlp .

The -t flag allows us to tag our successfully built image with a name. Typically I use the pattern of name/appname. So for instance, alex/wlp. You will see all of the steps defined in our Dockerfile begin to run in the terminal. Once we get the message saying “Successfully built $containerID”. Now we can run our built container using the command docker run. However, we have two choices at this point, which are to explicitly publish our container’s exposed ports to specified ports on the host machine, or to publish all of our exposed ports to ports determined by Docker. I’ll show both, starting with explicitly publishing our container’s exposed ports:

docker run -p 1930:9080 name/wlp

This command uses the -p flag in order to publish our container’s exposed port 9080 to the host machine’s port of 1930. Meaning that when you hit the host machine’s IP address at port 1930, you will actually be hitting port 9080 on our container. The alternative, which publishes all exposed ports, is as follows:

docker run -P name/wlp

In order to find out which exposed ports have been published to which host machine ports, we first retrieve the container ID using the docker ps command, which allows you to see currently running containers. Once we have the container ID, we can run the docker port command in order to find out the mapping. An example usage in this case would be:

root@dockertest:~# docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                     NAMES
3f71b89735ed        alex/wlp:latest     /bin/sh -c '/root/wl   10 minutes ago      Up 10 minutes>9080/tcp   stoic_galileo       
root@dockertest:~# docker port 3f7 9080

Now that we have run our container, we can check if everything is set up correctly. You should see something similar to the following lines printed in your terminal:

docker run -P alex/wlp
Launching JAXWSEJBSample (WebSphere Application Server on OpenJDK 64-Bit Server VM, version 1.6.0_31-b31 (en_US)
[AUDIT   ] CWWKE0001I: The server JAXWSEJBSample has been launched.
[AUDIT   ] CWWKZ0058I: Monitoring dropins for applications. 
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://localhost:9130/AnEJBWebServices/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://localhost:9130/AnEJBWebServicesWithHandler/
[AUDIT   ] CWWKT0016I: Web application available (default_host): http://localhost:9130/JAXWSEJBSample/
[AUDIT   ] CWWKZ0001I: Application JAXWSEJBSample started in 2.207 seconds.
[AUDIT   ] CWWKF0011I: The server JAXWSEJBSample is ready to run a smarter planet.

pushing your Docker image

Once you have built and tagged your image, you may want to have access to it on other machines. You can do this by pushing your image to the Docker repository. To do so, you must register a Docker account, and then tag your image with your_username/image_name. Once you have the image tagged with the same name as the account name you created, you can run the command

docker push your_username/project_name

However, since our Docker container runs proprietary code (WLP), we cannot push it to the public repository. I will show you how to create a private repository that runs on your local machine. Docker has recently made this very simple. In fact, you can run a container that has a docker-registry running in it. Invoke the container with

docker run -p 5000:5000 registry

After Docker pulls the image and runs it in a container, you’ll see gunicorn give you a success message. Now you can push your image to your local repository. First we must tag our image properly, with a tag following the pattern of localhost:5000/project_name. We can achieve that with the following command:

docker tag alex/wlp localhost:5000/wlp

We use localhost:5000 because that is the port we published with the previous run command. If you do not include the port, Docker will treat localhost as a username, such as alex/wlp. Now that the image is properly tagged, we can run

docker push localhost:5000/wlp

and we should see output similar to this:

root@dockertest:~/wlp-docker# docker push localhost:5000/wlp
The push refers to a repository [localhost:5000/wlp] (len: 1)
Sending image list
Pushing repository localhost:5000/wlp (1 tags)
Image 511136ea3c5a already pushed, skipping
Image 86492831f5b9 already pushed, skipping
Pushing tag for rev [86492831f5b9] on {http://localhost:5000/v1/repositories/wlp/tags/latest}

A warning about disk space

Docker currently leaves images and containers (even after you have killed a container) on your hard drive, and over time, these old images and containers will fill up your hard disk. I have found two commands online that clean out the old containers and images; I have put them in the following script that I run when I am done working to clean out my hard drive.

docker rm `docker ps --no-trunc -a -q`
docker images | grep '' | awk '{print $3}' | xargs docker rmi
exit 0

Add Comment

Leave a Reply

Your email address will not be published.Required fields are marked *


Hey Alex!
Thanks for the tutorial, but i’m having some trouble here and i am not sure of what is going on. I would be grateful if you could shed some light 🙂

I have followed your tutorial except for the fact of using ubuntu 14:04 as base image.
I also have a couple more doubts, the exposed port has to be 9080? or should it be 9130? As i was not sure i exposed both of them.

When i try to access the webserver from the outside i can’t. If i curl it with any of the possible combinations (just in case i was doing something wrong with the ports)
curl localhost:49153
curl localhost:49154
curl localhost:49153/JAXWSEJBSample/
curl localhost:49154/JAXWSEJBSample/

I get this:
curl: (56) Recv failure: Connection reset by peer

However, if i install curl inside the container and curl localhost at port 9130 it works smooth, so the application is running there. Is there any problem with the ports or with mapping that i should be aware of? I have also tried disabling the firewall completely, just in case it was blocking it somehow.



    Alex Weidner

    Hi, thanks for the feedback. There is actually something that I missed in the original blog post, and that is that the host in the Java project must be set to “*” or “”. The default is “localhost” which when ran inside of a Docker container, will not be available outside of it, as you’ve found. I hope that this helps clear up your issue. I’ll modify the tutorial as needed.



      Hi Alex:

      see your feedback “the host in the Java project must be set to “*” or “”. The default is “localhost” which when ran inside of a Docker container, will not be available outside of it.”

      How could I solve this problem for access to the web addr “http://localhost:9130/JAXWSEJBSample/” outside the container?



try to download your files and the EJB is not on the samples anymore


Kyle Lieber

The link to the sample project is wrong. I found it here:


Marcos Maia

Can I push the docker/liberty setup to run it in Bluemix?



Thanks for the tutorial
Somebody know if I can use docker with software licenced?, for example IBM Websphere ND 8.5



Yes, you can use docker with WebSphere ND



the link to the EJB-web-services-sample thing is dead

More How-tos stories

Tutorial: GitHub Traffic Analytics with Cloud Functions and Cloud Foundry

In a new solution tutorial, I show you how to automatically retrieve and store GitHub traffic data the serverless way with IBM Cloud Functions and Db2. The data can then be analyzed via a Web app deployed to Cloud Foundry on IBM Cloud. The app is secured with App ID using OpenID Connect. The new service Dynamic Dashboard Embedded provides visualization of the views and clones of GitHub repositories.

Continue reading

Cloning an App ID instance configuration

With App ID, you can now manage your service instance with an API!

Continue reading

IBM Cloud Foundry – CF Summit Summary and Path Forward

The Cloud Foundry Summit 2018 Boston just ended, and all I can say is wow! I'm the Offering Manager for IBM Cloud Foundry, and let me just say, it's been an honor representing IBM Cloud Foundry this week and working with all the incredible IBM technology people supporting this IBM Cloud compute offering. There was so much going on, so many great new things to learn, and so much news all around, it was a world-wind week of Cloud Foundry excellence.

Continue reading