序言

在开发中,经常需要部署SpringBoot服务,所以来简单记录一下我比较常用的一些部署方式。

简单粗暴的脚本

这种方法其实就是直接使用java -jar命令进行启动Jar包,所以得需要系统安装好Java的环境,然后打包好服务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/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环境。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
#!/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

以下是使用方法

1
2
3
4
5
6
7
8
9
10
11
12
# 获取当前服务信息
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包。

步骤:

  1. 拉取Springboot源代码
  2. 如果需要自定义maven配置,请添加maven配置文件在于源码目录,或自己添加
  3. 修改服务打包生成的JAR包文件名
  4. 制作镜像

使用Docker的话,得自行选择需要的JDK镜像和Maven版本镜像,然后修改服务打包出来后的服务名即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# 多阶段构建:第一阶段用于编译 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

步骤

  1. 打包好的JAR包
  2. 准备Dockerfile
  3. 修改服务打包生成的JAR包文件名
  4. 制作镜像
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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}"]