通过 socket 访问 docker 的接口

2021-08-05  本文已影响0人  追风骚年

由于 docker 是一个 cs 架构的设计,他后台会起一个服务,server 对外提供的是一个 socket 方式的访问入口,我们在终端使用 docker ps 等命令时,终端内的 docker 命令相当于一个客户端程序。

这里以 golang 程序为例,参考 docker 官方提供的技术文档。

package main

import (
    "context"
    "io/fs"
    "io/ioutil"
    "net"
    "net/http"
    "testing"
)

func getDockerClient() http.Client {
    return http.Client{
        Transport: &http.Transport{
            DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
                // /var/run/docker.sock 为 docker 对外提供的 socket 路径
                return net.Dial("unix", "/var/run/docker.sock")
            },
        },
    }
}

func TestDockerPs(t *testing.T) {
    client := getDockerClient()
    resp, err := client.Get("http://docker.sock/containers/json") // 这里的 host 没有意义,可以随便填

    if err != nil {
        t.Fatal(err)
    }
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        t.Fatal(err)
    }
    t.Log(string(body))
}

func TestDockerInspect(t *testing.T) {
    client := getDockerClient()

    resp, err := client.Get("http://docker.sock/containers/0b3606c482d4/json")

    if err != nil {
        t.Fatal(err)
    }
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        t.Fatal(err)
    }

    t.Log(string(body))
}

func TestDockerExport(t *testing.T) {
    client := getDockerClient()
    resp, err := client.Get("http://docker.sock/containers/0b3606c482d4/export")

    if err != nil {
        t.Fatal(err)
    }

    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        t.Fatal(err)
    }

    err = ioutil.WriteFile("0b3606c482d4.tar", body, fs.ModePerm)
    if err != nil {
        t.Fatal(err)
    }
}

通过测试可以发现 socket 访问程序速度非常快,有网友测试通过 socket 比普通的 tcp 请求快 15% 左右。

参考文档

上一篇下一篇

猜你喜欢

热点阅读