我使用 docker-compose 來設定帶有一些資料庫和播種器的 API。直到幾天前,一切都還順利,但現在我無法再為資料庫提供種子了。
這是我的一個例子docker-compose.yml文件:
version: '3'
services:
api:
image: <API image>
ports: {API_PORT}:5000 //Flask's default port
depends_on:
- db
db:
image: <DB image>
ports: {DB_PORT}:27017 //MongoDB Default port
db-seed:
image: <seeder image>
// pretty classic docker-compose file, nothing fancy
播種機使用碼頭網路存取 API 容器(http://api:80/)並為其播種。但是,播種器的腳本(用 Python 編寫)現在在連接到 API 容器時傳回錯誤:
$> docker-compose up db-seed
<LOT OF ERRORS>...
requests.exceptions.ConnectionError: HTTPConnectionPool(host='api', port=80): Max retries exceeded with url: /ping (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7f65e78a4310>: Failed to establish a new connection: [Errno 111] Connection refused'))
播種器容器似乎無法存取資料庫容器。導致此錯誤的原因可能是什麼?我該如何解決它?
這是碼頭工人網路檢查我的網路:
[{ "Name": "staging-sensei-api_default", "Id": "b5bd162d27f9a1addaacf1b0f2c09ad799d3ae195cc6e8c9cbb54bfffc27651c", "Created": "2019-07-22T14:18:05.080114521Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.26.0.0/16", "Gateway": "172.26.0.1" } ] }, "Internal": false, "Attachable": true, "Ingress": false, "ConfigFrom": { "Network": "" }, "ConfigOnly": false, "Containers": { "08672fe92d72b111f1a006a2ff20e885ef395a420525953b696672753cb73ff7": {
"Name": "com.frcyber.sensei.elasticsearch",
"EndpointID": "7ba9a1af1af5635d22c9cbd38fad8be222f351e5c0013f0280e2879cdd6e9e40",
"MacAddress": "02:42:ac:1a:00:03",
"IPv4Address": "172.26.0.3/16",
"IPv6Address": ""
},
"364f873d069e4ecd371cdd99ca952d1469ee875aacbf9ee2227bbf25ab65d841": {
"Name": "com.frcyber.sensei.api",
"EndpointID": "e5a3f4cd2099aff2a04efdeb7a5c5d0a8ade4248b76df048f20a8a75bf85ddba",
"MacAddress": "02:42:ac:1a:00:04",
"IPv4Address": "172.26.0.4/16",
"IPv6Address": ""
},
"f4bfaf323a8c8c6300156d3091ec70f091fc3492175bfa00faa1717e4f83d2a2": {
"Name": "com.frcyber.sensei.mongodb",
"EndpointID": "b5df4e0d3721ffe5cd28ce55f642e6a0bc7f5be1a12cc49bb2eb12a58eb82e7a",
"MacAddress": "02:42:ac:1a:00:02",
"IPv4Address": "172.26.0.2/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {
"com.docker.compose.network": "default",
"com.docker.compose.project": "staging-sensei-api",
"com.docker.compose.version": "1.24.0"
}
}
]
另外,我發現它在以下情況下有效API_連接埠設定為 5000:
api:
ports: 5000:5000
答案1
考慮到它在特定情況下工作,即:
另外,我發現當 API_PORT 設定為 5000 時它可以工作
api: ports: 5000:5000
我建議問題不在於 docker 端,而是您如何設定專案。這個建議基於我的假設:您的 db-seeder 容器使用 inAPI_PORT
作為其連接埠來連接到 api 容器(您的貼文中沒有明確定義,我假設它適用於以下內容)。
由於您的 python 錯誤顯示"api"
為主機,因此您正在嘗試連接到,根據您的輸出,從 DNS 角度來看,這相當於 IP 172.26.0.4 docker network inspect
。在此 IP 上,容器正在偵聽連接埠 5000,無論 的API_PORT
值為何(根據您的 docker-compose,因為您始終將主機的連接API_PORT
埠綁定到容器的 5000)。
奇怪的是,你之前說過它有效,但事實不應該是這樣,除非你有API_PORT
5000。
如果您想在 docker 網路內部的另一個連接埠上進行連接,則需要在建置或執行時間變更容器中的某些內容,而不僅僅是您綁定到的主機連接埠。
新增:「可配置性」的範例
從你的docker-compose
version: '3'
services:
api:
image: <API image>
ports: "80:${API_PORT:-5000}" //Flask's default port
depends_on:
- db
environment:
- DB_PORT=${DB_PORT:-27017}
- API_PORT=${API_PORT:-5000}
db:
image: mongo:latest
command: --port ${DB_PORT:-27017}
db-seed:
image: <seeder image>
environment:
- API_PORT=${API_PORT:5000}
這不會將您的資料庫連接埠暴露給主機外部。您需要從 shell 環境(或 .env 檔案)中擷取 API_PORT 和 DB_PORT 值,並以下列方式使用它們:
- 使用以下方式連接到 api
http(s)://api:$API_PORT
- 使用以下命令連接到 mongo
db:$DB_PORT
- 使用 API_PORT啟動您在生產中用於 api 的 cgi 伺服器(例如
uwsgi
),例如在 api 容器腳本的末尾ENTRYPOINT
:
# Some other config / checks / setup at runtime
exec uwsgi --port "$API_PORT" [ OTHER_OPTIONS ... ] path/to/your/application.py