淺析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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM