自己有一个简单的springboot web后端项目,每次部署的时候都是上传到服务器,然后nohup java -jar 运行打包的jar包。这样每次运行都要输命令,关闭时还得找到进程id手动kill掉,觉得太烦了,干脆做成docker镜像。
项目有对宿主机文件系统、数据库的访问,但这里不打算把mysql数据库也打包了,就只是访问主机上已经运行的。
编写Dockerfile
首先将需要的文件放在一个文件夹下。这里就只需要一个项目的jar包就行了,但如果想把其他用到的软件也打包进镜像,最好也要放进来。
在文件夹下创建Dockerfile文件,开始编写docker容器构建脚本。
FROM openjdk:15 MAINTAINER lpjworkroom ADD test.jar app.jar EXPOSE 8080 VOLUME /file #声明这是匿名卷,docker run时-v将主机目录绑定到此匿名卷 ENTRYPOINT java -jar app.jar
FROM openjdk:15,表示本镜像的基础镜像是openjdk,版本是15,毕竟要用java命令运行jar包的。docker会从dockerhub拉取对应的镜像,服务器不需要有。
MAINTAINER lpjworkroom,表示镜像的编写者。
ADD test.jar app.jar,表示将test.jar,也就是项目jar包,拷贝进镜像,并命名为app.jar。如果不拷贝,镜像就没jar包可运行了。
EXPOSE 8080,表示镜像将对外暴露8080端口,也就是编写项目时的运行端口。
VOLUME /file,表示将镜像的/file文件夹声明为匿名卷。这样做是因为,项目会读写文件系统的/file文件夹,如果不声明,那么项目运行后只会对镜像内的虚拟目录/file读写,而不会对主机的目录读写,等关闭容器后,写的内容就没了。所以,声明匿名卷是为了将写操作持久化。仅仅在dockerfile里声明还不够,在运行容器时还需要设置匿名卷对应的主机目录,这点我们下面会谈到。
ENTRYPOINT java -jar app.jar,表示容器运行后执行的命令。这里就只需要运行jar包就行了。
构建镜像
编写了Dockerfile,就可以构建镜像了。
docker build -t test_app:0.1 .
test_app是镜像的名字,-t代表给镜像打的标签,后面的:0.1意思就是这个镜像版本是0.1。如果不打标签,镜像的标签会自动设为latest。
最后的一个'.'代表Dockerfile所在位置,因为就在当前目录下,所以直接是一个'.'就行了。
docker会自动拉取openjdk。一会出现“Successfully built 7717b14bfe0a”,说明构建成功。
运行容器
接下来运行容器。
docker run -d --name test_app -v /home/file:/file --net=host -p 8080:8080 test_app:0.1
-d指在后台运行。
--name为容器起名。
-v指定容器匿名卷挂载的目录。这里/home/file:/file代表将主机的/home/file对应到容器的/file,也就是说,容器对/file目录的读写也就是对主机的/home/file读写。
--net=host指定容器的网络模式。host是最简单的模式,容器和主机共用一个网络,会互相占用端口。由于项目简单,我就没有再研究其他模式了,想研究的话可以看看官网教程。
-p 8080:8080指定端口映射。这里简单的将主机的8080端口映射到容器的8080端口。如果想要多个web程序运行在同一主机,不需要改代码里的运行端口,直接将主机的不同端口映射到容器的8080即可。
最后是容器使用的镜像,也就是刚刚构建好的test_app:0.1。
就这样,容器成功运行了。只要docker start/stop就能控制程序运行,部署新版本时,也只要将jar包再上传到目录下,重新构建即可。