Docker Tips: 關於/var/run/docker.sock
你可能已經執行過docker hub上的container並且注意到其中的一些需要繫結掛載(mount)/var/run/docker.sock
檔案。這個檔案是什麼呢,為什麼有些時候會被container所用到?剪短的回答:這個是Unix socket,Docker程式預設監聽檔案,為進行container程式間通訊所用。
我們先來看看Portainer,是一個用於管理docker host或者Swarm叢集的開源工具。如果用來管理本地Docker host Protaner可以用以下命令執行,繫結掛載到本地的docker的Unix socket上
$ docker container run -d \
-p 9000:9000 \
-v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
複製程式碼
然後我們可以通過本地9000埠來訪問圖形介面,可以管理我們的container,images,volumes等等
為了做到以上所有的管理功能,Portainer與本地Docker程式進行通訊就是通過掛載/var/run/docker.sock
檔案來實現的。
Docker daemon API
當Docker在主機上安裝以後,Docker守護程式監聽預設監聽/var/run/docker.sock
檔案。當然這個路徑是可以設定的,通過-H
-H unix:///var/run/docker.sock
複製程式碼
Notes: 由於-H引數的提供,Docker守護程式還可以監聽tcp 主機/埠或者其他的Unix sockets
所有HTTP介面定義在 Docker engine API v1.27。所有介面的底層通訊都是通過Unix socket。
Container Creation
通過Portainer介面,我們可以輕鬆的執行container。在引擎後面,Http請求通過docker.socket傳送到Docker程式。
下面來演示一下這個以及通過curl建立一個Nginx containue
Notes: 當使用HTTP API,執行container需要兩步,首先要先建立conatiner然後啟動。
建立一個Nginx Container
下面命令使用curl傳送{“Image”:”nginx”}
請求體通過Unix socket傳送到到Docker程式的介面/containers/create
。最終會建立一個Nginx的container並且會返回他的ID。
$ curl -XPOST --unix-socket /var/run/docker.sock -d '{"Image":"nginx"}' -H 'Content-Type: application/json' http://localhost/containers/create
{"Id":"fcb65c6147efb862d5ea3a2ef20e793c52f0fafa3eb04e4292cb4784c5777d65","Warnings":null}
複製程式碼
啟動Container
通過返回的ID,我們可以通過 /containers/<ID>/start
來執行剛剛新建立的container
$ curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/fcb6...7d65/start
複製程式碼
我們可以看到Nginx container就被啟起來並且正在執行狀態
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fcb65c6147ef nginx “nginx -g ‘daemon …” 5 minutes ago Up 5 seconds 80/tcp,443/tcp ecstatic_kirch
複製程式碼
這說明瞭如何使用Docker套接字輕鬆地從容器內部建立容器。 顯然,他實際並不是通過curl建立容易的,只是我這麼演示能更方便讀者理解。
Docker程式的Streaming events
Docker API暴露一個/events
的介面,可以用來獲取所有Docker程式生成的事件流,舉個例子,他可以用來通過負載勻衡去建立或者刪除container的事件,以便動態地更新他的配置。
跑一個簡單的container並且檢查一下我們如何使用docker程式事件
Apline container
下面命令會以互動模式啟動一個Apline container並繫結docker.sock
$ docker run -v /var/run/docker.sock:/var/run/docker.sock -ti alpine sh
複製程式碼
監聽docker程式的事件
在Apline container內部,我們首先通過apk安裝curl
$ apk update && apk add curl
複製程式碼
現在可以通過docker socket傳送HTTP請求到/events
介面。命令會被掛起,等待新的事件從程式中進來。每個新的事件都會是一個來自docker程式的事件流。
curl --unix-socket /var/run/docker.sock http://localhost/events
複製程式碼
觀察事件
我們建立了一個新的基於Nginx的container,然後監聽他,通過Apline container的標準輸出,這個事件由Docker程式生成。
docker container run -p 8080:80 -d nginx
複製程式碼
我們可以觀察到之前的請求會接收到一系列的事件
$ curl --unix-socket /var/run/docker.sock http://localhost/events
{
"status": "create","id": "277786a066994b4d842dc097c4544e2ddcf50ffe0b6aa8352812ca0aadec4078","from": "nginx","Type": "container","Action": "create","Actor": {
"ID": "277786a066994b4d842dc097c4544e2ddcf50ffe0b6aa8352812ca0aadec4078","Attributes": {
"image": "nginx","name": "hardcore_carson"
}
},"time": 1491683503,"timeNano": 1491683503003280100
}
{
"Type": "network","Action": "connect","Actor": {
"ID": "18147ed9f4510d0149a0810916434df19b3d03f30e17ac4effcbcc1d2371ba97","Attributes": {
"container": "277786a066994b4d842dc097c4544e2ddcf50ffe0b6aa8352812ca0aadec4078","name": "bridge","type": "bridge"
}
},"timeNano": 1491683503061245700
}
{
"status": "start","Action": "start","timeNano": 1491683503389984300
}
複製程式碼
基本上,三個事件發生:
- container的建立
- 預設網橋的建立
- container的啟動
總結
我希望快速解釋能讓你給/var/run/docker.sock
檔案有更好的理解以及他是如何被用來繫結container的。很明顯,應用通過socket連線並不是通過curl但是會用其他庫來進行HTTP請求傳輸給Docker程式。
注意:Docker程式socket的繫結掛載給了container很大的力量去控制Docker程式。所以必須謹慎使用並且只在我們可以信任的container上使用。