1. 程式人生 > 程式設計 >Docker Tips: 關於/var/run/docker.sock

Docker Tips: 關於/var/run/docker.sock

原文:medium.com/better-prog…

你可能已經執行過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上使用。