Skip to content

Java App with Docker, Jenkins, and Kubernetes

Level:Intermediate
Time:2-3 hours
Cost:medium
Works locally:No
Cloud creds:Yes
Cleanup:Yes
Reviewed:2026-05-30
Validation:kubectl apply --dry-run=client -f hello-world/regapp-deploy.yml -f hello-world/regapp-service.yml

Jenkins-on-EC2 lab deploying a Java web app container.

Outcome Passing pipeline run plus scan/deploy evidence
Tools used Java, Maven, Docker, Kubernetes, AWS, Jenkins
Best fit Intermediate - 2-3 hours
Student workstation Repository files CI/CD pipeline AWS account Validation proof
  • Install or review: Java, Maven, Docker, Kubernetes, AWS, Jenkins.
  • Use your own cloud account credentials and keep them out of commits.
  • This project expects cloud resources, so verify budget alerts and cleanup first.
  • Open the safety guide before running commands that create infrastructure.
Cost and credential stance

Cost risk is medium. Cloud target: AWS. Cloud credentials needed: Yes. Always use your own account, never commit secrets, and confirm cleanup before creating paid infrastructure.

Use this flow before you run commands:

  1. Read the cost and credential warning above.
  2. Review the validation, troubleshooting, cleanup, and portfolio proof sections below.
  3. Follow the original project guide preserved near the bottom of this page.
  4. Return to the validation and cleanup checks before you capture portfolio evidence.

Run the project validation command before and after meaningful changes:

Terminal window
kubectl apply --dry-run=client -f hello-world/regapp-deploy.yml -f hello-world/regapp-service.yml
  • Run kubectl apply --dry-run=client -f hello-world/regapp-deploy.yml -f hello-world/regapp-service.yml first so local tooling issues are visible early.
  • If a command fails, check tool versions, working directory, and required environment variables.
  • For cloud failures, confirm account identity, region, quotas, and least-privilege IAM.
  • For pipeline failures, check repository secrets, runner permissions, and pinned action versions.

Cleanup is available or expected for this lab. Use the cleanup or destroy steps in the guide below, then confirm that local clusters, containers, cloud resources, buckets, state files, and CI secrets are no longer active.

  • Validation command output: kubectl apply --dry-run=client -f hello-world/regapp-deploy.yml -f hello-world/regapp-service.yml
  • Screenshot or terminal proof: Passing pipeline run plus scan/deploy evidence
  • Notes explaining what changed, what failed, and how you fixed it
  • Cleanup evidence, especially for cloud or Kubernetes resources

The original README content is preserved here for lab-specific commands and context. Headings are intentionally demoted so the page outline stays focused on the standard lab flow.

External image reference AWS

In this blog, we are going to deploy a Java Web app on a Docker Container built on an EC2 Instance through the use of Jenkins.

  • Install Jenkins, Java & Maven on AWS EC2
  • Install Docker
  • Integrate Maven and Docker with Jenkins
  • Create Dockerfile and push to Github
  • Build the job on Jenkins
  • Publish the Docker image on the container
🛡️ 2026 DevSecOps Enhancements (What You Will Learn)
Section titled “🛡️ 2026 DevSecOps Enhancements (What You Will Learn)”

This legacy tutorial has been augmented with modern Cloud Native security standards. As you follow the deployment, observe the security improvements in the provided source code:

  1. Unprivileged Containers: The Dockerfile has been stripped of its default root user. It now formally executes as a restricted user to mitigate container breakout risks.
  2. Explicit K8s Resource Bounds: The deployment manifests now enforce strict CPU and Memory limits to prevent noisy-neighbor node starvation.
  3. Immutability: Static latest tagging has been eradicated from the pipeline in favor of traceable, semantic versioning.
  • AWS Account
  • Git/ Github Account with the Source Code
  • A local machine with CLI Access
  • Familiarity with Docker and Git
Step 1: Setup Jenkins Server on AWS EC2 Instance
Section titled “Step 1: Setup Jenkins Server on AWS EC2 Instance”
  • Setup a Linux EC2 Instance
  • Install Java
  • Install Jenkins
  • Start Jenkins
  • Access Web UI on port 8080

Log in to the Amazon management console, open EC2 Dashboard, click on the Launch Instance drop-down list, and click on Launch Instance as shown below:

External image reference AWS

Once the Launch an instance window opens, provide the name of your EC2 Instance:

External image reference AWS

Choose an Instance Type. Here you can select the type of machine, number of vCPUs, and memory that you want to have. Select t2.micro which is free-tier eligible.

External image reference AWS

For this demo, we will select an already existing key pair. You can create new key pair if you don’t have:

External image reference AWS

Now under Network Settings, Choose the default VPC with Auto-assign public IP in enable mode. Create a new Security Group, provide a name for your security group, allow ssh traffic, and custom default TCP port of 8080 which is used by Jenkins.

External image reference aws

Rest of the settings we will keep them at default and go ahead and click on Launch Instance

External image reference aws

On the next screen you can see a success message after the successful creation of the EC2 instance, click on Connect to instance button:

External image reference AWS

Now connect to instance wizard will open, go to SSH client tab and copy the provided chmod and SSH command:

External image reference aws

Open any SSH Client in your local machine, take the public IP of your EC2 Instance, and add the pem key and you will be able to access your EC2 machine in my case I am using MobaXterm on Windows:

External image reference aws

After logging in to our EC2 machine we will install Jenkins following the instructions from the official Jenkins website: https://pkg.jenkins.io/redhat-stable/

To use this repository, run the following command:
Section titled “To use this repository, run the following command:”
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key

Output:

External image reference aws

Now let’s install epel packages for Amazon Linux AMI:

External image reference aws

After installing epel packages, let’s install java-openjdk11:

External image reference aws

Let’s check the version of Java now:

External image reference aws

Now let’s install Jenkins with the below command as shown in the output:

External image reference aws

After successful installation Let’s enable and start Jenkins service in our EC2 Instance:

External image reference aws

Now let’s try to access the Jenkins server through our browser. For that take the public IP of your EC2 instance and paste it into your favorite browser and should see something like this:

External image reference aws

To unlock Jenkins we need to go to the path /var/lib/jenkins/secrets/initialAdminPassword and fetch the admin password to proceed further:

External image reference aws

Now on the Customize Jenkins page, we can go ahead and install the suggested plugins:

External image reference aws

Now we can create our first Admin user, provide all the required data and proceed to save and continue.

External image reference aws

Now we are ready to use our Jenkins Server.

External image reference aws
  • Install Git on Jenkins Instance
  • Install Github Plugin on Jenkins GUI
  • Configure Git on Jenkins GUI

Let’s first install Git on our EC2 instance with the below command:

External image reference aws

We can check the version as shown in the below screenshot:

External image reference aws

To install the GitHub plugin lets go to our Jenkins Dashboard and click on manage Jenkins as shown:

External image reference aws

On the next page, click on manage plugins:

External image reference aws

Now in order to install any plugin we need to select Available Plugins, search for Github Integration, select the plugin, and finally click on Install without restart as shown below:

External image reference aws

Now let’s configure Git on Jenkins. Go to Manage Jenkins, and click on Global Tool Configuration.

External image reference aws

Under Git installations, provide the name Git, and under Path, we can either provide the complete path where our Git is installed on the Jenkins machine or just put any name, in my case I put Git to allow Jenkins to automatically search for Git. Then click on Save to complete the installation.

External image reference aws
  • Setup Maven on Jenkins Server
  • Setup Environment Variables JAVA_HOME,M2,M2_HOME
  • Install Maven Plugin
  • Configure Maven and Java

To install Maven on our Jenkins Server we will switch to the /opt directory and download the Maven package:

External image reference aws

Now we will extract the tar.gz file:

External image reference aws

Now we will set up Environment Variables for our root user in bash_profile in order to access Maven from any location in our Server Go to the home directory of your Jenkins server and edit the bash_profile file as shown in the below steps:

External image reference aws

In the .bash_profile file, we need to add Maven and Java paths and load these values.

External image reference aws

To verify follow the below steps:

External image reference aws

With this setup, we can execute maven commands from anywhere on the server:

External image reference aws

Now we need to update the paths where Java and Maven have been installed in the Jenkins UI. We will first install the Maven Integration Plugin as shown below:

External image reference aws

After clicking on Install without restart, go again to manage Jenkins and select Global Tool configuration to set the paths for Java and Maven.

For JAVA:

External image reference aws

For MAVEN:

External image reference aws

Click on save and hence we have successfully Integrated Java and Maven with Jenkins.

  • Setup a Linux EC2 Instance
  • Install Docker
  • Start Docker Services
  • Run Basic Docker Commands

Let’s first launch an EC2 Instance. We will skip the steps here as we have already shown earlier how to create an EC2 Instance.

Below is the screenshot of our newly created EC2 Instance on which we will install Docker:

External image reference aws

We will first install Docker on this EC2 Instance:

External image reference aws

After the successful installation of Docker, let’s verify the version of Docker:

External image reference aws

Also, let’s enable and start the Docker Service:

External image reference aws

In my previous blog, I deployed a Java code on a Tomcat VM, here in this blog we will deploy on a Tomcat Docker container.

