由于 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% 左右。
网友评论