Tomcat + CodeDeploy: Your Path to Effortless Application Deployment
In DevOps, Continous Deployment is the term you will often hear. You might have also come across the AWS CodeDeploy and CodeDeploy-local. Codedeploy makes the deployment process easy and manageable. AWS also supports testing and debugging code-deploy locally before using the AWS Codedeploy service on instances. So, let's explore the code-deploy-local and tomcat setup along with it.
Install Codedeploy-agent
First thing first, install the code deploy-agent in your on-premise device.
You can follow this official AWS documentation link
https://docs.aws.amazon.com/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html
Setup Codedeploy-local
It is not a compulsory step, but it will make your journey easier.
If you use a configuration file on Amazon Linux, RHEL, or Ubuntu Server instances, you must either:
Use the
:root_dir:
and:log_dir:
variables to specify locations other than the defaults for the deployment root and log directory folders.Use
sudo
to run CodeDeploy agent commands.
These points are directly taken from AWS official documentation and you should keep this always in mind and especially the second point.
For your ease, follow this link https://aws.amazon.com/blogs/devops/how-to-test-and-debug-aws-codedeploy-locally-before-you-ship-your-code/ and create alias as said in the blog.
Leave the default path of the code deploy agent for now. You can change it but you should configure the configuration file as per the new directory.
It's time now to work on the main file.
Project Structure
Here, the demo-0.0.... is the war file which we will deploy in the Tomcat server.
Main appspec.yml
IT'S NOT YAML. IT'S YML. This one-letter difference took me almost 3 days. Yeah, it's my fault as I didn't watch the documentation properly but you be aware from the beginning. Create the appspec.yml file in the root directory where you want the project.
version
This section specifies the version of the AppSpec file. Do not change this value. It is required. Currently, the only allowed value is
0.0
. It is reserved by CodeDeploy for future use.Specify the version with a string.
os
This section specifies the operating system value of the instance to which you deploy. It is required. The following values can be specified:
linux โ The instance is an Amazon Linux, Ubuntu Server, or RHEL instance.
windows โ The instance is a Windows Server instance.
Specify os with a string.
hooks
This section specifies scripts to run at specific deployment lifecycle events during the deployment.
For more information, see AppSpec 'hooks' section.
In our case, there are four defined exclusively life cycle events.
ApplicationStop
This contains application-stop.sh script which stops the running tomcat service.
The script required for this event is inside the scripts-> application-stop.sh
BeforeInstall
This contains before-install.sh script which sets up the tomcat user and group, installs tomcat as per condition and copies the tomcat service file for systemd.
#!/bin/bash
set -e
CATALINA_DIR="/home/mahesh" #my tomcat catalina directory
TOMCAT_VERSION_NUMBER=9.0.78
echo "Tomcat group and user are going to be created."
TOMCAT_GROUP="tomcat"
TOMCAT_USER="tomcat"
# Create the Tomcat group
if ! getent group "${TOMCAT_GROUP}" > /dev/null; then
groupadd "${TOMCAT_GROUP}"
fi
# Create the Tomcat user without login shell access
if ! getent passwd "${TOMCAT_USER}" > /dev/null; then
useradd -M -g "${TOMCAT_GROUP}" -s /usr/sbin/nologin "${TOMCAT_USER}"
fi
# Print a message indicating the successful creation of the group and user
echo "group and user got created successfully"
#make PROJECT_HOME directory
if [ -d "${PROJECT_HOME}" ];
then
rm -rf ${PROJECT_HOME}
echo "removed PROJECT_HOME"
mkdir ${PROJECT_HOME}
echo "created PROJECT_HOME"
else
mkdir ${PROJECT_HOME}
fi
#
#######changed the owner group
chmod 755 -R ${PROJECT_HOME}
chown tomcat:tomcat -R ${PROJECT_HOME}
echo "made the owner tomcat and changed the mode to 755"
##check if tomcat is already installed or not
if [[ -d "${CATALINA_DIR}/apache-tomcat-${TOMCAT_VERSION_NUMBER}" ]];
then
echo "Tomcat is installed at ${CATALINA_DIR}/apache-tomcat-${TOMCAT_VERSION_NUMBER}"
echo "no need to download"
else
echo "Tomcat is not installed at ${CATALINA_DIR}/apache-tomcat-${TOMCAT_VERSION_NUMBER}"
###download tomcat
wget https://downloads.apache.org/tomcat/tomcat-9/v${TOMCAT_VERSION_NUMBER}/bin/apache-tomcat-${TOMCAT_VERSION_NUMBER}.tar.gz
####extract tomcat
tar -xzvf apache-tomcat-${TOMCAT_VERSION_NUMBER}.tar.gz -C ${CATALINA_DIR}
rm -rf apache-tomcat-${TOMCAT_VERSION_NUMBER}.tar.gz
###permission to tomcat user
#need to change owner and group from mahesh to tomcat in the final one
chmod 755 -R "${CATALINA_DIR}/apache-tomcat-${TOMCAT_VERSION_NUMBER}"
chown tomcat:tomcat -R "${CATALINA_DIR}/apache-tomcat-${TOMCAT_VERSION_NUMBER}"
fi
if [[ -f "/etc/systemd/system/tomcat.service" ]];
then
# cp -f tomcat-service-file /etc/systemd/system/tomcat.service
echo "found service file but copied new service file"
chmod 755 /etc/systemd/system/tomcat.service
chown tomcat:tomcat /etc/systemd/system/tomcat.service
echo "changed user and permission for service file"
systemctl daemon-reload
systemctl enable tomcat
echo "service found"
else
echo "no service not found"
## description: Tomcat startup/ shutdown script
# process name: tomcat
cp -f tomcat-service-file /etc/systemd/system/tomcat.service
echo "copied service file"
chmod 755 /etc/systemd/system/tomcat.service
chown tomcat:tomcat /etc/systemd/system/tomcat.service
echo "changed user and permission for service file"
systemctl daemon-reload
systemctl enable tomcat
fi
AfterInstall
This contains after-install.sh which removes ROOT and ROOT.war from webapps of catalina directory and copies war file to webapps as ROOT.war and deplyos it to tomcat server.
#!/bin/bash
set -e
DEPLOY_TO_ROOT='true'
WAR_STAGED_LOCATION="/home/mahesh/Desktop/projects/tomcat-codedeploy-test/demo-0.0.1-SNAPSHOT.war"
CATALINA_DIR="/home/mahesh"
TOMCAT_VERSION_NUMBER=9.0.78
# In Tomcat, ROOT.war maps to the server root
if [[ "$DEPLOY_TO_ROOT" = 'true' ]];
then
CONTEXT_PATH='ROOT'
fi
# Remove unpacked application artifacts
if [[ -f "${CATALINA_DIR}/apache-tomcat-${TOMCAT_VERSION_NUMBER}/webapps/${CONTEXT_PATH}.war" ]];
then
rm "${CATALINA_DIR}/apache-tomcat-${TOMCAT_VERSION_NUMBER}/webapps/${CONTEXT_PATH}.war"
fi
if [[ -d "${CATALINA_DIR}/apache-tomcat-${TOMCAT_VERSION_NUMBER}/webapps/${CONTEXT_PATH}" ]];
then
rm -rf "${CATALINA_DIR}/apache-tomcat-${TOMCAT_VERSION_NUMBER}/webapps/${CONTEXT_PATH}"
fi
# Copy the WAR fsile to the webapps directory
cp "${WAR_STAGED_LOCATION}" "${CATALINA_DIR}/apache-tomcat-${TOMCAT_VERSION_NUMBER}/webapps/${CONTEXT_PATH}.war"
ApplicationStart
This contains application-start.sh script which starts the tomcat service.
Conclusion
If you have set up the following stepwise mentioned in the blog, you can run the command:
codedeploy-local #run it from the root where appspec.yml file is present
You can find me here:
GitHub ( Full code can be found in this repo. You can clone and make use of it)
LinkedIn (You can connect and message me in case of any issues)
Follow me on the hashnode for more content. Thank you!
Subscribe to my newsletter
Read articles from Mahesh Upreti directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Mahesh Upreti
Mahesh Upreti
I am a DevOps and Cloud enthusiast currently exploring different AWS services and DevOps tools.