dubbo-admin 容器化构建

摘要:最近研究开源项目 zheng,其中用到了dubbo的服务,在使用 Docker 搭建环境的时候发现 dubbo-admin 没有官方的 Docker 镜像,于是自己动手根据官方源码制作一个镜像,学习一下 Spring Boot 应用的容器化过程。

背景介绍

目前 dubbo-admin 被阿里弃用之后并不活跃,但是仍然是一个值得学习的优秀项目。目前官方没有提供Docker 镜像,通过搜索最近只有一个相对较新的镜像:这个镜像是通过获取源码编译获得,但是并没有追踪源码的版本控制,由于dubbo-admin 近期迁移到 Spring Boot,使用jar而不是war,所以这个镜像的DockerFile 已经无法成功构建了,所以决定自己根据源码,然后利用 Maven 插件对项目进行构建并推送镜像到 Docker Hub,完全依照持续集成的思路实现。

参考文章

网上已经有很多关于 Spring Boot 的容器化教程,下面是几篇较为详细的参考:

  1. Dockerize a Spring Boot application
  2. Dockerizing a Spring Boot Application

自动构建配置

整个过程分为三步

  1. 配置 Dockerfile 构建应用镜像
  2. 配置 dockerfile-maven-plugin 使用maven自动构建镜像
  3. 配置 docker-compose 测试镜像

Dockerfile 配置

这里不会详细介绍 Dockerfile 的语法说明,只会对用到的语法进行说明。 Dockfile 的 Github 源码地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# Start with a base image containing Java runtime
FROM openjdk:8-jdk-alpine

# Add Maintainer Info
LABEL maintainer="[email protected]"

# Add a volume pointing to /tmp
VOLUME /tmp

# Make port 8080 available to the world outside this container
EXPOSE 7001

# The application's jar file
ARG JAR_FILE=target/dubbo-admin-2.0.0.jar

# Add the application's jar to the container
ADD ${JAR_FILE} dubbo-admin.jar

# timezone
ARG TIME_ZONE=Asia/Shanghai

RUN apk add -U tzdata \
&& cp /usr/share/zoneinfo/${TIME_ZONE} /etc/localtime

ENV ZOOKEEPER="127.0.0.1:2181"
ENV ROOT_PASS="root"
ENV GUEST_PASS="guest"

# Run the jar file
#ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom", "$ZOOKEEPER", "$ROOT_PASS", "$GUEST_PASS","-jar","/dubbo-admin.jar"]
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Ddubbo.registry.address=zookeeper://$ZOOKEEPER -Ddubbo.admin.root.password=$ROOT_PASS -Ddubbo.admin.guest.password=$GUEST_PASS -jar /dubbo-admin.jar

基本配置

对于该镜像的主要思路就是使用 JDK 基础镜像加载项目构建的额 JAR 文件。同时支持启动的选项配置。

基础镜像:

1
FROM openjdk:8-jdk-alpine

暴露端口

1
EXPOSE 7001

拷贝构建好的项目的JAR

1
2
3
4
5
# The application's jar file
ARG JAR_FILE=target/dubbo-admin-2.0.0.jar

# Add the application's jar to the container
ADD ${JAR_FILE} dubbo-admin.jar

这里配置了一个 ARG,因为随着项目版本的迭代,这个项目的JAR文件名会根据项目版本变化,所以这个作为一个变量存放,后面在 Maven 插件的配置中将会用到该变量。

执行 JAR 文件, 中间的 -Dxxx 都是 Option

1
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Ddubbo.registry.address=zookeeper://$ZOOKEEPER  -Ddubbo.admin.root.password=$ROOT_PASS -Ddubbo.admin.guest.password=$GUEST_PASS -jar /dubbo-admin.jar

环境参数

大部分 Docker 镜像都需用户进行简单配置,我们这里提供了三种配置:

  1. ZOOKEEPER的地址
  2. ROOT密码
  3. GUEST密码
1
2
3
4
5
6
ENV ZOOKEEPER="127.0.0.1:2181"
ENV ROOT_PASS="root"
ENV GUEST_PASS="guest"

