序言
在开发中,经常需要部署SpringBoot服务,所以来简单记录一下我比较常用的一些部署方式。
简单粗暴的脚本
这种方法其实就是直接使用java -jar命令进行启动Jar包,所以得需要系统安装好Java的环境,然后打包好服务
#!/bin/bash
JAVAHOME=$JAVA_HOME
echo "--------start--------"
PID=$(ps -ef|grep app.jar |grep -v grep|awk '{print $2}')
if [ ! $PID ]; then
nohup java -jar -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -Xms512m -Xmn768m -Xmx1024m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC app.jar > app.log 2>&1 &
echo "--------------start success-----------"
exit
else
kill -9 ${PID}
echo "--------------kill success-----------"
echo "---------------now wait start-------"
nohup java -jar -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=256m -Xms512m -Xmn768m -Xmx1024m -Xss256k -XX:SurvivorRatio=8 -XX:+UseConcMarkSweepGC app.jar > app.log 2>&1 &
echo "--------------start success-----------"
exit
fi
注意这种方法,简化了一些重启的操作,会寻找是否有名字为app.jar的服务进程,所以服务器上如果部署有多个服务,那么jar包不要重名,或者修改成路径
参数版脚本文件
这是我自己参考,然后修改的一个脚本文件,只要将该脚本文件和Jar包放入同一个目录下运行即可启动服务。
这种是本地启动的方式,所以需要自行配置服务器的Java环境。
#!/bin/bash
# 文件夹路径
FOLDER_PATH=''
# 服务名称
SERVER_NAME=''
# jar包名称
JAR_NAME=''
# PID文件
PID_FILE=''
# java -jar的参数
OPTIONS=''
# log文件
LOG_FILE=''
# 使用说明
usage() {
echo "Usage: sh ****.sh [OPTION]... "
echo -e "\033[43;37m 注意: 需要添加参数运行,否则无法成功运行 \033[0m"
echo -e "\033[43;37m 注意: 需要将本sh文件和jar包放在同一个文件夹 \033[0m"
echo "当前OPTION参数有以下几种"
echo " --info 查看当前服务信息"
echo " --start 启动服务"
echo " --stop 停止服务"
echo " --restart 重启服务"
echo " --status 查询服务运行状态"
exit 1
}
# 初始化
init() {
FOLDER_PATH=$( pwd )
JAR_NAME=$( ls -l |grep .jar | awk '{print$9}' )
SERVER_NAME=$( basename ${JAR_NAME} .jar )
PID_FILE=${SERVER_NAME}\.pid
LOG_FILE=${SERVER_NAME}\.log
OPTIONS='-Xms256m -Xmx512m'
}
# 获取环境信息
info() {
echo "----------检测是否有Java环境----------"
if ! command -v java &> /dev/null
then
echo "-bash: java: command not found"
echo "请检查是安装了Java环境,是否配置了环境变量"
else
echo "----------当前Java的环境为----------"
echo ""
echo "$( java -version )"
fi
echo "----------当前文件夹路径----------"
echo "当前文件夹路径为${FOLDER_PATH}"
echo "----------启动服务的信息----------"
echo "当前服务名称为${SERVER_NAME}"
echo "需要启动的jar包名称为${JAR_NAME}"
echo "保存的PID文件名称为${PID_FILE}"
echo "保存的LOG文件名称为${LOG_FILE}"
echo "----------java -jar的参数----------"
echo "当前参数为${OPTIONS},需要更改请执行 -setOptions参数进行修改"
}
# 查询当前程序是否运行
is_running() {
pid=`ps -ef|grep $JAR_NAME | grep -v grep | awk '{print $2}' `
# pid是否存在,存在返回1,不存在返回0
if [ -n "${pid}" ]; then
return 1
else
return 0
fi
}
# 启动服务
start() {
is_running
# 如果服务没有运行,则启动服务,否则不启动
if [ $? -eq "0" ]; then
init
echo "服务启动中,请稍后"
nohup java ${OPTIONS} -jar ${JAR_NAME} >${LOG_FILE} 2>&1 &
echo $! > ${PID_FILE}
echo "服务启动成功,当前的PID为$( cat ${PID_FILE} )"
else
echo "目标服务正在运行,请勿再次启动"
fi
}
# 停止服务
stop() {
is_running
if [ $? -eq "0" ]; then
echo "没有检测到服务启动,请启动之后在尝试"
exit 2
fi
pid=$(cat ${PID_FILE})
kill ${pid}
rm -rf ${PID_FILE}
sleep 1
is_running
if [ $? -eq "1" ]; then
kill -9 ${pid}
fi
echo "成功结束${SERVER_NAME}的进程"
}
# 查询服务运行状态
status() {
is_running
if [ $? -eq "1" ]; then
echo "${SERVER_NAME}服务正在运行中,当前服务的PID为${pid}"
else
echo "${SERVER_NAME}服务没有在运行"
fi
exit 0
}
# 重启服务
restart() {
is_running
if [ $? -eq "1" ]; then
stop
start
else
echo "当前服务并没有运行,请运行之后在尝试"
fi
exit 0
}
init
case "$1" in
"--info")
info
;;
"--start")
start
;;
"--stop")
stop
;;
"--status")
status
;;
"--restart")
restart
;;
*)
usage
;;
esac
exit 0
以下是使用方法
# 获取当前服务信息
sh start.sh --info
# 启动服务
sh start.sh --start
# 停止服务
sh start.sh --stop
# 查询服务状态
sh start.sh --status
# 重启服务
sh start.sh --restart
# 提示使用信息
sh start
其实这个脚本文件多多少少还是有一点问题的,提示信息也不是很美观,但是自己使用还是没什么问题的。
自动maven打包的Dockerfile
这种方法是通过Docker部署的方式,将源码使用maven打包成jar包,然后在容器内运行jar包。
步骤:
- 拉取Springboot源代码
- 如果需要自定义maven配置,请添加maven配置文件在于源码目录,或自己添加
- 修改服务打包生成的JAR包文件名
- 制作镜像
使用Docker的话,得自行选择需要的JDK镜像和Maven版本镜像,然后修改服务打包出来后的服务名即可。
# 多阶段构建:第一阶段用于编译 Spring Boot 项目
FROM maven:3.8.1-openjdk-17 AS builder
LABEL stage=builder
# 设置工作目录
WORKDIR /app
# 拷贝项目文件
COPY pom.xml .
COPY src ./src
# 如果需要自定义maven镜像仓库配置,请添加maven配置文件
COPY settings.xml /root/.m2/settings.xml
# 编译并打包(跳过测试)
RUN mvn clean package -DskipTests
# 第二阶段:运行阶段(基于轻量级 JRE 镜像)
FROM eclipse-temurin:17-jre-alpine
LABEL maintainer="yww@yww52.com"
# 设置时区
ENV TZ=Asia/Shanghai
RUN apk add --no-cache tzdata && \
ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && \
echo $TZ > /etc/timezone && \
rm -rf /var/cache/apk/*
# 定义 JAR 名称变量(需自定义)
ARG JAR_NAME=app.jar
# 定义 JVM 参数和应用目录
ARG JAR_NAME=app.jar
ENV JAVA_OPTS="-Xms512m -Xmx1536m -Xmn614m -Xss256k -XX:SurvivorRatio=6 -XX:+UseG1GC -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
ENV APP_HOME=/app
# 创建非 root 用户并设置权限
RUN adduser -D appuser && \
mkdir -p $APP_HOME && \
chown -R appuser:appuser $APP_HOME
USER appuser
# 设置工作目录
WORKDIR $APP_HOME
# 从构建阶段复制生成的 JAR 文件
COPY --from=builder /app/target/*.jar ${JAR_NAME}
# 暴露应用端口
EXPOSE 9872
# 启动命令(使用 exec 确保 Java 成为 PID 1)
ENTRYPOINT ["sh", "-c", "exec java $JAVA_OPTS -jar ${JAR_NAME}"]
这个制作镜像的方式会有个问题,就是每次制作镜像都需要去跑maven下载依赖,然后打包,时间花费的很多,而且有时候有些maven依赖在仓库上获取不到,所以这种方式适合一些自建有maven仓库的项目,比如自建有Nexus,早就下载好依赖上传到仓库的项目。 不然的话还是在本地打包后在制作镜像吧,这样也快速,就是会很麻烦,不够自动化。
打包后的Dockerfile
步骤
- 打包好的JAR包
- 准备Dockerfile
- 修改服务打包生成的JAR包文件名
- 制作镜像
FROM eclipse-temurin:17-jre-alpine
LABEL maintainer="yww@yww52.com"
# 定义应用相关环境变量
ENV JAVA_OPTS="-Xms512m -Xmx2048m -Xmn614m -Xss256k -XX:SurvivorRatio=6 -XX:+UseG1GC -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=512m"
ENV APP_HOME=/app
ARG JAR_NAME=app.jar
# 设置时区
ENV TZ=Asia/Shanghai
RUN apk add tzdata \
&& ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
&& echo $TZ > /etc/timezone \
&& apk del tzdata \
&& rm -rf /var/cache/apk/*
# 创建非root用户并设置权限
RUN adduser -D appuser && \
mkdir -p $APP_HOME && \
chown -R appuser:appuser $APP_HOME
USER appuser
# 设置工作目录和应用目录
WORKDIR $APP_HOME
# 复制已打包的 JAR 文件
COPY ${JAR_NAME} $APP_HOME/${JAR_NAME}
# 暴露应用端口
EXPOSE 9872
# 启动命令(使用环境变量配置 JVM 参数)
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar ${JAR_NAME}"]