一、Unix domain socket(UDS)是什么
Unix domain socket 又叫 IPC(inter-process communication 进程间通信)socket,用于实现同一主机上的进程间通信。
socket 原本是为网络通讯设计的,但后来在 socket 的框架上发展出一种 IPC 机制,就是 UNIX domain socket。虽然网络 socket 也可用于同一台主机的进程间通讯(通过 loopback 地址 127.0.0.1),但是 UNIX domain socket 用于 IPC 更有效率:不需要经过网络协议栈,不需要打包拆包、计算校验和、维护序号和应答等,只是将应用层数据从一个进程拷贝到另一个进程。这是因为,IPC 机制本质上是可靠的通讯,而网络协议是为不可靠的通讯设计的。
UNIX Domain SOCKET 有 SOKCET_DGRAM(数据包套接字)和 SOCKET_STREAM(流套接字)两种模式,类似于UDP和TCP,但是面向消息的UNIX socket也是可靠的,消息既不会丢失也不会顺序错乱。
UNIX domain socket 是全双工的,API 接口语义丰富,相比其它 IPC 机制有明显的优越性,目前已成为使用最广泛的 IPC 机制,比如 X Window 服务器和 GUI 程序之间就是通过 UNIX domain socket 通讯的。
Unix domain socket 是 POSIX 标准中的一个组件,所以不要被名字迷惑,linux 系统也是支持它的。
使用UNIX Domain Socket的过程和网络socket十分相似,也要先调用socket()创建一个socket文件描述符,address family指定为AF_UNIX,type可以选择SOCK_DGRAM或SOCK_STREAM,protocol参数仍然指定为0即可。
查了一下资料,不太懂,就能知道是个什么东西,很多东西代码也是用 C 语言写的,有兴趣的自己去查下资料了解吧
二、Java如何使用UnixSocket调用Docker API对容器进行操作
1、docker-api官方文档:https://docs.docker.com/engine/api/v1.27/#operation/ContainerStart
2、使用curl调用docker-api
curl -v --unix-socket /var/run/docker.sock http:/v1.24/containers/json // -v 打印详情命令
curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/ea05b10d8bef/stop // stop-停止容器 start-启动容器 restart-重启容器
3、在 Docker 官网查阅 API 调用方式
例如:查询正在运行的容器列表,HTTP 方式如下:
$ curl --unix-socket /var/run/docker.sock http:/v1.24/containers/json [{ "Id":"ae63e8b89a26f01f6b4b2c9a7817c31a1b6196acf560f66586fbc8809ffcd772", "Names":["/tender_wing"], "Image":"bfirsh/reticulate-splines", ... }]
4、分析 API 请求的过程
在本机执行如下命令:
curl -v --unix-socket /var/run/docker.sock http:/v1.24/containers/json
三、Java 调用 Docker API 的代码实现 —— jnr-unixsocket
1、导入依赖
<!-- 操作docker -->
<dependency>
<groupId>com.github.jnr</groupId>
<artifactId>jnr-unixsocket</artifactId>
<version>0.38.8</version>
</dependency>
2、测试代码
public static void main(String[] args) { // 建立 Unix Socket 连接
File sockFile = new File("/var/run/docker.sock"); UnixSocketAddress address = new UnixSocketAddress(sockFile); UnixSocketChannel channel = UnixSocketChannel.open(address); UnixSocket unixSocket = new UnixSocket(channel); // 调用 Docker API
PrintWriter w = new PrintWriter(unixSocket.getOutputStream()); w.println("GET /v1.24/containers/json HTTP/1.1"); w.println("Host: http"); w.println("Accept: */*"); w.println(""); w.flush(); // 关闭 Output,否则会导致下面的 read 操作一直阻塞
unixSocket.shutdownOutput(); // 获取返回结果
System.out.println("---- Docker Response ----"); BufferedReader br = new BufferedReader(new InputStreamReader(unixSocket.getInputStream())); String line; while ((line = br.readLine()) != null){ System.out.println(line); } unixSocket.close(); }
3、项目代码
private UnixSocket createUnixSocket() throws IOException { // 建立 Unix Socket 连接
File sockFile = new File("/var/run/docker.sock"); UnixSocketAddress address = new UnixSocketAddress(sockFile); UnixSocketChannel channel = UnixSocketChannel.open(address); UnixSocket unixSocket = new UnixSocket(channel); return unixSocket; } @Override public void createContainer(String config, String containerName) throws IOException { // 建立 Unix Socket 连接
UnixSocket unixSocket = createUnixSocket(); // 调用 Docker API
PrintWriter w = new PrintWriter(unixSocket.getOutputStream()); w.println("POST /v1.24/containers/create?name=" + containerName + " HTTP/1.1"); w.println("Host: http"); w.println("Accept: */*"); w.println("Content-Type: application/json"); w.println("Content-Length: " + config.length()); w.println(""); w.write(config); w.flush(); // 关闭 Output,否则会导致下面的 read 操作一直阻塞
unixSocket.shutdownOutput(); // 获取返回结果
log.info("---- Create Container " + containerName + " ----"); BufferedReader br = new BufferedReader(new InputStreamReader(unixSocket.getInputStream())); String line; while ((line = br.readLine()) != null) { log.info(line); } unixSocket.close(); }
参考文章:
JAVA调用docker-api对容器进行操作:https://blog.csdn.net/nizhen8698/article/details/116725766
Java 使用 UnixSocket 调用 Docker API:https://www.cnblogs.com/anoyi/p/12249257.html