前言
在使用Docker部署java 项目时,发现容器占用内存很高,导致服务器内存压力大,一个简单的boot项目,占用达到1G多内存,有些容器甚至达到快3G内存,并且发现java -jar 启动的项目,相比docker容器,内存占用要小很多。
解决方式
启动容器,指定jvm 内存参数来降低对服务器内存的消耗
配置前说明环境
笔者的环境:是在pom.xml中,生成的dockerFile ,每次MAVEN install都会生成新的dockerFile,并且会执行docker build (通过dockerFile 文件生成docker镜像)所以笔者是在pom文件中,添加jvm参数的
具体配置
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<skipDocker>${docker}</skipDocker>
<!-- 基础镜像jdk 1.8-->
<baseImage>java</baseImage>
<!-- 制作者提供本人信息 -->
<maintainer>yanjun.liu</maintainer>
<imageName>${project.artifactId}</imageName>
<imageTags>
<imageTag>latest</imageTag>
</imageTags>
<!--切换到/ROOT目录 -->
<workdir>/ROOT</workdir>
<!-- <cmd>["java", "-version"]</cmd>-->
<entryPoint>["java","-Duser.timezone=GMT+8", "-Xms800m", "-Xmx800m","-XX:MaxPermSize=256m","-XX:MaxNewSize=256m","-jar", "${project.build.finalName}.jar","--spring.profiles.active=${active}"]</entryPoint>
<!--是否推送到docker私有仓库-->
<!--<pushImage>true</pushImage>-->
<!-- 指定 Dockerfile 路径 ${project.basedir}:项目根路径下,这是第二种方式需要配置的-->
<!-- <dockerDirectory>${project.basedir}</dockerDirectory>-->
<!--指定远程 docker api地址-->
<!--<dockerHost>http://127.0.0.1:2375</dockerHost>-->
<!-- 这里是复制 jar 包到 docker 容器指定目录配置 -->
<resources>
<resource>
<targetPath>/ROOT</targetPath>
<!--用于指定需要复制的根目录,${project.build.directory}表示target目 录-->
<directory>${project.build.directory}</directory>
<!--用于指定需要复制的文件。${project.build.finalName}.jar指的是打包 后的jar包文件。-->
<include>${project.build.finalName}.jar</include>
</resource>
</resources>
<!-- 以下两行是为了docker push到DockerHub使用的。maven xml中配置harbor的账号密码-->
<!--<serverId>docker-hub</serverId>-->
<!--<registryUrl>${docker.repostory}</registryUrl>-->
</configuration>
<!--maven package 自动构建镜像到服务器 -->
<executions>
<execution>
<id>build-image</id>
<phase>package</phase>
<goals>
<goal>build</goal>
<!--<goal>push</goal>-->
</goals>
</execution>
</executions>
</plugin>
关键配置,注意 格式,指定的jvm 每项参数,都是独立的,用""包起来
"-Xms800m", “-Xmx800m”,"-XX:MaxPermSize=256m","-XX:MaxNewSize=256m"
<entryPoint>["java","-Duser.timezone=GMT+8", "-Xms800m", "-Xmx800m","-XX:MaxPermSize=256m","-XX:MaxNewSize=256m","-jar", "${project.build.finalName}.jar","--spring.profiles.active=${active}"]</entryPoint>
最后Maven Install 会生成dockerFile文件,最后在执行docker build,看看生成的dockerFile中写了些什么
FROM java
MAINTAINER yanjun.liu
WORKDIR /ROOT
ADD /ROOT/feynman-aged-web-0.0.1-SNAPSHOT.jar /ROOT/
ENTRYPOINT ["java","-Duser.timezone=GMT+8","-Xms800m", "-Xmx800m","-jar", "feynman-aged-web-0.0.1-SNAPSHOT.jar","--spring.profiles.active=test"]
解释一下第三个参数,和第四个
第三个:上述pom文件中使用了docker-maven-plugin 插件来生成dockerFile,以及build镜像,那么这里的/ROOT 目录就是指的target/docker/ROOT 目录(Maven install 会在此生成一个jar包)
第四个参数含义:将 target/docker/ROOT/ 目录下的jar包 拷贝 到 docker 容器 内部 根目录 /ROOT/ 下(docker容器内部 / 指的是centos的根目录 /
,毕竟每个docker 容器都是建立在一个小的Linux上的)
第五个就是java JVM 运行时 参数了,当然也可以不用pom插件的方式来生成dockerFIle,dockerFile 直接提前写好,然后shell脚本build运行写好的dockerFile,生成镜像也是一样的
配置好之后,就可以启动容器了,最终优化效果 节省了最少10个G的内存空间,(docker一共跑了12个java项目)之前32个G满满的,现在还有一半的可使用空间