Docker Engine API === Docker 的架構 --- * 下圖是 Docker 官方的架構圖 * 由圖可知,Docker Client 與 Docker Host 是可以分開的 * 而我們一般運行 Docker,Client & Host 是同一台伺服器 ![image.png](https://lh3.googleusercontent.com/pw/AP1GczNDzlLliP08VjU6rbfdrTBolxR1cik2XSqJsOEFD2q6QLggmefpXJ0xD4AhhBdciRc89Uipu94NdyY7xaBqJKCXrtDTtnhM8OcUqpyjGZRke6y_cWC_hBH50M6n2BKkMjbeNrzhoQGZ7R81vPDg3LQvSA=w1233-h651-s-no-gm?authuser=0) * Docker Engine 提供了 Web API,讓你可以使用慣用的程式語言來控制 Docker Engine,甚至 Docker Container Apps 的數量(Scale Up/Down) * 另外,Docker Engine 也提供了 [SDK for Go & Python](https://docs.docker.com/engine/api/sdk/),熟悉這兩種語言的人,可以直接使用 SDK * Docker Engine API 是 RESTful API,你可以很輕鬆地使用 wget, curl, powershell, 或是你慣用的程式語言來存取它。 * 要使用 Docker Engine API 之前,必須先知道你的 Docker Engine 版本所使用的 API 版本 #### 查詢 Docker API 版本可以使用以下命令 ```bash= docker version ``` ![image.png](https://hackmd.io/_uploads/SJTSwqPQT.png) 啟用 Docker Engine API --- #### Docker Engine API 預設是沒有啟動的,必須自行設定,設定步驟如下 1. 開啟遠端 Docker Host 上的 Docker Service 設定檔 ```bash= # 以 systemctl 讀取服務設定 # 第一行是設定檔路徑檔名 # 將第一行的註解符號去除掉,得到完整路徑檔名 # 存入環境變數 DOCKER_SERVICE_CONF_FILE=$(systemctl cat docker.service | head -n 1 | sed 's/^#\s//g') vi ${DOCKER_SERVICE_CONF_FILE} # vi /usr/lib/systemd/system/docker.service ``` 2. 修改其中 **ExecStart** 的命令,增加 ==-H tcp://0.0.0.0:2375== 並存檔。 ![image.png](https://hackmd.io/_uploads/HJJEi9DQT.png) 3. 然後讓 systemd 重新載入 Daemon 相關設定檔,然後重新啟動 Docker ```bash= # 讓 systemd 重新載入 Daemon 設定檔 sudo systemctl daemon-reload # 重新啟動 Docker Daemon sudo systemctl restart docker # 檢查 Docker Service 狀態 sudo systemctl status docker ``` #### 如果有正常啟動 docker daemon 會看到如下圖 ![image.png](https://hackmd.io/_uploads/ByOQh5wQT.png) 4. 檢查 Docker 是否有監聽 2375 Port ```bash= sudo lsof -i -P -n | grep dockerd ``` ![image.png](https://hackmd.io/_uploads/rkGsh9PXT.png) ```bash= sudo ss -tulpn | grep dockerd ``` ![image.png](https://hackmd.io/_uploads/HJxpn9PX6.png) #### 以上就完成了啟用 Docker Engine API --- Docker Engine API v1.43 簡單列舉容器相關操作 --- ### 查詢 Container 資訊 Method: **GET** :::info http://{docker_host_ip}:2375/containers/json ::: |參數|說明| |----|----| |all| boolean,預設值為 false/0,表示只回傳正在運行的容器資訊;all=true/1,表示回傳所有容器資訊;==注意這裡數值的布林值,與Python相同,只有0代表 false,其他數值,不管正負,都代表true==| |limit|integer,回傳最近幾個Container的資訊,包含沒有在運行的容器| |size|boolean,預設值為 false,回傳資訊增加容器大小| |filters|string,設定篩選容器的條件| #### 可用的 filters |參數|說明| |----|----| |ancestor|指定 "ancestor": ["image_name":"image_tag"]| |before|指定 container_id 或 container_name之前的容器| |expose|指定 expose port| |exited|指定 container exit code| |health|指定狀態:starting, healthy, unhealthy, none| |id|指定 Container ID| |isolation|指定隔離狀態:default, process, hyperv;Windows Daemon Only| |label|指定 {"label":["key"]} 或是 {"label":["key=value"]}| |name|指定Container Name| |network|指定 network_id 或 network_name| |publish|指定 port/proto 或 startport-endport/proto| |since|指定 container_id 或 container_name之後的容器| |status|指定特定狀態的容器:created, restarting, running, removing, paused, exited, dead| |volume|指定volume_name 或 volume_id| 範例: ```bash curl http://192.168.13.161:2375/containers/json?all=1 curl http://192.168.13.161:2375/v1.43/containers/json?filters={"ancestor": ["nginx:latest"]} curl http://192.168.13.161:2375/containers/json?filters={"label":["CallFrom=Powershell"]} ``` --- ### 查詢指定的 Container 資訊 Method: **GET** ```bash http://{docker_host_ip}:2375/containers/[container_id | container_name]/json ``` --- ### 查看 Container 內部運行的程式 Method: **GET** :::info http://{docker_host_ip}:2375/containers/[container_id | container_name]/top ::: --- ### 查看 Container 運行的 Log Method: **GET** :::info http://{docker_host_ip}:2375/containers/[container_id | container_name]/logs ::: --- ### 查看 Container 內部被異動的檔案/目錄 Method: **GET** :::info http://{docker_host_ip}:2375/containers/[container_id | container_name]/changes ::: --- ### 匯出 Container 並下載 Method: **GET** :::info http://{docker_host_ip}:2375/containers/[container_id | container_name]/export ::: --- ### 持續回傳容器運行資源狀態(JSON) Method: **GET** :::info http://{docker_host_ip}:2375/containers/[container_id | container_name]/stats ::: --- ### 建立容器(注意:==容器只有建立,並沒有運行==) Method: **POST** :::info http://{docker_host_ip}:2375/container/create ::: |網址參數|說明| |------|----| |name|string,必須符合正規式 ^/?[a-zA-Z0-9][a-zA-Z0-9_.-]+$ | #### Header請指定 "Content-Type: application/json" #### Body JSON 簡單列舉參數如下 |參數名稱|說明| |-------|---| |Env|Array of Strings,指定環境變數及值| |Cmd|Array of Strings,指定容器啟動時,要執行的命令| |Image|string,指定容器要使用的 Image Name 以及 Tag| |Volumes|指定掛載的磁碟| |WorkingDir|指定命令要在哪個目錄下運行| |Labels|指定 Key/Value 的 Metadata| |HostConfig|設定網路相關資訊,例如:Port Mapping| #### 使用 bash shell curl 建立 Container ```bash= curl -X POST -H "Content-Type: application/json" \ -d '{"Image": "nginx:latest", "ExposedPorts": { "80/tcp": {} }, "HostConfig": { "PortBindings": { "80/tcp": [{ "HostIp": "", "HostPort": "9001" }] } } }' \ http://192.168.213.214:2375/containers/create ``` #### 使用 Powershell 跑迴圈,建立三個 Container:web01, web02, web03,分別使用 Port 9001, 9002, 9003,並啟動這三個Container * Create Containr,並不會啟動 Container ```powershell= $head = @{ 'Content-Type' = 'application/json' } $Port = 9000 For($i=1; $i -le 3; $i++){ $Port++ $json = "{""Image"": ""nginx:latest"", " $json += """ExposedPorts"": { ""80/tcp"": {} }, " $json += """HostConfig"": { ""PortBindings"": { ""80/tcp"": [{ ""HostIp"": ""0.0.0.0"", ""HostPort"": ""$Port"" }] } }, " $json += """Labels"" : {""CallFrom"":""Powershell""} }" # Create Container Invoke-RestMethod -Method POST -Uri ("http://192.168.13.161:2375/containers/create?name=web{0:d2}" -f $i) -Headers $head -Body $json # Start Container Invoke-RestMethod -Method POST -Uri ("http://192.168.13.161:2375/containers/web{0:d2}/start" -f $i) -Headers $head } ``` --- ### 啟動執行容器(Start) Method: **POST** :::info http://{docker_host_ip}:2375/containers/[container_id | container_name]/start ::: --- ### 停止運行容器(Stop) Method: **POST** :::info http://{docker_host_ip}:2375/containers/[container_id | container_name]/stop ::: --- ### 重新啟動執行容器(Restart) Method: **POST** :::info http://{docker_host_ip}:2375/containers/[container_id | container_name]/restart ::: --- ### 傳送 POSIX signal 給容器(Kill) Method: **POST** :::info http://{docker_host_ip}:2375/containers/[container_id | container_name]/kill?signal=[SIGNAL_STRING | SIGNAL_CODE] ::: --- ### 變更容器名稱(Rename) Method: **POST** :::info http://{docker_host_ip}:2375/containers/[container_id | container_name]/rename?name=[new_container_name] ::: --- ### 刪除容器名稱(Remove) Method: ==DELETE== :::info http://{docker_host_ip}:2375/containers/[container_id | container_name] ::: --- #### 以上,當你使用錯誤的 Method 時,會顯示 page not found 錯誤訊息 ![image.png](https://hackmd.io/_uploads/Bka6ChD7a.png) 參考資料 --- [Configure remote access for Docker daemon](https://docs.docker.com/config/daemon/remote-access/) [Docker Engine API (1.43)](https://docs.docker.com/engine/api/v1.46/) [Docker Engine API version history](https://docs.docker.com/engine/api/version-history/) [Develop with Docker Engine SDKs](https://docs.docker.com/engine/api/sdk/)