Deploying a Java Spring Boot Application on CentOS 7
This guide details the steps to deploy a Java Spring Boot application on a CentOS 7 server, covering enviroment setup, service installation, and automated deployment scripts.
Initial Server Configuration
Begin by installing essential tools and creating necessary directories.
yum install wget vim net-tools -y
mkdir -p /data/{html,backend}
Installing Java Development Kit 17
Install JDK 17, which is required to run the Java application.
# Download the JDK 17 RPM package
wget https://download.oracle.com/java/17/latest/jdk-17_linux-x64_bin.rpm
# Install the package
sudo yum -y localinstall ./jdk-17_linux-x64_bin.rpm
# Verify the installation
java -version
Successful installation will output version details similar to:
java version "17.0.11" 2024-04-16 LTS
Java(TM) SE Runtime Environment (build 17.0.11+7-LTS-207)
Java HotSpot(TM) 64-Bit Server VM (build 17.0.11+7-LTS-207, mixed mode, sharing)
Installing and Configuring Nginx
Nginx will act as a reverce proxy for the application.
# Install Nginx from the EPEL repository
yum install epel-release -y
yum install nginx -y
Configuration files are typically located in /etc/nginx/conf.d/. Create or edit a configuration file (e.g., app.conf) to define proxy rules for your application's endpoints.
Installing and Securing Redis
Install Redis, which will be used as a caching layer or session store.
# Install Redis
yum install redis -y
# Start the Redis service
systemctl start redis
# Enable Redis to start on boot
systemctl enable redis
# Check the service status
systemctl status redis
To set a password, edit the Redis configuration file:
vi /etc/redis.conf
Find the line # requirepass foobared, uncomment it, and replace foobared with a strong password.
Preparing for Automated Deployment
Set up SSH key-based authentication from your local machine to the server to enable secure file transfers.
# On your local machine, copy the public key to the server
ssh-copy-id root@your_server_ip
Build and Deployment Script
The following script, run from a local development or CI/CD machine, builds the project and deploys it to the server. It assumes a Gradle project structure.
#!/bin/bash
# deploy.sh - Builds the project and transfers the JAR to the server
SERVER_IP="192.168.7.166"
PROJECT_HOME="/local/path/to/your/project"
REMOTE_DIR="/data/backend"
cd "${PROJECT_HOME}"
git pull
# Build the project, skipping tests and other non-essential tasks
./gradlew :application-module:build -x test \
-Dorg.gradle.java.home='/usr/local/jdk-17.0.8' \
-Dorg.gradle.daemon=true
if [ $? -ne 0 ]; then
echo "Build failed. Exiting."
exit 1
fi
# Copy the built JAR file to the server
JAR_FILE="${PROJECT_HOME}/application-module/build/libs/application-0.0.1-SNAPSHOT.jar"
scp "${JAR_FILE}" root@${SERVER_IP}:${REMOTE_DIR}/
# Execute the remote restart script
ssh root@${SERVER_IP} << 'ENDSSH'
cd /data/backend
./service_restart.sh
ENDSSH
Server-Side Management Scripts
Create the folowing helper scripts in the server's /data/backend directory.
1. Port Check Script (port_check.sh)
This script checks if a given port is in use.
#!/bin/bash
# port_check.sh - Checks if a port is in use. Returns 1 if used, 0 if free.
TARGET_PORT=$1
PROCESS_ID=$(lsof -ti:${TARGET_PORT})
if [ -n "${PROCESS_ID}" ]; then
echo "1"
else
echo "0"
fi
2. Application Restart Script (service_restart.sh)
This is the main script that stops the old instance and starts the new one, updating the Nginx configuration.
#!/bin/bash
# service_restart.sh - Manages application lifecycle and Nginx proxy.
ACTIVE_PORT=8080
PREVIOUS_PORT=8081
TIMESTAMP=$(date +"%Y%m%d%H%M%S")
# Determine which port is free
PORT_STATUS=$(./port_check.sh ${ACTIVE_PORT})
if [ "${PORT_STATUS}" -eq "1" ]; then
echo "Port ${ACTIVE_PORT} is occupied. Switching to port ${PREVIOUS_PORT}."
ACTIVE_PORT=8081
PREVIOUS_PORT=8080
else
echo "Port ${ACTIVE_PORT} is available for use."
fi
# Start the new application instance on the chosen port
nohup java -Dspring.profiles.active=prod \
-Dserver.port=${ACTIVE_PORT} \
-jar application-0.0.1-SNAPSHOT.jar > app_${ACTIVE_PORT}.log 2>&1 &
# Wait for the application to fully start (looks for startup message in logs)
tail -f app_${ACTIVE_PORT}.log | grep -m 1 "Started Application in"
# Update Nginx configuration to point to the new port
echo "proxy_pass http://127.0.0.1:${ACTIVE_PORT};" > /etc/nginx/conf.d/app_proxy.conf
nginx -s reload
# Gracefully shut down the previous instance after a short delay
sleep 15
SHUTDOWN_RESPONSE=$(curl -s http://127.0.0.1:${PREVIOUS_PORT}/actuator/shutdown || echo "0")
if [ "${SHUTDOWN_RESPONSE}" != "{\"message\":\"Shutting down\"}" ]; then
echo "Warning: Graceful shutdown of previous instance may have failed."
# Optionally force kill the process on the old port
# pkill -f "server.port=${PREVIOUS_PORT}"
else
echo "Previous instance shut down successfully."
fi
Make both scripts executable:
chmod +x /data/backend/port_check.sh /data/backend/service_restart.sh
Installing Additional Dependencies (Tesseract OCR)
If your application requires Optical Character Recognition (OCR), install Tesseract.
yum install tesseract tesseract-langpack-deu -y
Database Configuration
This deployment assumes a pre-configured remote database (e.g., Alibaba Cloud RDS). Ensure your application's application-prod.properties or application.yml file contains the corrrect JDBC URL, username, and password for the production database.