一、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
