fabric8io的插件不仅支持通过dockerfile和docker-compose文件进行docker镜像构造(build),镜像推送(push),还支持对容器操作(如run,stop,remove等),也就是说它可以实现对Docker从构建镜像到运行和推送完整的控制流程,这是它独树一帜的地方.
在众多docker-maven插件中,fabric8io的docker-maven-plugin毫无疑问是最强大的.
现在网上相关的教程大多是使用spotify的,本人一开始也是用spotify,但发现使用起来很有局限性,然后就找其他的docker-maven插件,最终挖掘到了fabric8io的插件.简单来说,spotify能做的事,fabric8io都能做,而且fabric8io选择更多,功能更多.

一 fabric8io和spotify的对比

下面用fabric8io和spotify代指其插件

首先,在对比之前,要先认识一个观点,不管使用哪一种docker插件来构造image,都比不上直接用Dockerfile编写简单,而且可复用,不用学习不同插件不同的构造规则.这一点也在spotify的github项目的README文档里有特别强调,为此他们还特地开发了一个dockerfile-maven插件,这个插件强制要求使用Dockerfile,他们认为这才是正途,事实也是如此.

很多人选择用spotify是因为所谓"从Stars、文档易用性以及更新频率三个纬度考虑",那下面我们就先从这三者来做简单的对比.再对比功能.

1 Stars

截至目前(2018年7月),fabric8io的star数是900+,spotify的dockerfile-maven是800+,两者差不多,比较多的是spotify的docker-maven-plugin(1500+),但spotify也说了,用docker-maven-plugin不如用dockerfile-maven简单(不然也不需要多做这个插件出来),所以Stars这里是基本持平的

2 文档易用性

这里毫无疑问是spotify的文档更容易用,因为不管是docker-maven-plugin还是dockerfile-maven,spotify的所谓文档都只是放在对应github项目的首页,就是一份README的MarkDown文档而已,可读性很强,可以简单上手.相信这也是spotify插件拥有大量Stars的原因.

相比之下,fabric8io的github的README相当于什么都没写,就只是简单粗暴地给了用户手册的访问链接,虽然也有一个简单的"introlmd",但是对于构建项目没有太大的帮助,最后还是得来看用户手册

fabric8io的用户手册内容相当丰富,这也是因为它功能比较强大.所以这里见仁见智.另外,如果使用Dockerfile和docker-compose文件的话,其实可以避开大部分的配置,剩下的配置都是因为它额外的功能,所以其文档虽然复杂,但配置却可以很简单.

3 更新频率

截至目前,fabric8io最近一次更新推送是在12天前,spotify的两个项目则是在两个月前.

4 功能

这才是要比较的重点,也是 fabric8io全面碾压spotify的地方

1 对dockerfile和docker-compose文件配置的支持

截至到2019年1月。
spotify才刚刚支持自定义dockerfile文件的位置,在这之前dockerfile必须安装一定的规则放置才行。对于docker-compose.yml文件的支持为零。

fabric8io很早就支持自定义dockerfile文件和docker-compose.yml文件的导入了。不过目前对docker-compose.yml版本不支持3.0及更新。对于我目前来说是够用了,以后希望会更新支持。

对于我这种喜欢把启动参数放在docker-compose文件的人来说,对docker-compose的支持很重要,而且这样就完全剥离了插件对docker构建和运行参数的繁琐配置了。

2 对docker容器的控制

fabric8io的有两大功能:

  1. 构造并推送Docker镜像
  2. 启动和停止Docker容器

也就是说通过fabric8io的docker插件,我们可以实现对Docker从构建镜像到运行和推送完整的控制流程

而包括spotify在内的其他插件则仅有第一部分功能,即构造并推送镜像,而没有实现对容器的控制.这也是我使用fabric8io而不使用spotify的最主要原因.

2 对远程docker主机的连接支持

spotify只支持在本机docker的镜像build、tag、push,而fabric8io可以用于远程主机,这个时候要注意 dockerHost 项的配置。

二 dockerHost 配置

这里单独先列出来说是因为我在这里被坑了很久。
需要注意一下 dockerHost的配置和docker官方的配置规则不太一样,这里是个坑点

1 docker官方的监听配置

docker可以配置三种不同类型的Socket请求:unix,tcp,和 fd,其中 fd 和 unix 通常用于本机连接, tcp 用于 ip 连接。三者在 /etc/docker/daemon.json 的配置项为 "hosts",需要注意不支持 http(https)

2 fabric8io 的主机配置

fabric8io的 的dockerHost支持 tcp 和http(https)两种格式

1 tcp

