前言
今天修改了boot项目中的一小部分代码,重新部署到服务器上时,由于网络原因,只是上传文件,就花了五分钟。
因为本地打包项目时,把依赖打了进去,实际代码可能也就几百KB,但依赖是不变的。平时网络好的时候也没在意,但网络一有点状况的话,部署一次浪费的时间就有点多了。
但也不能在启动项目的时候才下载依赖,这样更慢。
所以我上网查了些资料,准备把项目依赖抽取出来放在服务器上,本地打包时就只打源码,避免部署一次,要上传几十MB的文件,浪费时间。
但由于服务器用了docker容器,查阅资料就有了很多限制,花了不少时间才成功完成需求。
正文
maven配置
意义
本地打包的时候,maven默认是不打包依赖文件的,这一点与我们的需求一致,但我们需要maven把项目所需依赖单独抽取出来,以便我们存放在服务器中使用。
同时,maven默认依赖路径是项目目录下的lib,需要修改成服务器所存放依赖的位置。
代码
上面有部分注释可参考
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
</plugin>
<!--打包jar-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<!--不打包资源文件-->
<excludes>
<!--<exclude>*.**</exclude>-->
<!--这里不打包yml文件,将配置文件也进行分离处理-->
<exclude>*.yml</exclude>
</excludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<!--MANIFEST.MF 中 Class-Path 加入前缀,主要就是这里,项目启动时,maven会根据这里的路径引入依赖
需要修改成服务器上存放依赖的路径-->
<classpathPrefix>主机存放的依赖路径,例如:
/www/wwwroot/commons/new/lib/</classpathPrefix>
<!--jar包不包含唯一版本标识-->
<useUniqueVersions>false</useUniqueVersions>
<!--指定boot启动类-->
<mainClass>com.___.___Application</mainClass>
</manifest>
<!--<manifestEntries>-->
<!--MANIFEST.MF 中 Class-Path 加入资源文件目录,资源文件也可以像依赖文件一样抽离-->
<!--<Class-Path>./resources/</Class-Path>-->
<!--</manifestEntries>-->
</archive>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</plugin>
<!--拷贝依赖 copy-dependencies-->
<!--也可以执行mvn copy-dependencies 命令打包依赖-->
<!--引入此配置时,会将项目用到的依赖单独打包在target下的lib文件夹里,
如果项目未变更依赖,则可注释-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/lib/
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- 拷贝资源文件 copy-resources
引入此配置时,会将项目配置文件单独打包在target下的resources文件夹里,
如果配置文件未变更,则可注释-->
<!--<plugin>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-resources</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<outputDirectory>${project.build.directory}/resources</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>-->
<!--spring boot repackage,依赖 maven-jar-plugin 打包的jar包 重新打包成 spring boot 的jar包-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!--不将项目依赖打包进jar中-->
<includes>
<include>
<groupId>null</groupId>
<artifactId>null</artifactId>
</include>
</includes>
<layout>ZIP</layout>
<!--使用外部配置文件,jar包里没有资源文件-->
<addResources>true</addResources>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<!--配置jar包特殊标识 配置后,保留原文件,生成新文件 *-run.jar -->
<!--配置jar包特殊标识 不配置,原文件命名为 *.jar.original,生成新文件 *.jar -->
<!--<classifier>run</classifier>-->
</configuration>
</execution>
</executions>
</plugin>
</plugins>
效果
这样配置后,会将项目中的依赖,配置文件,jar包单独的打包在target下的lib,resources,*.jar中。此时的jar包是无依赖的。
我们只需将lib和resources拷贝至服务器中,以后项目仅变更源码时,可直接拷贝源码jar,节省时间,但要注意pom文件中的lib引用路径需要和服务器上的lib文件夹路径一致。
Docker配置
意义
因为docker创建images时,相当于是在服务器上新建一台服务器,这时,images和主机的文件是不互通的,所以在制作竟像时,我们需要修改Dockerfile的内容,将主机上的依赖、配置文件夹挂载到容器中
Dockerfile代码
docker代码不是很熟,就不做详尽解释了。
大概就是add自己的项目文件到容器中,新名字未test_test.jar
设定时区
开放端口
启动项目时用到的配置文件
FROM java:8
VOLUME /tmp
ADD 项目.jar test_test.jar
ENV TZ=Asia/Shanghai
RUN bash -c 'ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && touch test_test.jar'
EXPOSE 8000
EXPOSE 9000
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/test_test.jar",\
"--spring.config.location=/www/wwwroot/commons/new/config/application.yml",\
"--logging.path=/www/wwwroot/commons/new/logs",\
"--loader.path=/www/wwwroot/commons/new/lib"]
效果
使用此文件制作images时,会因为最后一个ENTRYPOINT 配置中,启动配置的设定,loader.path的指向,获取依赖。
启动容器
写了个简单的重新启动容器的sh文件
停止test_test容器,移除容器,移除镜像,重新利用Dockerfile制作镜像.
启动容器时,需要将主机端口指向容器端口,并用-V 关键字,将主机文件夹挂载到容器中
#!/bin/bash
docker stop test_test
docker rm test_test
docker rmi test_test:1.0
docker build -f Dockerfile -t test_test:1.0 .
docker run -p 8000:8000 -p 9000:9000 --name test_test \
-v /www/wwwroot/commons/new/config:/www/wwwroot/commons/new/config \
-v /www/wwwroot/commons/new/logs:/www/wwwroot/commons/new/logs \
-v /www/wwwroot/commons/new/lib:/www/wwwroot/commons/new/lib \
test_test:1.0
Dockerfile和sh文件,及jar包需要放在同一个文件夹下执行
总结
经过以上操作,之后修改代码时,只要再打包一次源码,上传后,运行sh文件后,就可以重新启动容器,同时,如果仅仅是修改boot配置的话,也可以stop容器,然后直接去修改被引用的,主机下的application.yml文件,再start容器即可
借鉴资料
借鉴: maven打包时分离lib依赖
借鉴: docker启动容器时,挂载主机资源