如何设置Docker容器 内存盘中Java应用的内存限制

解决Docker Machine中的容器文件不能持久的问题 - 编程随笔 - docker-machine- - ITkeyowrd
解决Docker Machine中的容器文件不能持久的问题 - 编程随笔
hadoop最初主要是针对流式文件的,每个文件在NameNode中都会保存一份文件元数据,并且运行过程中,元数据都是加载到内存中的,有namenode内存的限制;其次mapred
领取地址:
解决Docker Machine中的容器文件不能持久的问题
目前Mac下使用docker的主流方式还是使用Docker machine. Docker machine需要借用Virtual Box虚拟器启动一个Linux宿主机, 才能在上面启动多个Docker容器.
当我们在docker容器中运行服务时,经常会有需要将服务数据持久化的场景.比如运行Elasticsearch集群时, 需要将索引数据持久保存到磁盘.
那具体保存到哪里呢?容器的无状态特性决定了我们不应该将数据保存在容器中, 因为容器一旦重启, 文件数据就会丢失.一般应该使用volume参数,通过挂载外部文件系统到Docker容器中来保存数据.
当我在Mac下使用Docker开发时, 遇到这种场景, 自然就想到了将服务数据保存到Linux宿主机上. 结果很不辛, 使用Docker Machine创建的Linux宿主机的文件系统几乎也是不能持久的, Linux重启后, 之前写入的文件都会丢失.
不过好在使用Docker Machine创建的Linux宿主机上面,自动挂载了Mac上的用户目录到Linux宿主机上. 如下:
Linux: /Users
我们挂载文件系统时, 将应用的数据保存到/Users不久可以了吗?
然而现实还是那么残酷. 当我使用按照这个方式启动Elasticsearch时:
docker run -v &/Users/isaac/work/data&:/usr/share/elasticsearch/data elasticsearch:2.3.3
却得到了以下错误:
Exception in thread &main& java.lang.IllegalStateException: Unable to access 'path.data' (/usr/share/elasticsearch/data/elasticsearch)
Likely root cause: java.nio.file.AccessDeniedException: /usr/share/elasticsearch/data/elasticsearch
at sun.nio.fs.UnixException.translateToIOException(UnixException.java:84)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
at sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:384)
at java.nio.file.Files.createDirectory(Files.java:674)
at java.nio.file.Files.createAndCheckIsDirectory(Files.java:781)
at java.nio.file.Files.createDirectories(Files.java:767)
at org.elasticsearch.bootstrap.Security.ensureDirectoryExists(Security.java:337)
at org.elasticsearch.bootstrap.Security.addPath(Security.java:314)
at org.elasticsearch.bootstrap.Security.addFilePermissions(Security.java:259)
at org.elasticsearch.bootstrap.Security.createPermissions(Security.java:212)
at org.elasticsearch.bootstrap.Security.configure(Security.java:118)
at org.elasticsearch.bootstrap.Bootstrap.setupSecurity(Bootstrap.java:196)
at org.elasticsearch.bootstrap.Bootstrap.setup(Bootstrap.java:167)
at org.elasticsearch.bootstrap.Bootstrap.init(Bootstrap.java:270)
at org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:35)
经过分析, 文件操作失败是因为用户权限的问题.查看Linux宿主机的用户信息:
docker-machine ssh default
cat /etc/passwd
得到以下内容:
root:x:0:0:root:/root:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
nobody:x::nobody:/nonexistent:/bin/false
tc:x:1001:50:Linux User,,,:/home/tc:/bin/sh
docker:x:1000:50:Linux User,,,:/home/docker:/bin/sh
所以通过指定启动Docker容器的用户, 可以解决此问题:
docker run -u 1000 -v &/Users/isaac/work/data&:/usr/share/elasticsearch/data elasticsearch:2.3.3
其中:-u 1000 代表使用id为1000的docker用户来启动应用
在docker-compose.yml中指定启动用户为docker用户:
elasticsearch1:
image: elasticsearch:2.3.3
command: &elasticsearch -Des.cluster.name=elasticsearch -Des.discovery.zen.ping.unicast.hosts=elasticsearch_master&
- elasticsearch_master
- /Users/isaac/work/data:/usr/share/elasticsearch/data
user: &1000&
ok,启动服务后, 数据终于持久不丢失了.
解决Docker Machine中的容器文件不能持久的问题 目前Mac下使用docker的主流方式还是使用Docker machine. Docker machine需要借用Virtual Box虚拟器启动一个Linux宿主机, 才能在上面启动多个Dock
相关阅读排行
相关内容推荐
请激活账号
为了能正常使用评论、编辑功能及以后陆续为用户提供的其他产品,请激活账号。
您的注册邮箱:
如果您没有收到激活邮件,请注意检查垃圾箱。如何设置Docker容器中Java应用的内存限制
时间: 23:24:07
&&&& 阅读:244
&&&& 评论:
&&&& 收藏:0
标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&& &如果使用官方的镜像,或者基于Java镜像构建的Docker镜像,都可以通过传递&JAVA_OPTS&环境变量来轻松地设置JVM的内存参数。比如,对于官方&镜像,我们可以执行下面命令来启动一个最大内存为512M的tomcat实例
docker run --rm -e JAVA_OPTS=‘-Xmx512m‘ tomcat:8
在日志中,我们可以清楚地发现设置已经生效 “Command line argument: -Xmx512m”
02-Apr-:26.970 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server version:
Apache Tomcat/8.0.32
02-Apr-:26.974 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server built:
Feb 2 :53 UTC
02-Apr-:26.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Server number:
02-Apr-:26.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Name:
02-Apr-:26.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log OS Version:
4.1.19-boot2docker
02-Apr-:26.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Architecture:
02-Apr-:26.975 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Java Home:
/usr/lib/jvm/java-7-openjdk-amd64/jre
02-Apr-:26.976 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Version:
1.7.0_95-b00
02-Apr-:26.976 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log JVM Vendor:
Oracle Corporation
02-Apr-:26.977 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_BASE:
/usr/local/tomcat
02-Apr-:26.977 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log CATALINA_HOME:
/usr/local/tomcat
02-Apr-:26.978 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=/usr/local/tomcat/conf/logging.properties
02-Apr-:26.978 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
02-Apr-:26.978 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Xmx512m
然而在Docker集群上部署运行Java容器应用的时候,仅仅对JVM的heap参数设置是不够的,我们还需要对Docker容器的内存资源进行限制:1. 限制容器使用的内存的最大量,防止对系统或其他应用造成伤害2. 能够将Docker容器调度到拥有足够空余的内存的节点,从而保证应用的所需运行资源
关于容器的资源分配约束,Docker提供了相应的
对内存而言,最基本的就是通过&-m参数来约束容器使用内存的大小
-m, --memory=""
Memory limit (format: &number&[&unit&]). Number is a positive integer. Unit can be one of b, k, m, or g. Minimum is 4M.
那么问题就来了,为了正确设置Docker容器内存的大小,难道我们需要同时传递容器的内存限制和JAVA_OPTS环境变量吗? 如下所示:
docker run --rm -m 512m -e JAVA_OPTS=‘-Xmx512m‘ tomcat:8
这个方法有两个问题1. 需要管理员保证容器内存和JVM内存设置匹配,否则可能引发错误2. 当对容器内存限制调整时,环境变量也需要重新设定,这就需要重建一个新的容器
是否有一个方法,可以让容器内部的JVM自动适配容器的内存限制?这样可以采用更加统一的方法来进行资源管理,简化配置工作。
大家知道Docker是通过CGroup来实现资源约束的,自从1.7版本之后,Docker把容器的local cgroups以只读方式挂载到容器内部的文件系统上,这样我们就可以在容器内部,通过cgroups信息来获取系统对当前容器的资源限制了。
我创建了一个示例镜像&registry.aliyuncs.com/denverdino/tomcat:8-autoheap,其源代码可以从&获得。它基于Docker官方Tomcat镜像创建,它的启动脚本会检查CGroup中内存限置,并计算JVM最大Heap size来传递给Tomcat。其代码如下
#!/bin/bash
limit_in_bytes=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes)
# If not default limit_in_bytes in cgroup
if [ "$limit_in_bytes" -ne "4771712" ]
limit_in_megabytes=$(expr $limit_in_bytes \/ 1048576)
heap_size=$(expr $limit_in_megabytes - $RESERVED_MEGABYTES)
export JAVA_OPTS="-Xmx${heap_size}m $JAVA_OPTS"
echo JAVA_OPTS=$JAVA_OPTS
exec catalina.sh run
为了监控,故障排查等场景,我们预留了部分内存(缺省64M),其余容器内存我们都分配给JVM的堆。
这里没有对边界情况做进一步处理。在生产系统中需要根据情况做相应的设定,比如最大的堆大小等等。
现在我们启动一个tomcat运行在512兆的容器中
docker run -d --name test -m 512m registry.aliyuncs.com/denverdino/tomcat:8-autoheap
通过下列命令,从日志中我们可以检测到相应的JVM参数已经被设置成 448MB (512-64)
docker logs test
02-Apr-:09.870 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Xmx448m
我们也可以方便的调整Java应用的内存.
Docker 1.10提供了对容器资源限制的动态修改能力。但是由于JVM无法感知容器资源修改,我们依然需要重启tomcat来变更JVM的内存设置,例如,我们可以通过下面命令把容器内存限制调整到1GB
docker update -m 1024m test
docker restart test
再次检查日志,相应的JVM Heap Size最大值已被设置为960MB
docker logs test
02-Apr-:07.644 INFO [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Xmx960m
&标签:&&&&&&&&&&&&&&&&&&&&&&&&&&&原文地址:http://www.cnblogs.com/ilinuxer/p/6648681.html
&&国之画&&&& &&&&chrome插件
版权所有 京ICP备号-2
迷上了代码!在docker中部署tomcat并且部署java应用程序的步骤详解_docker
作者:用户
本文讲的是在docker中部署tomcat并且部署java应用程序的步骤详解_docker,
先给大家简单说下Docker的概念
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接
先给大家简单说下Docker的概念
Docker 是一个开源的应用容器引擎,让者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
1、先说如何在docker中部署tomcat
第一步:root用户登录在系统根目录下创建文件夹tomcat7,命令如:mkdir tomcat7,并且切换到该目录下:cd tomcat7;
第二步:创建Dockerfile,命令如:touch Dockerfile;
第三步:编写Dockerfile,命令如:vim Dockerfile,完成以下命令编写:
FROM ubuntu:14.04
MAINTAINER zhaichong &&
ENV REFRESHED_AT
RUN apt-get -yqq update
RUN apt-get -yqq install tomcat7 default-jdk
ENV CATALINA_HOME /usr/share/tomcat7
ENV CATALINA_BASE /var/lib/tomcat7
ENV CATALINA_PID /var/run/tomcat7.pid
ENV CATALINA_SH /usr/share/tomcat7/bin/catalina.sh
ENV CATALINA_TMPDIR /tmp/tomcat7-tomcat7-tmp
RUN mkdir -p $CATALINA_TMPDIR
VOLUME ["/var/lib/tomcat7/webapps/"]
ENTRYPOINT ["/usr/share/tomcat7/bin/catalina.sh", "run" ]
说明:这里的EXPOSE要把程序中需要使用到的端口都要暴露出去。根据环境变量CATALINA_BASE可以知道VOLUME指定的目录就是tomcat部署war包的目录。
第四步:生成镜像,命令如:docker build -t test/test_app . (注意这里有个英文的句号);注意,在这个过程中docker需要下载安装的jdk和tomcat程序所以比较忙,可以通过命令:docker image查看下,返回的数据中第一行有个REPOSITORY和TAG都是&none&的数据行,其中的VIRTUAL_SIZE是阶段性变大的,说明是在下载。
第五步:运行镜像生成容器,命令如:docker run --name test_app -d -p
镜像id,如果不知道镜像id是多少就使用命令:docker images查看下,注意这里把EXPOSE出来的端口和宿主主机的端口绑定起来了,以后就可以使用宿主主机的IP地址和这个端口来访问docker容器中的tomcat以及其中的应用程序了。
第六步:测试:在浏览器地址栏敲:http://宿主主机ip:8080/,好了成功了。
可以使用命令:docker port 容器id 8080,这个命令查看容器的8080端口和宿主主机端口之间的映射关系,而已看出来现在容器的8080端口映射的是宿主主机的8080端口。
2、再说如何部署我们的应用程序到docker容器的tomcat里?
大家知道tomcat在容器中,如果要像在宿主主机上那样部署tomcat应用程序肯定是不行的。那么采用什么办法呢?
第一步:上一个问题中我们已经知道war包是部署在容器的位置是:/var/lib/tomcat7/webapps/,那么这个位置到底在什么地方?使用命令:docker inspect -f "{{.Volumes}}" 容器id,如果不知道容器id,则可以通过:docker ps的方式查看到所有运行的容器,也可以通过docker ps -a的方式查看所有容器,包括运行的和不运行的。
会得出以下的结果:
map[/var/lib/tomcat7/webapps:/var/lib/docker/vfs/dir/28d6ddd8aeeff402a843bd57d3b21fcd80eac7df02],
在这个map的中括号里,冒号前边的是容器中的目录,冒号后边的对应的宿主主机中的目录,所以我们只需要把我们的war包拷贝到这个地方然后重启tomcat即可。
这里要注意,由于我们上边写的Dockerfile中默认容器启动时是会启动tomcat的,所以这里只需要重启容器就能让tomcat把我们的容器加载上,命令如:
docker restart 容器id
3、如果要看成tomcat的日志呢?比如查看启动时的日志,则可以使用命令:
docker logs 容器id,如果要持续观察日志,则是:docker logs -f 容器id,这个时候日志是从头开时读的,如果日志很长会刷屏很久,如果只打算看最新的日志可以采用以下的方式:docker logs --tail 0 -f 容器id
注意,有的时候我们想在执行docker run命令的时候才指定映射的Volumes,则可以使用如下命令:
docker run --name gboat2_ca -d -p
--link db001:db_ca -v /home/webapp/ca:/var/lib/tomcat7/webapps/ 64de1445c34c
这里一定要注意的是最后的英文冒号前边是宿主主机的文件夹路径,冒号后边是容器中的路径。
以上所述是小编给大家介绍的在docker中部署tomcat并且部署java应用程序的步骤详解,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对云栖社区网站的支持!
以上是云栖社区小编为您精心准备的的内容,在云栖社区的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索docker
部署tomcat
docker部署java应用
docker 部署tomcat、docker中部署tomcat、docker web部署tomcat、docker部署多个tomcat、在docker上部署tomcat,以便于您获取更多的相关知识。
弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率
40+云计算产品,6个月免费体验
稳定可靠、可弹性伸缩的在线数据库服务,全球最受欢迎的开源数据库之一
云服务器9.9元/月,大学必备
云栖社区(yq.aliyun.com)为您免费提供相关信息,包括
,所有相关内容均不代表云栖社区的意见!你的浏览器禁用了JavaScript, 请开启后刷新浏览器获得更好的体验!
【编者的话】 如果你尝试在容器中运行Java程序,或者专注于Docker,你可能会遇到一些关于JVM和堆大小的问题。本篇文章将介绍如何解决这些问题。
很多开发者会(或者应该)知道,当我们为运行在Linux容器(Docker、rkt、runC、lxcfs等)中的Java程序去设置JVM的GC、堆大小和运行时编译器的参数时并没有得到预想的效果。当我们通过“java -jar mypplication-fat.jar”的方式而不设置任何参数来运行一个Java应用时,JVM会根据自身的许多参数进行调整,以便在执行环境中获得最优的性能。
本篇博客将通过简单的方式向开发人员展示在将Java应用运行在Linux容器内时需要了解的内容。
我们倾向于认为容器可以像虚拟机一样可以完整的定义虚拟机的CPU个数和虚拟机的内存。容器更像是一个进程级别的资源(CPU、内存、文件系统、网络等)隔离。这种隔离是依赖于Linux内核中提供的一个的功能。
然而,一些可以从运行时环境中收集信息的应用程序在cgroups功能出现之前已经存在。在容器中执行命令 ‘top‘、‘free‘、‘ps’,也包括没有经过优化的JVM是一个会受到高限制的Linux进程。让我们来验证一下。
问题为了展示遇到的问题,我使用命令“docker-machine create -d virtualbox –virtualbox-memory ‘1024’ docker1024”在虚拟机中创建了一个具有1GB内存的Docker守护进程,接下来在3个Linux容器中执行命令“free -h”,使其只有100MB的内存和Swap。结果显示所有的容器总内存是995MB。
即使是在 Kubernetes/OpenShift集群中,结果也是类似的。我在一个内存是15G的集群中也执行了命令使得Kubernetes Pod有511MB的内存限制(命令:“kubectl run mycentos –image=centos -it –limits=’memory=512Mi’”),总内存显示为14GB。
想要知道为什么是这样的结果,可以去阅读此篇博客文章 “”
我们需要知道Docker参数(-m、–memory和–memory-swap)和Kubernetes参数(–limits)会让Linux内核在一个进程的内存超出限制时将其Kill掉,但是JVM根本不清楚这个限制的存在,当超过这个限制时,不好的事情发生了!
为了模拟当一个进程超出内存限制时会被杀死的场景,我们可以通过命令“docker run -it –name mywildfly -m=50m jboss/wildfly”在一个容器中运行WildFly Application Server并且为其限制内存大小为50MB。在这个容器运行期间,我们可以执行命令“docker stats”来查看容器的限制。
但是过了几秒之后,容器Wildfly将会被中断并且输出信息:* * * JBossAS process (55) received KILL signal * * *
通过命令 “docker inspect mywildfly -f ‘{{json .State}}'”可以查看容器被杀死的原因是发生了OOM(内存不足)。容器中的“state”被记录为OOMKilled=true 。
这将怎样影响Java应用在Docker宿主机中创建一个具有1GB内存的虚拟机(在之前使用命令已经创建完毕 “docker-machine create -d virtualbox
–virtualbox-memory ‘1024’ docker1024”) ,并且限制一个容器的内存为150M,看起来已经足够运行这个在 Dockerfile中设置过参数-XX: PrintFlagsFinal 和 -XX: PrintGCDetails的Spring Boot application了。这些参数使得我们可以读取JVM的初始化参数并且获得 Garbage Collection(GC)的运行详细情况。
尝试一下:
$&docker&run&-it&--rm&--name&mycontainer150&-p&&-m&150M&rafabene/java-container:openjdk
我也提供了一个访问接口“/api/memory/”来使用String对象加载JVM内存,模拟大量的消耗内存,可以调用试试:
$&curl&http://`docker-machine&ip&docker/api/memory
这个接口将会返回下面的信息 “Allocated more than 80% (219.8 MiB) of the max allowed JVM memory size (241.7 MiB)”。
在这里我们至少有2个问题:
为什么JVM会允许241.7MiB的最大内容?如果容器已经限制了内存为150MB,为什么允许Java分配内存到220MB?
首先,我们应该重新了解在中所描述的 “maximum heap size”的定义,它将会使用1/4的物理内存。JVM并不知道它运行在一个容器中,所以它将被允许使用260MB的最大堆大小。通过添加容器初始化时的参数-XX: PrintFlagsFinal,我们可以检查这个参数的值。
$&docker&logs&mycontainer150|grep&-i&MaxHeapSize
uintx&MaxHeapSize&:=&&{product}&
其次,我们应该理解当在docker命令行中设置了 “-m 150M”参数时,Docker守护进程会限制RAM为150M并且Swap为150M。从结果上看,一个进程可以分配300M的内存,解释了为什么我们的进程没有收到任何从Kernel中发出的退出信号。
更多的关于Docker命令中内存限制 (–memory)和Swap (–memory-swap)的差别可以参考。
更多的内存是解决方案吗?开发者如果不理解问题可能会认为运行环境中没有为JVM提供足够的内存。通常的解决对策就是为运行环境提供更多的内存,但是实际上,这是一个错误的认识。
假如我们将Docker Machine的内存从1GB提高到8GB(使用命令 “docker-machine create -d virtualbox –virtualbox-memory ‘8192’ docker8192”),并且创建的容器从150M到800M:
$&docker&run&-it&--name&mycontainer&-p&&-m&800M&rafabene/java-container:openjdk
此时使用命令 “curl 53X:8080/api/memory” 还不能返回结果,因为在一个拥有8GB内存的JVM环境中经过计算的MaxHeapSize大小是(~ 2GB)。可以使用命令“docker logs mycontainer|grep -i MaxHeapSize”查看。
应用将会尝试分配超过1.6GB的内存,当超过了容器的限制(800MB的RAM
800MB的Swap),进程将会被Kill掉。
很明显当在容器中运行程序时,通过增加内存和设置JVM的参数不是一个好的方式。当在一个容器中运行Java应用时,我们应该基于应用的需要和容器的限制来设置最大堆大小(参数:-Xmx)。
解决方案是什么?在Dockerfile中稍作修改,为JVM指定扩展的环境变量。修改内容如下:
CMD&java&-XX:+PrintFlagsFinal&-XX:+PrintGCDetails&$JAVA_OPTIONS&-jar&java-container.jar
现在我们可以使用JAVA_OPTIONS的环境变量来设置JVM Heap的大小。300MB看起来对应用足够了。稍后你可以查看日志,看到Heap的值是
bytes(300MBi)。
Docker下,可以使用“-e”的参数来设置环境变量进行切换。
$&docker&run&-d&--name&mycontainer8g&-p&&-m&800M&-e&JAVA_OPTIONS='-Xmx300m'&rafabene/java-container:openjdk-env
$&docker&logs&mycontainer8g|grep&-i&MaxHeapSize
uintx&&&&MaxHeapSize&:=&&&&&&&&{product}&
在Kubernetes中,可以使用“–env=[key=value]”来设置环境变量进行切换:
$&kubectl&run&mycontainer&--image=rafabene/java-container:openjdk-env&--limits='memory=800Mi'&--env=&JAVA_OPTIONS='-Xmx300m'&
$&kubectl&get&pods
NAME&&&&&&&&&&&&&&&&&&&&&&&&&&READY&&STATUS&&&&RESTARTS&AGE
mycontainer--b1u0o&&1/1&&&&Running&&&0&&&&&&&&6s
$&kubectl&logs&mycontainer--b1u0o|grep&MaxHeapSize
uintx&&&&&MaxHeapSize&:=&&&&&&{product}&
还能再改进吗?有什么办法可以根据容器的限制来自动计算Heap的值?
事实上如果你的基础Docker镜像使用的是由Fabric8提供的,那么就可以实现。镜像fabric8/java-jboss-openjdk8-jdk使用了脚本来计算容器的内存限制,并且使用50%的内存作为上限。也就是有50%的内存可以写入。你也可以使用这个镜像来开/关调试、诊断或者其他更多的事情。让我们看一下一个Spring Boot应用的 Dockerfile :
FROM&fabric8/java-jboss-openjdk8-jdk:1.2.3
ENV&JAVA_APP_JAR&java-container.jar
ENV&AB_OFF&true
EXPOSE&8080
ADD&target/$JAVA_APP_JAR&/deployments/
就这样!现在,不管容器的内存限制如何,我们的Java应用将在容器中自动的调节Heap大小,而不是再根据宿主机来设置。
总结到目前为止,Java JVM还不能意识到其是运行在一个容器中 — 某些资源在内存和CPU的使用上会受到限制。因此,你不能让JVM自己来设置其认为的最优的最大Heap值。
一个解决对策是使用Fabric8作为基础镜像,它可以意识到应用程序运行在一个受限制的容器中,并且在你没有做任何事情的情况下,可以自动的调整最大Heap的值。
在JDK9中已经开始进行尝试在容器(i.e. Docker)环境中为JVM提供cgroup功能的内存限制。相关信息可以查看:
原文链接:(翻译:李强)
要回复文章请先或
IT老兵,互联网新兵!DevOps的铁粉~在Docker容器中运行Spring Boot应用-docker,springboot,java 相关文章-天码营
在Docker容器中运行Spring Boot应用
Spring Boot简化了Spring应用的开发过程,遵循约定优先配置的原则提供了各类开箱即用(out-of-the-box)的框架配置。另一方面,Spring Boot还具备将代码直接构建为可执行jar包的能力,这个jar包是一个可以独立运行的部署单元。基于以上特性,现在普遍认为提供了一种快速构造的能力。Docker与Spring Boot是一种Linux容器的实现,Linux容器是基于进程的轻量级资源隔离技术,每一个容器对应操作系统中的一个进程,但是它又会有自己的网络空间、文件系统、PID等。Docker除了实现Linux容器,还使得容器具有“社会化”的功能,用户可以将容器镜像发布在与其他开发者共享、协作。安装Docker的教程请参考Spring Boot应用通常被构建为一个可单独执行的jar包,通过java -jar ...运行,但是框架本身并没有提供以服务形式运行在后台的方法,通常需要借助Systemd, Supervisord等进程管理工具来实现。另一方面,虽然应用运行环境非常的简单,但是将他们容器化为Docker容器镜像并运行,对于自动化部署、运维都是非常有利的。本文将以一个最简单的Spring Boot开发的Web应用为例,讲解如何将其容器化运行。本文的重点是构建Docker镜像、运行Docker容器,关于Spring Boot开发Web应用可以参考构建并Spring Boot应用在应用代码编写完成后,可以直接将其打包并运行:Maven: mvn package && java -jar target/spring-boot-docker-0.1.0.jarGradle: gradle build && java -jar build/libs/gs-spring-boot-docker-0.1.0.jar在浏览器地址栏种输入[]()可以访问应用Dockerfile构建镜像Docker提供了格式的文件来构建应用镜像,现在开始创建一个Spring Boot应用的Dockerfile:FROM java:8
VOLUME /tmp
ADD spring-boot-docker-0.1.0.jar app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
java:8是指Docker Hub上官方提供的java镜像,版本号是8也就是jdk1.8,有了这个基础镜像后,Dockerfile可以通过FROM指令直接获取它的状态——也就是在容器中java是已经安装的,接下来通过自定义的命令来运行Spring Boot应用:VOLUME /tmp创建/tmp目录并持久化到Docker数据文件夹,因为Spring Boot使用的内嵌Tomcat容器默认使用/tmp作为工作目录ADD spring-boot-docker-0.1.0.jar app.jar 将应用jar包复制到/app.jarENTRYPOINT表示容器运行后默认执行的命令Dockerfile非常的简单,编辑完成后运行docker构建镜像命令:docker build -t tmy/spring-boot-app .
然后运行Docker容器:docker run -d -p
--name sample-app tmy/spring-boot-app
其中-d表示后台运行容器,这也就自然地解决的Spring Boot不支持后台运行应用程序的问题。-p 表示将容器内部的8080端口映射到宿主机器的8080端口,这样就可以通过宿主机器直接访问应用。--name sample-app给容器取一个容易记住的名字方便日后管理。使用Maven/Gradle创建Docker镜像为了方便Java开发者创建Docker镜像,Maven/Gradle都提供了响应的插件。Maven&properties&
&docker.image.prefix&springio&/docker.image.prefix&
&/properties&
&groupId&com.spotify&/groupId&
&artifactId&docker-maven-plugin&/artifactId&
&version&0.2.3&/version&
&configuration&
&imageName&${docker.image.prefix}/${project.artifactId}&/imageName&
&dockerDirectory&src/main/docker&/dockerDirectory&
&resources&
&resource&
&targetPath&/&/targetPath&
&directory&${project.build.directory}&/directory&
&include&${project.build.finalName}.jar&/include&
&/resource&
&/resources&
&/configuration&
&/plugins&
上述pom.xml包含了docker-maven-plugin的配置:imageName指定了镜像的名字dockerDirectory指定Dockerfile的位置resources是指那些需要和Dockerfile放在一起,在构建镜像时使用的文件,一般应用jar包需要纳入经过以上配置后,运行下列命令可以在本地Docker中创建一个镜像:$ mvn package docker:build
GradleGradle同样也有支持Docker的插件:buildscript {
dependencies {
classpath('se.transmode.gradle:gradle-docker:1.2')
group = 'springio'
apply plugin: 'docker'
task buildDocker(type: Docker, dependsOn: build) {
push = true
applicationName = jar.baseName
dockerfile = file('src/main/docker/Dockerfile')
into stageDir
上述配置和Maven基本类似,执行以下命令构建镜像:$ gradle build buildDocker
本文由创作,转载需署名作者且注明文章出处
要获取本文的参考代码,请访问:
留个记号,(*^__^*) 嘻嘻……
&不知道你用systemd的目的是什么?如果只是想以daemon的形式运行Spring Boot应用,那么docker本身也可以认为提供了这样的功能——docker容器中运行的进程不能够以后台服务的形式运行。
我也是想只运行一个进程,但是我想在dockerfile中用systemctl启动而不是java -jar。
&我个人认为一个docker容器只运行一个进程是一种比较好的实践,所以一般情况下无需使用systemd这样的进程管理器。如果一定要使用可以参考:另外推荐一个轻量级的python实现的进程管理工具Supervisord
容器中怎么用systemd管理服务?
Spring MVC实战入门训练,以一个博客系统为例,将Spring MVC的核心知识融入到实战当中...
本课程中将介绍目前深度学习领域中最流行的诸多模型和算法。通过对这些算法的学习,你将能够对深度学习领域...
爬虫是一个非常适合Java实战练手的项目,而且具有实用性。这个训练中,我们将练习如何爬取、解析网易云...

我要回帖

更多关于 内存映射 速度 的文章

 

随机推荐