如果使用tcp则只能使用 2375 和 2376端口,分别对应不加密验证和加密验证
这个时候在url里配置其他端口是无效的。
(也就是说,服务器设置了监听 tcp:///0.0.0.0:9999,fabric8io的插件设置 tcp:公网ip:9999,也是无效的,这个时候如果启用了ssl加密的话就只能一起用 2376)

2 http/https

这个时候端口是可以自定义的
即是说直接用 http://公网ip(域名):9999 即可。

3 端口报错的提示

端口问题连接时会报错 : Cannot create docker access object org.apache.http.ProtocolException: The server failed to respond with a valid HTTP response

三 fabric8io的docker-maven插件的使用

1 参考配置

如果是想要快速启动,可以参考下面的配置

远程Docker的控制和配置可以看这一篇文章:Docker 守护进程+远程连接+安全访问

下面使用Dockerfile完成docker镜像构建,使用docker-compose.yml完成docker容器启动参数控制

            <plugin>
            
                <groupId>io.fabric8</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.26.0</version>

                <!--全局配置-->
                <configuration>
	                <!--这一部分是为了实现对远程docker容器的控制-->
                    <!--docker主机地址,用于完成docker各项功能,注意是tcp不是http!-->
                    <dockerHost>tcp://公网IP:2376</dockerHost>
                    <!--docker远程访问所需证书地址,如果docker远程主机没有启用TLS验证则不需要配证书-->
                    <certPath>${project.basedir}/docker/ssh</certPath>

					<!--这一部分是为了实现docker镜像的构建和推送-->
                    <!--registry地址,用于推送,拉取镜像,我这里用的是阿里的registry-->
                    <registry>registry.cn-shenzhen.aliyuncs.com</registry>
                    <!--认证配置,用于私有registry认证,如果忘记了可以去阿里的registry查看-->
                    <authConfig>
                        <push>
                            <username>这里填registry的用户名</username>
                            <password>这里填registry的密码</password>
                        </push>
                    </authConfig>
                    
                    <!--镜像相关配置,支持多镜像-->
                    <images>
                        <!-- 单个镜像配置 -->
                        <image>
                            <!--镜像名(含版本号)-->
                            <name>命名空间/仓库名称:镜像版本号</name>
                            <!--别名:用于容器命名和在docker-compose.yml文件只能找到对应名字的配置-->
                            <alias>${project.name}</alias>
                            <!--镜像build相关配置-->
                            <build>
                                <!--使用dockerFile文件-->
                                <dockerFile>${project.basedir}/docker/${project.name}</dockerFile>
                            </build>
                            <!--配置docker-compose文件-->
                            <external>
                                <type>compose</type>
                                <basedir>${project.basedir}/docker</basedir>
                                <composeFile>docker-compose.yml</composeFile>
                            </external>
                            <!--容器run相关配置-->
                            <run>
                                <!--配置运行时容器命名策略为:别名,如果不指定则默认为none,即使用随机分配名称-->
                                <namingStrategy>alias</namingStrategy>
                            </run>
                        </image>
                    </images>
                </configuration>
                <dependencies>
                    <!--该插件需要这个依赖-->
                    <dependency>
                        <groupId>commons-codec</groupId>
                        <artifactId>commons-codec</artifactId>
                        <version>1.11</version>
                    </dependency>
                </dependencies>
            </plugin>

可以看到,其实配置是相当简单清晰的,只要你确保Dockerfile和docker-compose.yml符合规范,能够使用,这个插件就可以代替你使用了,而你仅需要给它配置一些最基础的授权信息

2 mvn指令说明

maven指令功能
docker:start创建和启动容器
docker:stop停止并销毁容器
docker:build构建镜像
docker:watch自动进行重建和重启
docker:push将镜像推送到registry
docker:remove从本地docker主机删除镜像
docker:logs显示容器日志
docker:source将docker build archive附加到Maven项目
docker:save将镜像保存到文件
docker:volume-create创建卷以在容器之间共享数据
docker:volume-remove删除创建的卷

注意,start和run是同义的,可以互相代替,另外,这里的stop和remove和在docker的不一样,docker的stop会保留容器,这里默认是停止并销毁(当然也可以在pom配置或mvn参数里指定keepContainer使其不销毁),但是我认为一般是不会用到暂停的,stop就是为了remove

3 指令实践

这里我贴一下我常用的maven指令
这样就可以完成从打包到容器运行的完整流程

mvn clean package docker:stop docker:remove docker:build docker:run 

不是每一次运行都要推送的,如果要的话可以单独调用docker:push

mvn docker:push

4 注意事项

docker:run 这里有个坑,docker:run是在前台执行,也就是说,它并不能像使用docker一下直接docker start -d来实现后台运行,所以如果是在命令行下启动的话,按Ctrl+C就直接退出了,方法是命令行下启动的时候使用如下指令包装成后台运行

nohup mvn docker:run & 

如果是用IDE控制的话就不用担心,因为IDE只是监控运行日志而已,IDE这里退出不影响其在远程服务器上的运行.

另外,docker:run之后的指令不会运行,因为run之后它会监控Java程序的控制台输出直到运行结束,而一般Java Web程序是作为服务器一直运行的,所以就导致docker:run后面的指令不执行
解决方法有两个,第一,让docker:run放最后,第二,另外单独执行第二条mvn指令

参考:
github项目地址:https://github.com/fabric8io/docker-maven-plugin
用户手册:http://dmp.fabric8.io/

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