We will first pull the official Tomcat docker image from the Docker Hub and then run the container out of the same image.

External image reference aws

Let’s now create a Container from the same Image with the command:

docker run -d --name tomcat-container -p 8081:8080 tomcat
External image reference aws

The above command runs a docker container in detached mode with the name tomcat-container and we are exposing port 8081 of our host machine with port 8080 of our container and it’s using the latest image of tomcat.

Let’s verify the running container on our EC2 machine:

External image reference aws

Before accessing our container from the browser we need to allow port 8081 in the Security Group of our EC2 docker-host machine.

Go to the Security group of your EC2 machine and click on Edit inbound rules:

External image reference aws

Click on Add rule, select Custom TCP as type, and in port range put 8081–9000 in case we need it in the future, and under source select from anywhere and then click on Save rules to proceed:

External image reference aws

Now let’s take the public IP of our Docker-host EC2 machine and with port 8081 access it from our browser:

External image reference aws

From the above screenshot, you can see that although there is a 404 error, it also displays Apache Tomcat at the bottom which means the installation is successful however this is a known issue with the Tomcat docker image that we will fix in the next steps.

The above issue occurs because whenever we try to access the Tomcat server from the browser it will look for the files in /webapps directory which is empty and the actual files are being stored in /webapps.dist.

So in order to fix this issue we will copy all the content from webapps.dist to webapps directory and that will resolve the issue.

Let’s access our tomcat container and perform the steps as shown below:

External image reference aws

Once we are in the tomcat container go to the /webapps.dist directory and copy all the content to webapps directory:

External image reference aws

After that we should be able to access our tomcat docker container:

External image reference aws

Somehow if we stop this container and start another container with the same Image on a different port we will face the same issue of 404 error. This happens because every time we launch a new container we are using a new Image as the previous container gets deleted.

This issue can be solved by creating our own Docker Image with the appropriate changes required to run our container. This can be achieved by creating a Dockerfile on which we can mention the steps required to build the docker image and from that Image, we can run the container.

Create a Customized Dockerfile for Tomcat:

To create the Dockerfile we will use the official Image of Tomcat and with it will mention the step to copy the contents from the directory /webapps.dist to /webapps:

