如何在Docker中部署运行jar
作者:justry_deng
基本前提条件
1、系统已安装Docker。
2、系统可上网。
第一大步
docker search justrydeng搜索Docker的JDK镜像
注:这是本人自己组装并上传到Docker官方仓库里的一个jdk8的镜像。如果读者不想用这个镜像,那么也可以使
用其他的jdk镜像。
第二大步
docker pull justrydeng/jdk8拉取(下载)镜像
此时,就可以看到:本地有镜像了:
第三大步
根据要运行的.jar文件,使用Dockerfile + build生成对应的新镜像,并利用该镜像生成容器
假设:我们要运行的jar包是jenkins-0.0.1-SNAPSHOT.jar。
第一小步:创建一个Dockerfile文件并编写,如(这是编写后的样子):
FROM justrydeng/jdk8 MAINTAINER dengshuai<13548417409@163.com> RUN mkdir /var/jarDir && mkdir /var/jarDir/jenkins-docker-test CMD ["nohup","java","-jar","/var/jarDir/jenkins-docker-test/jenkins-0.0.1-SNAPSHOT.jar","&"]
提示:此CMD里为启动jar包的指令,根据不同的需求,编写对应的启动jar包指令即可。
说明一:RUN指令的作用是当利用新的镜像创建容器后,容器马上再创建一个目录,来放置后面会放进去的jar文件,这么做的目的是为了归类方便管理。
追注:实际上,此一步不是必要的,因为一般而言,一个Docker容器就运行一个jar包,所以也可以直接将jar包放置在/下也行。
说明二:CMD指令的作用是:当docker start 启动容器后(注意:是启动,而不是创建),会马上执行该指令。
第二小步:使用docker build指令,生成新的镜像;如这里:
docker build -t justrydeng/jar . -f jarDockerfile
说明一:因为我们创建新的镜像时,不需要什么外部的东西,所以我们指定其上下文“母体”时,最好指定一个空的文件夹或者指定一个几乎不含内容的文件夹。本人这里为了方便,指定的是当前文件夹。
此时,可看见,已经生成了新的镜像:
第三小步:使用docker run指令,配置映射、生成容器,如:
docker run -p 8080:8080 --name jenkins-docker-test -d justrydeng/jar
说明一:-p 8080:8080作用是,将宿主机的端口8080(前面那个),与docker的端口8080(后面那个)映射。
说明二:docker ps 只能查看正在运行着的容器,而docker ps -a可以查看所有的容器。
第四大步
使用docker cp将宿主机中的jar包,拷贝至容器中的对应位置
如:
docker cp jenkins-0.0.1-SNAPSHOT.jar jenkins-docker-test:/var/jarDir/jenkins-docker-test
说明一:将jar包放进容器中的对应的位置(即:Dockerfile的CMD指令对应的位置)。
说明二:只要容器存在(无论容器是否正在运行),就能将东西放进去。
第五大步
docker start启动容器即可
如:
docker start jenkins-docker-test
第六大步
http://宿主机ip:映射后的宿主机端口访问测试
提示,该jar包中的Controller方法有:
访问:http://10.8.109.60:8080/jenkins/test?name=JustryDeng
由此可见:在Docker的容器中部署运行jar包,成功!
拓展一
编写一个通用的运行jar包的镜像(这里只给思路,不给具体示例)
> Dockerfile如:
FROM justrydeng/jdk8 MAINTAINER dengshuai<13548417409@163.com> RUN mkdir /jarAppDir/ CMD ["nohup","java","-jar","/jarAppDir/app.jar","&"]
> 生成镜像docker build -t justrydeng/common-run-jar . -f jarDockerfile
注: -f 可以指定Dockerfile文件的文件名。
> 在后面使用时,我们可以使用同一个镜像来制作对应不同端口(不同服务)的容器
docker run -p 宿主机端口:要映射的容器端口 --name 容器名 -d justrydeng/common-run-jar
> 在更新jar包时,需要在把xxx.jar包复制进容器时,统一重命名为app.jar
docker cp 宿主机jar包 容器名(或容器ID):/jarAppDir/app.jar
说明:此方式的优势在于:每次如果要更新jar包,只需要先将容器stop,然后直接替换容器里面的jar包,最后再将该容器start即可。无需每次都创建新的镜像,创建新的容器。
拓展二
解决Docker部署微服务时,服务之间不能调用的问题(示例)
调用服务出错时的Eureka:
如图所示:
eureka找服务时,会根据服务名【efficiency-taskrelease-service】,找到对应的要访问的地址【6129d46c643e:2050】;一般的,如果我们在微服务中只配了:
的话,那么这个服务注册到eureka中的就可能是【主机名:服务应用名称:服务端口号】。
如果主机名是localhost的话,那可能影响不大;
但是如果主机名是其他的什么的话(如:6129d46c643e),那么就可能造成java.net.UnknownHostException: 6129d46c643e异常,将微服务放在Docker容器中进行服务注册时可能会出问题,微服务会将Docker容器的主机名(而不是宿主机的主机名)注册到eureka上,这时我们可以通过配置,来指定使用宿主机的ip,如:
注:此时,可以不需要指定server.port了,因为我们已经在eureka.instance.instance-id中指明了;但spring.application.name还是需要指明的。
配置完成后,再重启服务,再次查看eureka,可看见:
此时,微服务集成Docker时,各个服务不能调用的问题就得到了解决!
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。