使用 Docker 构建 Spring Boot Application

Docker & Spring Boot

Docker 是一种 Linux 容器的实现,具有进程的轻量级资源隔离的特点,每一个容器对应操作系统中的一个进程,但是它又会有自己的网络空间、文件系统、PID 等。Docker 除了实现 Linux 容器,还使得容器具有“社会化”的属性,用户可以将容器镜像发布在 Docker Hub 与其他开发者共享、协作,类似于 Maven

Spring Boot 简化了 Spring 应用程序的开发过程,遵循约定优先配置的原则提供了各类 开箱即用(out-of-the-box) 的框架配置。另一方面,Spring Boot 还具备将代码直接构建为可执行 jar 包的能力,这个 jar 包是一个可以独立运行的部署单元。基于以上特性,现在普遍认为 Spring Boot 提供了一种快速构造微服务(Micro-Service)的能力。

Spring Boot 的运行环境非常简单,将 Spring Boot Application 打包为 Docker 镜像,对于自动化部署、运维都非常方便。

Dockerizing Spring Boot Application

使用 Docker 发布 Spring Boot Application,需要经历简单的几步,即可实现。

如有需要,可参考本文所涉及 Demo

常规操作

编写 Spring Boot Application

本文不是为了讲解如何编写 Spring Boot Application,故建议读者直接采用脚手架快速构建出一个 Spring Boot Application。

编写 Dockerfile

Dockerfile 对于 Docker 的意义如同 POM 之于 Maven

pom.xml 同级目录新建文件 Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 基础运行环境,建议采用 openjdk alpine 作为基础的镜像
FROM openjdk:8-jdk-alpine

# 标记作者
LABEL maintainer="fuyongde@foxmail.com"

# 挂载 /tmp 目录,因为 Spring Boot 内嵌的 Tomcat 默认使用 /tmp 作为工作目录
VOLUME [ "/tmp" ]

# 容器对外映射 8080 端口
EXPOSE 8080

# 定义要打包的 jar
ARG JAR_FILE=target/thanos-0.0.1-SNAPSHOT.jar

# 将指定的 jar 添加到目标镜像并重命名
ADD ${JAR_FILE} thanos-0.0.1.jar

# 使用 java -jar 命令运行目标程序
ENTRYPOINT [ "java", "-jar", "/thanos-0.0.1.jar" ]
  • FROM:指定一个构建镜像的基础源镜像,如果本地没有就会从公共库中拉取,没有指定镜像的标签会使用默认的 latest 标签,如果需要在一个 Dockerfile 中构建多个镜像,该选项可以出现多次。
  • LABEL:为镜像指定标签
  • VOLUME:可实现挂载功能,可以将内地文件夹或者其他容器种得文件夹挂在到这个容器种
  • EXPOSE:暴漏容器运行时的监听端口给外部,但是 EXPOSE 并不会使容器访问主机的端口,如果想使得容器与主机的端口有映射关系,必须在容器启动的时候加上 -p 参数
  • ARG:设置变量
  • ADD:将文件添加到目标镜像中
  • ENTRYPOINT:启动时的默认命令

构建 Docker 镜像

由于 Docker 依赖我们程序编译的结果,故在构建 Docker 镜像之前,需要先构建我们的工程。

如本文所讲例子,需要依次执行

1
2
3
4
# 采用 Maven 构建 Spring Boot Application
mvnw install
# 构建 Docker Image
docker build -t thanos .

构建完成之后,可以通过 docker image ls 查看。

1
2
REPOSITORY    TAG       IMAGE ID        CREATED              SIZE
thanos latest 5f30b11b5088 About an hour ago 122MB

运行 Docker 镜像

和正常的运行 Docker 镜像的命令一致。

1
2
3
4
docker run -p 8080:8080 thanos

# 也可以采用后台运行的方式运行容器
docker run -d -p 8080:8080 thanos

运行之后,通过 docker ps 命令来查看当前运行的容器。

1
2
CONTAINER ID   IMAGE    COMMAND                  CREATED             STATUS             PORTS                    NAMES
9f20a76e22fa thanos "java -jar /thanos-0…" About an hour ago Up About an hour 0.0.0.0:8080->8080/tcp xenodochial_noyce

将 Docker 镜像推送到镜像仓库

由于众所周知的原因,我们访问 docker hub 并不稳定,而且速度比较慢,本文采用阿里云的容器镜像服务。

  1. 登录到阿里云容器镜像服务
1
2
3
# 登录
docker login --username=fuyongde@foxmail.com registry.cn-hangzhou.aliyuncs.com
# 输入密码,当看到 Login Succeeded 表示登录成功
  1. 为当前镜像打 tag
1
docker tag thanos registry.cn-hangzhou.aliyuncs.com/fuyongde/thanos:v1
  1. 推送到容器镜像服务
1
docker push registry.cn-hangzhou.aliyuncs.com/fuyongde/thanos:v1

按照上述步骤操作完成之后,登录到阿里云的控制台 > 容器镜像服务 > 镜像仓库 即可查看已经推送好的镜像。

dockerfile-maven-plugin

经过上述的操作我们发现,要将我们的 Spring Boot Application 打包为 Docker 镜像,必须先将我们的工程构建,然后才能执行 Docker 的 buildpush。那么能否将工程的构建与 Docker 的操作合二为一呢?

答案是肯定的,这就需要用到 dockerfile-maven-plugin

引入 dockerfile-maven-plugin

基于上述工程,在 pom.xml 中添加插件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.10</version>
<configuration>
<repository>registry.cn-hangzhou.aliyuncs.com/fuyongde/thanos</repository>
<tag>${project.version}</tag>
<useMavenSettingsForAuth>true</useMavenSettingsForAuth>
</configuration>
<executions>
<execution>
<id>default</id>
<phase>install</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
</plugin>

其中:

  • repository:表示要上传的容器镜像服务,可以是阿里云、Docker Hub 等
  • tag:镜像打包的 tag
  • execution:这个标签下的配置表示,在 Maveninstall 阶段,进行 Dockerbuildpush 操作
  • useMavenSettingsForAuth:表示使用 Maven 的配置的账号密码来认证 Docker 容器镜像服务,需要在 Mavensettings.xml 文件中加入以下配置:
1
2
3
4
5
6
7
<servers>
<server>
<id>registry.cn-hangzhou.aliyuncs.com</id>
<username>username</username>
<password>password</password>
</server>
</servers>

构建

执行 mvn install 命令,Docker 镜像就打包并上传好了 ✌。

One more thing

你以为上述构建 Docker 镜像方法就非常方便了吗?

Too young!

下一篇,带你了解 Jib,Make docker simple again✨!