前言

前面几节我们学习了 mongodb 的一些基本操作,上一节我们又用 springboot 整合 mongodb 完成了一个小 demo,这节我们将从基础开始把这个 springboot 项目部署到 docker 环境。

基础镜像构建

我们都知道java项目需要依赖 jre 环境,如果你的镜像直接添加一个jdk进去,这也是完全可以的,但是有一个问题就是,这样可能会使得你的镜像非常大,但是这其实是完全没必要的。

了解过的人都知道,docker 镜像是分层构建的,怎么描述呢?通常一个 docker 镜像可以分为 系统层、环境层、应用层。比如这里的系统层指的就是我们依赖的操作系统,我这里是centos7,环境层指的是运行java依赖的jre环境,应用层就值得是我们自己的应用(jar包)文件。

为了使我们的镜像可以比较小,各层都采用基础镜像完成构建。当然精简的镜像好处就是体积小,但也有缺点,比如我们常用的一些 linux 工具没有安装,使得我们在进入到容器内部排查问题就有些不方便了。

系统层

这里我们系统层采用 alpine 作为基础镜像,alpine 是一个轻量级的linux系统,镜像大小5M左右。我们直接使用 alpine 作为基础层镜像,这里不用特殊处理。

环境层

环境层这里采用 jdk8 来构建,我们对其做适当精简。
首先下载 jdk8
下载完成以后解压文件并删除不分不需要的文件

mkdir -p /usr/local/shell/docker
tar -zxvf jdk-8u333-linux-x64.tar.gz
cd jdk1.8.0_333/
mv jre/ ..
cd jre/

rm -rf ./lib/plugin.jar \
./lib/ext/jfxrt.jar \
./bin/javaws \
./lib/javaws.jar \
./lib/desktop \
./plugin \
./lib/deploy* \
./lib/*javafx* \
./lib/*jfx* \
./lib/amd64/libdecora_sse.so \
./lib/amd64/libprism_*.so \
./lib/amd64/libfxplugins.so \
./lib/amd64/libglass.so \
./lib/amd64/libgstreamer-lite.so \
./lib/amd64/libjavafx*.so \
./lib/amd64/libjfx*.so

服务镜像构建

cd /usr/local/shell/docker
cat >> Dockerfile <<EOF
# 以alpine为基础镜像
FROM docker.io/jeanblanchard/alpine-glibc

# 把jre添加进去
ADD jre /usr/local/

# 设置环境变量
ENV JAVA_HOME /usr/local/jre
ENV PATH ${PATH}:${JAVA_HOME}/bin
CMD ["java", "-version"]
EOF

# 构建镜像
docker build -t jre-env/jre:v1 .

在这里插入图片描述
基础镜像构建完成,通过 docker iamges 查看,我们新构建的镜像大小为 137M。

应用层

docker 镜像的构建都是基于 Dockerfile 描述文件,
项目添加 Dockerfile。

# 使用我们上面构建的环境镜像作为基础镜像
FROM jre-env/jre:v1

# 维护者信息
MAINTAINER hxj

# 设置字符编码
ENV LANG C.UTF-8

# 设置alpine时区
ENV TIMEZONE Asia/Shanghai

# 添加应用 这里相当于把应用添加进来并重命名
ADD spring-mongo-1.0.jar spring-mongo.jar

# 启动应用
ENTRYPOINT ["java -jar spring-mongo.jar"]

由于我本地没有安装docker,把 Dockerfile 文件和 spring-mongo-1.0.jar,文件拷贝到 images 下 构建应用镜像。

docker build -t spring-mongo .

在这里插入图片描述
查看镜像,发现我们构建的镜像已经在我们本地镜像仓库了。

docker images

在这里插入图片描述

部署

镜像构建完成,那我们试试把应用跑起来:

docker run -itd -p 80:8080 spring-mongo

# 查看运行中的镜像
docker ps

在这里插入图片描述
不幸的是,这里面并没有我们刚刚启动的 spring-mongo,我开始发现,事情并没有我想象的name简单。

# 查看容器日志
docker logs bf3b671ed5f97d95efc16bd57caf0db10b9d673f2bc6ac7b08ed77f497f2df6f(容器id)

在这里插入图片描述
这是什么鬼,完全不认识好吗!百度了下,musl libc 和 glibc 之间的差异,不明觉厉的样子,解决起来好像还挺麻烦,既然这样,干脆换个基础镜像好了。于是在 dockerhup 找到了这个镜像 frolvlad/alpine-glibc,那我就重新构建,只需要修改 Dockerfile 中的基础镜像:

cd /usr/local/shell/docker
cat >> Dockerfile <<EOF
# 以frolvlad/alpine-glibc为基础镜像
FROM frolvlad/alpine-glibc

# 把jre添加进去
ADD jre /usr/local/

# 设置环境变量
ENV JAVA_HOME /usr/local/jre
ENV PATH ${PATH}:${JAVA_HOME}/bin
CMD ["java", "-version"]
EOF

# 构建镜像
docker build -t jre-env/jre:v1 .

然后重新构建应用镜像,构建完成以后在此运行,刚才的问题还是存在!!! 好吧,我承认我可耻的屈服了。直接使用 java8 做基础镜像,这回不会有问题了吧。修改应用层 Dockerfile

# 使用java:8-jre作为基础镜像
FROM java:8-jre

# 维护者信息
MAINTAINER hxj

# 设置字符编码
ENV LANG C.UTF-8

# 设置alpine时区
ENV TIMEZONE Asia/Shanghai

# 添加应用 这里相当于把应用添加进来并重命名
ADD spring-mongo-1.0.jar spring-mongo.jar

# 启动应用
ENTRYPOINT ["java" ,"-jar", "spring-mongo.jar"]

构建应用镜像

docker build -t spring-mongo .

运行

docker run -itd -p 80:8080 spring-mongo

查看运行中容器:

docker ps

在这里插入图片描述
oh mygod!终于跑起来了,迫不及待拿出 postman 请求了下接口,发现不通,telnet 主机 80,果然不通,怀疑是防火墙的问题
查看防火墙

systemctl status firewalld.service

# 发现有个绿色的 active 字样,果然防火墙是开着的
# 这里为了简单,直接关闭防火墙

systemctl stop firewalld.service

# 再次查看防火墙状态 disavtive ,说明防火墙已关闭
systemctl status firewalld.service

# 最后禁止防火墙启动,一劳永逸
systemctl disable firewalld.service

再次 telnei 主机 80,瞬间就连上了,拿出 postman,果然拿到了我们想要的数据
在这里插入图片描述
至此,我们的 springboot 应用就成功部署到 docker 上了。虽然过程不是那么的顺利,虽然我们的镜像有一点肥胖,但是我们最终还是达成了我们的目的。

至于这个肥胖的镜像,以后有时间再尝试给他减肥吧。今天的内容就到这里了,我们下节见。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