Docker Engine API
===
Docker 的架構
---
* 下圖是 Docker 官方的架構圖
* 由圖可知,Docker Client 與 Docker Host 是可以分開的
* 而我們一般運行 Docker,Client & Host 是同一台伺服器

* 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
```

啟用 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== 並存檔。

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 會看到如下圖

4. 檢查 Docker 是否有監聽 2375 Port
```bash=
sudo lsof -i -P -n | grep dockerd
```

```bash=
sudo ss -tulpn | grep dockerd
```

#### 以上就完成了啟用 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 錯誤訊息

參考資料
---
[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/)