FROM tomcat:10.1-jdk17-temurin
RUN cp -R /usr/local/tomcat/webapps.dist/* /usr/local/tomcat/webapps
External image reference aws

Now let’s build the Docker Image using this Dockerfile using the below command:

docker build -t tomcatserver .
External image reference aws

Let’s verify with the docker images command:

External image reference aws

Now is the time to run the docker container out of our customized docker image which we built using our dockerfile. The command is as:

docker run -d --name tomcat-server -p 8085:8080 tomcatserver

Here you should remember that we have already allowed port range 8081–9000 in the security group of our docker EC2 Instance.

External image reference aws

Let’s verify using the docker ps command:

External image reference aws

Also, let’s try to access the Tomcat server on port 8085 from the browser:

External image reference aws

Hence we should be now able to launch as many times the same container without facing any issues by utilizing our customizable Dockerfile.

  • Create a dockeradmin user
  • Install the “Publish Over SSH” plugin
  • Add Dockerhost to Jenkins “configure systems”

Let’s first create a dockeradmin user and create a password for it as well.

External image reference aws

Now let’s add this user to the Docker group with the below command:

usermod -aG docker dockeradmin

Now in order to access the server using the newly created User we need to allow password-based authentication. For that, we need to do some changes in the /etc/ssh/sshd_config file.

External image reference aws

As you can see above we need to uncomment PasswordAuthentication yes and comment out PasswordAuthentication no.

Once we have updated the config file we need to restart the services with the command:

service sshd reload
Redirecting to /bin/systemctl reload sshd.service

Now we would be able to log in using the dockeradmin user credentials:

External image reference aws

Now next step is to integrate Docker with Jenkins, for that we need to install the “Publish Over SSH” plugin:

Go to Manage Jenkins > Manage Plugins > Available plugins and search for publish over ssh plugin:

External image reference aws

Click on Install without restart to install the plugin.

Now we need to configure our dockerhost in Jenkins. For that go to Manage Jenkins > Configure System:

External image reference aws

On the next page after scrolling down you would be able to see Publish over SSH section where you need to add a new SSH server with the info as shown below:

External image reference aws

It should be noted that it’s best practice to use ssh keys however for this demo we are using password-based authentication. In the above screenshot, we have provided details of our Docker host which we created on EC2 Instance. Also, note the use of private IP under Hostname as both our Jenkins Server and Dockerhost are on the same subnet. We can also use Public IP here.

Click on Apply and Save to proceed. With this, our Docker integration with Jenkins is successfully accomplished.

Step 6: Create Jenkins Job to Build and Copy Artifacts on to Docker Host
Section titled “Step 6: Create Jenkins Job to Build and Copy Artifacts on to Docker Host”

In this section, we would create a new job in Jenkins however we would copy from the existing job

External image reference aws

Click on Ok to configure the job.

On the configure settings you will notice that our new job has inherited all the settings from our previous build job. However, you can change the description and other settings:

External image reference aws

Now one important change we need to do is to delete the previous job post-build step and select Send files or execute commands over SSH option.

Under the SSH server, it will display the already created ssh server which we created in our earlier steps. Then we need to provide the path from where the WAR file will be copied and then deployed on the remote server for which we also need to provide a path under the Remote directory. Then finally Apply and Save to proceed.

External image reference aws

Once we save the project the build will be triggered automatically due to Poll by SCM feature which we have enabled.

Now if we check the console output of our job we should see the Job has been successfully finished.

External image reference aws

We can also verify by checking the presence webapp.war file on our docker EC2 machine:

External image reference aws
Step 7: Update Dockerfile to copy Artifacts to launch New Container
Section titled “Step 7: Update Dockerfile to copy Artifacts to launch New Container”

In this step, we will create a Dockerfile to include the webapp.war file to launch a new container using our Java web Application. For that, we need to copy our artifacts to the location where we have our Dockerfile.

We will create a separate directory named docker under the root user of our dockerhost inside /opt.

External image reference aws

As you can in the above screenshot that this new docker directory is owned by root and in Jenkins configuration settings we have mentioned that the artifacts are owned by the dockeradmin user. So let’s give the ownership of this directory to dockeradmin user.

External image reference aws

Now let’s copy the Dockerfile which we created in earlier steps to this newly created docker directory and change its ownership to dockeradmin as well:

mv Dockerfile /opt/docker/
cd /opt/docker/
chown -R dockeradmin:dockeradmin /opt/docker/
ll
total 4
-rw-r--r-- 1 dockeradmin dockeradmin 89 May 10 12:08 Dockerfile

Now we need to configure our Jenkins job to change the remote directory from /home/dockeradmin to //opt//docker:

External image reference aws

Click on Apply and Save to build the Job manually.

If the build is successful we can see the webapp.war file in the /opt/docker directory of our dockerhost:

External image reference aws

Now in our Dockerfile, we need to mention the location of this WAR file and copy this file onto the /usr/local/tomcat/webapps location in the container.

Dockerfile:

FROM tomcat:10.1-jdk17-temurin
RUN cp -R /usr/local/tomcat/webapps.dist/* /usr/local/tomcat/webapps
COPY ./*.war /usr/local/tomcat/webapps

Let’s now build a new image using this updated Dockerfile with the command:

docker build -t tomcat:v1 .

Output:

External image reference aws

In the next step let’s now create a container out of this image with the command:

docker run -d --name tomcatv1 -p 8086:8080 tomcat:v1

Output:

External image reference aws

Now let’s access this application from our browser using URL http://54.173.227.226:8086/webapp/

External image reference aws

So far we have successfully copied the artifacts to our dockerhost and then manually used docker commands like docker build and docker run to deploy our application on the docker container.

Step 8: Automate Build and Deployment on Docker Container
Section titled “Step 8: Automate Build and Deployment on Docker Container”

In this step, we will try to automate end to end Jenkins pipeline right from when we commit our code to GitHub, it should build it, create an artifact and then copy the artifacts to the docker host, create a docker image, and finally create a docker container to deploy the project.

For this automation to happen we need to go to our Jenkins job, select configure, and under Send files or execute commands over SSH there is Exec command field where we need to put some commands as shown below:

cd /opt/docker;
docker build -t regapp:v1 .;
docker run -d --name registerapp -p 8087:8080 regapp:v1
External image reference aws

Now let’s do some minor changes in our code and commit the changes which will trigger the Jenkins build process and we can see the results of automation.

As soon as I made some changes in the Readme file in the GitHub repository the build got triggered in our Jenkins Job.

If the build is successful we should see our new docker image and docker container as shown in the below screenshot:

External image reference aws

Also, we if access our new dockerized app from our browser on port 8087, the result should be something like this:

External image reference aws

In this blog, we learned how to automate the build and deploy process using GitHub, Jenkins, Docker, and AWS EC2.

Happy Learning!

If you are planning to use this repo for learning, please hit the star. Thanks!

External image reference Source image
Use the guide first.

The full learning flow stays on this page. Open GitHub only when a step asks you to inspect code, fork the lab, or download source assets.