Eu uso o docker-compose para configurar uma API com alguns bancos de dados e um semeador. Tudo funcionou perfeitamente até alguns dias atrás, mas agora não consigo mais semear o banco de dados.
Aqui está um exemplo do meudocker-compose.ymlarquivo:
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
A semeadora usa orede dockerpara acessar o contêiner da API (http://api:80/) e semeie-o. No entanto, o script do semeador (escrito em Python) agora retorna um erro ao conectar-se ao contêiner da 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'))
Parece que o contêiner semeador não consegue acessar o contêiner do banco de dados. Qual poderia ser a causa deste erro? Como eu poderia consertar isso?
Aqui está oinspeção de rede dockerda minha rede:
[{ "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"
}
}
]
Além disso, descobri que funciona quandoAPI_PORTestá definido como 5000:
api:
ports: 5000:5000
Responder1
Considerando que funciona em um caso específico, ou seja:
Além disso, descobri que funciona quando API_PORT está definido como 5000
api: ports: 5000:5000
Eu sugiro que o problema não esteja no lado do docker, mas em como você configura seu projeto. Esta sugestão é baseada em uma suposição de minha parte: seu contêiner db-seeder usa o valor in API_PORT
como sua porta para se conectar ao contêiner da API (não claramente definido em sua postagem, presumo que sim para o seguinte).
Como o seu erro python aparece "api"
como o host ao qual você está tentando se conectar, em termos de DNS, isso seria equivalente ao IP 172.26.0.4, de acordo com sua docker network inspect
saída. Neste IP, o contêiner está escutando na porta 5000, independente do API_PORT
valor de (de acordo com o seu docker-compose, já que você sempre vincula a porta do seu host API_PORT
à 5000 do contêiner).
O estranho é que você disse que funcionava antes, o que não deveria ter acontecido, exceto se você tivesse API_PORT
5.000.
Se quiser se conectar dentro da rede docker em outra porta, você precisará alterar algo no contêiner, seja na compilação ou no tempo de execução, não apenas na porta do host à qual você está vinculado.
Adição: exemplo de "configurabilidade"
De você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}
Isso não expõe sua porta db para fora do seu host. Você precisará recuperar os valores API_PORT e DB_PORT do ambiente do seu shell (ou arquivo .env) e usá-los da seguinte maneira:
- conectar-se à API usando
http(s)://api:$API_PORT
- conecte-se ao mongo usando
db:$DB_PORT
- inicie o servidor cgi que você usa para sua API em produção (exemplo para
uwsgi
) usando API_PORT, por exemplo, no final doENTRYPOINT
script do seu contêiner de API:
# Some other config / checks / setup at runtime
exec uwsgi --port "$API_PORT" [ OTHER_OPTIONS ... ] path/to/your/application.py