浅析Unix domain socket是什么、Java如何使用UnixSocket调用Docker API对容器进行操作(jnr-unixsocket的使用)
一、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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2017-07-19 浅析JavaScript之深拷贝浅拷贝