如果使用Docker ,则应该知道它具有客户端-服务器架构。 有docker
命令行工具,可将所有命令( build
, pull
, run
等)发送到Docker Host的API。 命令行工具只是一个优雅的包装器,因此您不必自己进行原始HTTP调用。
这种架构提供了非常方便的去耦。 例如,您可以指示docker
客户端将命令发送到远程多克尔守护进程,而不是从本地主机的一个。 更重要的是,得益于此架构,各种各样的软件都可以与Docker集成,这正是我的项目之一comdor所做的。 但是,我遇到了麻烦,并且它的开发目前处于待定状态,等待docker-java-api的第一个版本发布。
docker
客户端已经有两种Java实现: docker-java / docker-java和spotify / docker-client ,为什么还要另外一个呢?
第一个原因是它们都不是面向对象的。 它们实际上不是API,而是SDK。 从我的角度来看,SDK和API之间的区别如下:SDK是一组类/工具,用户必须将这些类/工具放在一起才能创建某些东西。 另一方面,API应该是已经构建的系统上的一组接口,该接口应该流畅且直观–理想情况下,我应该能够像使用Docker一样容易地使用Java包装器来学习Docker。通过与命令行客户端一起玩。
上面的两个库都是SDK,因为它们的封装几乎为零,用户必须知道如何将这些工具放在一起才能在Java中实现docker
。 例如,在那些库中,我不知道应该将Port
或ExposedPort
类型的对象ExposedPort
哪里,或者它们之间有什么区别。 也有诸如HostConfig
和PortBinding
类的类。
让我问一个问题:当您第一次开始使用Docker(或其他任何应用程序)时,它是否要求您提供任何端口,绑定或服务上下文? 不,您只按了一个按钮,或运行了一个命令,就使用了interface 。 当然,根据系统的复杂性,您可以选择进行调整,更改一些配置等,但是这些应该是高级选项,而不是大多数用例中必须要做的事情。
底线是它们不是很有用。 我想从Java访问Docker,而不是在Java中构建/组装Docker –我希望您能有所作为。
使我决定写一个新书的第二个原因 (这实际上是表演的终结者)是,他们俩似乎都非常“胖”。 他们甚至警告您,它们可能会导致类路径问题(它们都带来了Jersey 2.x实现,这显然与Jersey 1.x不兼容)–这在我的项目中引起了问题,因为它是Java EE,所以我什至无法部署在Glassfish上的应用程序,它引起了一些非常奇怪的异常。 我尝试了各种变通办法,包括对依赖项进行着色 ,似乎没有任何效果。
因此,我决定构建自己的Java包装器,该包装器应为:
- 尽可能流畅和直观
- 封装–理想情况下,只有两个公共类,其他所有东西都隐藏在Java接口后面
- 尽可能少的建造者
- 干净,其依赖项应该清楚,并且不会与其他Java平台或框架发生冲突
它仍处于早期阶段,因此我只能提供一些有关其工作方式的提示:
final Docker docker = new LocalDocker("unix:///var/run/docker.sock");
docker.containers().create(
Json.createObjectBuilder()//JSON payload for creating a Container.
.add(..., ...)
.build()
);
final Container container = docker.containers().get("containerId");
//...
上面是与本地Docker Daemon通信的方式。 有趣的是,我们必须通过unix套接字实现HTTP调用。 对于Java中的Unix套接字,将使用此项目,并将创建的Socket
传递给Apache HttpClient。
这是使用远程Docker主机的方法:
final Docker docker = new RemoteDocker(
"tcp://123.34.65.232:1234",
"/path/to/ssl/certs"
);
final Container created = docker.containers().create(
Json.createObjectBuilder()
.add(..., ...)
.build()
);
final Container existing = docker.containers().get("containerId");
//...
这后面有一个简单的HttpClient,没有Unix套接字,但是,我们必须确保它正确使用了那些证书,以便完全加密通信。
您会看到,用户仅使用界面。 它很流利,不需要任何可疑的配置对象或端口-至少不是第一次使用时,也许我们可以以某种方式修饰这些实现,从而为用户提供更多的调优功能。
此外,它应尽可能与该语言集成。 例如,这就是我要遍历所有容器的方式:
final Docker docker = new RemoteDocker(
"tcp://123.34.65.232:1234",
"/path/to/ssl/certs"
);
final Containers containers = docker.containers();
for(final Container container : containers) {
//Containers is the entry point of the Containers API
//and also implements Iterable<Container>
}
你怎么看? 这看起来是更好的选择吗? 如果是,请随时贡献。 该项目还通过Zerocracy进行管理,因此这是在平台上赢得声誉点的好方法。
翻译自: https://www.javacodegeeks.com/2018/03/java-api-for-docker.html