This article demonstrates continuous integration between a GitHub project, and a Java web application running on WebSphere Liberty in a Docker container in Amazon’s AWS Elastic Beanstalk environment.

We’ll take this simple user story:

“As a developer, I want code changes I push to GitHub to be automatically deployed to ‘the cloud’ – in this case, a web application running on WebSphere Liberty, in a Docker container, on Amazon Beanstalk.”

This article is part of a series about running WebSphere Liberty applications in Amazon AWS. Jeremy Hughes and I showed an easy way to run, scale and load balance WebSphere Liberty in Amazon virtual machines. We used a pre-canned application and plain EC2 virtual machines, and took manual steps in several places.

In this article, we broaden our scope. The application code starts as source, we run Liberty inside a Docker container, and we fully automate the application build and deployment. This article will show you how to get our user story working for yourself, using tools and services that are free to developers.

Here’s our user story in a picture:


Our target user story

We’re introducing several new technologies here. These are probably familiar to you, but just in case:

  • Git is a distributed version control system. Git is free and open source, and the most widely used source control system in the world.
  • GitHub is a web-based Git repository hosting service, and currently the world’s largest host of source code.
  • Travis CI is a web-based continuous integration (CI) service that can build, test and deploy code hosted in GitHub.
  • Docker is an open source technology for automating software deployment. Docker containers ‘wrap a piece of software in a complete filesystem that contains everything needed to run: code, runtime, system tools, system libraries – anything that can be installed on a server. This guarantees that the software will always run the same, regardless of its environment.’ Containers start and stop more quickly, and require less disk and memory than virtual machines.
  • AWS Elastic Beanstalk is a “an easy-to-use service for deploying and scaling web applications and services developed with Java, .NET, PHP, Node.js, Python, Ruby, Go, and Docker”.
  • WebSphere Liberty is a fast, dynamic, easy-to-use Java EE application server. It’s ideal for developers but also ready for production, on-premise or in the cloud.
  • Maven is a powerful ‘software project management and comprehension tool’ that is widely used for building Java projects.

Our focus here is on ways to use WebSphere Liberty in Amazon AWS. Elastic Beanstalk has native Java support but it’s tied to Tomcat as a runtime. Docker allows us to package Liberty in a form that Beanstalk understands. Docker is in many ways a platform in its own right and provides a degree of isolation from the specifics of the cloud provider. It encourages the use of immutable images, which can help reduce the differences between development, test and production environments.

How to get it working

In order to run this sample you will need:

  • An Amazon AWS account, with access to S3 and Elastic Beanstalk.
  • Your AWS access key ID and secret access key. Please note that Amazon advise against providing AWS secret key and access key id to third parties, but it’s necessary in this case. You might wish to create temporary credentials for the purpose of this exercise. Pld. See Best Practices for Managing AWS Access Keys for more information.
  • A GitHub account.
  • A machine from which you can run the mvn and git commands. Maven needs a Java SDK. We’ve tested this with Java 8; Java 7 should also be fine.

Follow these next steps once you’re ready:

  1. Go to GitHub and fork our sample project into your own repository.
  2. git clone your new repository to your development machine.
  3. cd into the sample.aws directory.
  4. Build the project: run the command mvn clean install.
  5. Our first deployment to Beanstalk is manual; all future updates are automated.
    1. Go to the AWS console in a web browser and select Elastic Beanstalk.
    2. Create a new application and environment. Give the application a name; e.g. sample.aws. We’ll need this as $APP_NAME later.
    3. Select the Docker platform.
    4. Upload the application: click Choose file and navigate to target/upload-1.0.zip
    5. Navigate the rest of the wizard. The default values are typically fine. You can optionally provide your EC2 keypair if you wish to log in to the EC2 instance.
    6. Review your settings deploy the test application.
    7. Revisit the Beanstalk summary page and note the new environment a name; this will be $ENV_NAME later on. Make a note of the Environment URL.
    8. Finally, navigate to S3 in the AWS console. You should see a bucket named elasticbeanstalk-{region}-{numbers}. We’ll need this whole string as $BUCKET_NAME in the next section.
  6. Test the application! The base environment URL will take you to the WebSphere Liberty landing page. Navigating to baseEnvironmentUrl/test will show a simple ‘hello world’ message – this is our running application.
  7. Next we’ll set up and test our automation:
    1. Browse to https://travis-ci.org and click Sign in with GitHub if you’re not logged in all ready.
    2. Grant Travis CI the permissions it requires and log in with your GitHub username and password.
    3. After an initial sync, Travis CI shows you a list of your GitHub repositories.


    sample repository viewed in Travis CI

    1. Select your project to enable Travis CI and then click the cog icon.
    2. Fill in the values for the six environment variables as shown in the example below. $REGION is your AWS region; it also appears in $BUCKET_NAME. We made notes of the first three values in the steps above. Ensure that Display value in build log is OFF when you enter your access key ID; you can’t change it later.


    General settings and environment variables in Travis CI

    1. At this point we’re ready to follow a code change through to deployment. Start by creating a new local branch: git checkout -b first.edit
    2. Edit src/main/java/test/TestServlet.java and change the message printed out by the Servlet.
      public void doGet (HttpServletRequest req, HttpServletResponse resp) throws IOException {
          resp.getWriter().println ("Hello world from edits during article preparation");  
      }
          
    3. Run git add src/main/java/test/TestServlet.java
    4. Run git commit
    5. Run git push origin first.edit
  8. Now visit https://travis-ci.org. In the left hand column under ‘My Repositories’ you’ll see that a new build has started. By the end you should see:


    Expected output from Travis CI when sample.aws is built

  9. Now re-visit the application to see your changes live on AWS. After a short delay you should see:


Updated application seen running in a web browser

That’s it! The git push has automatically produced our web application running on WebSphere Liberty, in a Docker container, on Amazon Beanstalk.

How it works

The sample application is as simple as possible. Travis integration is done through /.travis.yml. The first line of that file reads:

language: java
  

Travis CI can build Java projects using Maven, Gradle, or Ant. In our case, that causes Travis CI to invoke Maven against /pom.xml. There are three plug-ins in our pom. The first runs a (trivial) unit test, src/test/java/sample/HelloTest.java, whose only purpose is to act as a placeholder. The second plug-in runs the maven-war-plugin, packaging our Servlet into a WAR file. The final plug-in invokes the maven-assembly-plugin, which creates a ZIP file based on the instructions in src/assembly/bin.xml. The result is target/upload-1.0.zip, which contains two files: test.war, and resources/Dockerfile. Our Dockerfile is very simple:

FROM websphere-liberty
ADD test.war /opt/ibm/wlp/usr/servers/defaultServer/dropins/
ENV LICENSE accept

EXPOSE 9080
  

The Dockerfile highlights how simple it is to use WebSphere Liberty in a Docker container. WebSphere Liberty is a Java EE 7 certified application server with a small footprint and quick startup time. It uses simple XML for configuration while retaining runtime fidelity with WebSphere Application Server traditional. Liberty can be used for development at no charge, and can be downloaded from wasdev.net.

There are several ways to deploy a Docker container to Elastic Beanstalk. You can provide a Dockerfile or a Dockerrun.aws.json file to deploy a Docker container from an existing image. Alternatively, you can provide a ZIP file containing application files with a Dockerfile, a Dockerrun.aws.json, or both. In our case, we’ve opted to provide the application binary and a Dockerfile inside a ZIP file. In a CI pipeline we might choose to do a docker push in the .travis.yml and then provide the pre-built Docker image’s coordinates in the Dockerrun.aws.json file.

Once the Maven build has constructed target/upload-1.0.zip, Travis CI pushes it to Elastic Beanstalk. Here’s the rest of .travis.yml:

language: java
deploy:
  - provider: elasticbeanstalk
    skip_cleanup: true
    app: $APP_NAME
    env: $ENV_NAME
    bucket_name: $BUCKET_NAME
    region: $REGION
    access-key-id: $ACCESS_KEY_ID
    secret-access-key: $SECRET_ACCESS_KEY
    zip_file: target/upload-1.0.zip
    on:
      all_branches: true
  

skip_cleanup: true is needed to prevent target/upload-1.0.zip from being deleted before the deploy stage starts. As noted in the build output, the elasticbeanstalk provider is ‘experimental’ and is not listed on the main Travis CI documentation page. The best documentation is in the ‘dpl’ GitHub project.

You don’t have to use Travis CI to deploy to Elastic Beanstalk. Amazon provide two different command line options: aws elasticbeanstalk and eb. There are some notes in our sample project’s README about using the command line. We found this article on how to deploy Docker applications useful when getting started. The deploy-to-aws.sh script was particularly helpful.

Summary

We’ve shown how to push a branch to a fork of the sample.aws project, and have that change automatically deployed by Travis CI to Amazon Elastic Beanstalk. We used a simple Java project built by a single pom.xml and kept the ‘pipeline’ very short. This allowed us to focus on the steps required to get WebSphere Liberty running in a Docker container in the Elastic Beanstalk environment.

Acknowledgements

I’d like to thank KD Singh from AWS and Ross Pavitt from IBM for their valuable feedback and testing during the preparation of this article.

Join The Discussion

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