一个安静的周末,
shigen
又睡懒觉了,上次说的拖延症的惩罚来了:早晚各100个健腹轮练习,早上的已经完成了。今天的文章来的有点晚,但是依旧保持质量。
springboot项目生成容器并运行
背景
将springboot项目打包成jar包,上传到服务器并打包成镜像,运行成docker
容器对外提供服务。
这篇文档写于
2023年5月25日
,现在shigen
分享出来,也希望能给开发者提供技术参考。
问题场景
本地的springboot服务编写好代码之后,需要同步到服务器。在服务器上,服务是以容器的形式运行的,所以需要经过以下步骤:
解决方案
- 效率化首选的
shell
脚本,使用rsync
工具上传jar
包到服务器,在服务器使用docker相关的命令进行构建镜像和运行生成容器提供服务
具体实现
upload.sh
本地打包构建服务,生成一个jar包,上传到服务器
代码语言:text复制#!/bin/zsh
# save original file info and show progress
JAR_FILE_NAME='wx-develop-0.0.1-SNAPSHOT.jar'
UPLOAD_CMD="
rsync -e -avp
./dockerfile
./deploy.sh
../../../target/$JAR_FILE_NAME
root@server-ip:/app
"
# maven clean install to ensure the jar is the newest
mvn clean install -f ../../../pom.xml
if [ $? -ne 0 ]; then
echo "maven build failed........."
exit 1
else
echo "now start upload files include $JAR_FILE_NAME"
fi
if [ ! -e ./dockerfile ] || [ ! -e "../../../target/$JAR_FILE_NAME" ]; then
echo "dockerfile or jar JAR_FILE_NAE not exists"
exit 1
fi
eval $UPLOAD_CMD
后期的优化的话,建议将脚本直接放在项目的根路径下,即与
pom.xml
在同一级显示。
Dockerfile
代码语言:shell复制需要注意:
生成的镜像的时区问题 约定项目的工作目录 指定
JVM
的参数 暴露服务的端口号
FROM openjdk:8u302-jdk
# 作者信息
MAINTAINER shigen
# 设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
# 拷贝jar 把可执行jar包复制到基础镜像的根目录下
ADD ./wx-develop.jar /wx-develop.jar
# 设置暴露的端口号
EXPOSE 8088
# 在镜像运行为容器后执行的命令
ENTRYPOINT ["java","-jar","wx-develop.jar","-Xms256m", "-Xmx256m","-XX: UnlockExperimentalVMOptions","-XX: UseCGroupMemoryLimitForHeap"]
deploy.sh
正如我的脚本注释所说:to run jar as a docker container
,即将jar包生成镜像并运行成容器。根据我上文分析的流程进行设计。
#!/bin/bash
# this shell is designed to run jar as a docker container
# define colors
RED='e[1;31m' # 红
GREEN='e[1;32m' # 绿
YELLOW='e[1;33m' # 黄
BLUE='e[1;34m' # 蓝
PINK='e[1;35m' # 粉红
RES='e[0m' # 清除颜色
JAR_FILE_NAME='wx-develop-0.0.1-SNAPSHOT.jar'
DEFAULT_LABEL="wx-develop:`date %Y%m%d`"
CONTAINER_PORT='8088/tcp'
PORT='80'
if [ ! -e ./dockerfile ] || [ ! -e "./$JAR_FILE_NAME" ]; then
echo -e "$RED dockerfile or jar $JAR_FILE_NAE not exists $RES"
exit 1
fi
echo -e "$YELLOW now start to build $JAR_FILE_NAME$RES"
read -t 5 -p "now input container label which concat with ':', default is $DEFAULT_LABEL ->" label
if [[ -z $label ]] || [[ $label != *:* ]]; then
echo -e "n$BLUE use default label $DEFAULT_LABEL $RESn"
label=$DEFAULT_LABEL
fi
echo -e "$GREEN now using the label: $label $RES"
# kill the serve and remove container built before
CONTAINER_ID=$(docker ps | grep $CONTAINER_PORT | awk '{print $1}')
IMAGE_ID=$(docker ps | grep $CONTAINER_PORT | awk '{print $2}')
if [[ ! -z $CONTAINER_ID ]]; then
echo -e "$RED now stop container $CONTAINER_ID $RES"
docker stop $CONTAINER_ID
docker rm $CONTAINER_ID
fi
if [[ ! -z $IMAGE_ID ]]; then
echo -e "$RED now delete image $IMAGE_ID $RES"
docker rmi $IMAGE_ID
fi
eval "docker build -t $label ."
echo -e "$GREEN successfully build $label $RES"
echo -e "$BLUE----------------------now run container $label--------------------------$RES"
docker run -d -p $PORT:$CONTAINER_PORT --name $(echo $label | cut -d : -f 1) $label
echo -e "$GREEN successfully run serve on port: $PORT $RES"
使用方法
- 在本地的
src/main/resources
目录下执行 upload.sh - 在服务器上执行 deploy.sh