# Run the jar file
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Ddubbo.registry.address=zookeeper://$ZOOKEEPER -Ddubbo.admin.root.password=$ROOT_PASS -Ddubbo.admin.guest.password=$GUEST_PASS -jar /dubbo-admin.jar

三个参数都有默认值,如果在启动镜像容器时指定了参数,那么将会使用指定的参数。

dockerfile-maven-plugin 配置

首先看一下整体配置,源码参考见 GitHub

目前这个插件主要做两件事情

  1. 根据当前构建 Jar 包,以及指定的标签,构建 Docker 镜像
  2. 推动镜像到 Docker Hub 仓库

该标签 <repository>xinmeng/dubbo-admin</repository> 指定了远程镜像地址,这个在 Docker Hub 中是唯一的。

1
2
3
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>

这段配置就是指定构建的 Jar 包,标签的名字和我们前面提到的 Dockerfile 里面配置的参数是一致的。

如何快速构建 latest 和带有标签的版本

参考该 issue, 通过配置多个 execution 来完成不同的工作。

比如我们想构建带有项目版本的标签的镜像,那么在 configuration 中加入 <tag>${project.version}</tag>. 如果构建latest 版本,那么 tag 就是 <tag>latest</tag>,在 build 时这个默认值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<!--
mvn dockerfile:build
mvn dockerfile:tag@tag-version
mvn dockerfile:push@push-latest
mvn dockerfile:push@push-version
-->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.3</version>
<configuration>
<repository>xinmeng/dubbo-admin</repository>
<buildArgs>
<JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
<executions>
<execution>
<id>build-and-tag-latest</id>
<phase>none</phase>
<goals>
<goal>build</goal>
</goals>
</execution>
<execution>
<id>tag-version</id>
<phase>none</phase>
<goals>
<goal>tag</goal>
</goals>
<configuration>
<tag>${project.version}</tag>
</configuration>
</execution>
<execution>
<id>push-latest</id>
<phase>none</phase>
<goals>
<goal>push</goal>
</goals>
<configuration>
<tag>latest</tag>
</configuration>
</execution>
<execution>
<id>push-version</id>
<phase>none</phase>
<goals>
<goal>push</goal>
</goals>
<configuration>
<tag>${project.version}</tag>
</configuration>
</execution>
</executions>
</plugin>

有这个配置,我们只需要执行以下命令就可以完成对应的工作,如果需要推送,首先需要 Docker 登陆到对应权限的账号才能成功推送。

1
2
3
4
5
6
7
8
// 构建最新版本
mvn dockerfile:build
// 构建当前项目版本
mvn dockerfile:tag@tag-version
// 推送最新版本
mvn dockerfile:push@push-latest
// 推送当前项目版本
mvn dockerfile:push@push-version

Docker Compose 测试

由于dubbo依赖 zookeeper,所以这里使用docker-compose 创建一个 zookeeper 的服务,并且定一个网络别名,然后使用我们构建的镜像运行 dubbo-admin 服务。
只需要以下命令就可以完成服务启动。

1
docker-compose -f docker/dubbo.yml up -d

关闭服务:

1
docker-compose -f docker/dubbo.yml down

附配置文件源码

zookeeper.yml

1
2
3
4
5
6
version: '2'
services:
dubbo-zookeeper:
image: zookeeper:3.5
ports:
- 2181:2181

dubbo.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
version: '2'
services:
dubbo-zookeeper:
extends:
file: zookeeper.yml
service: dubbo-zookeeper
networks:
dubbo-net:
aliases:
- zookeeper
dubbo-admin:
image: xinmeng/dubbo-admin:2.0.0
environment:
- ZOOKEEPER=zookeeper:2181
- ROOT_PASS=root
- GUEST_PASS=guest
ports:
- 8090:7001
networks:
dubbo-net:
aliases:
- dubbo
networks:
dubbo-net:

总结

该镜像已经应用于 Zheng 的环境部署,参考该文章