O contêiner do Docker não pode se conectar a outro usando uma rede docker

O contêiner do Docker não pode se conectar a outro usando uma rede docker

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_PORTcomo 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 inspectsaída. Neste IP, o contêiner está escutando na porta 5000, independente do API_PORTvalor 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_PORT5.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 usandohttp(s)://api:$API_PORT
  • conecte-se ao mongo usandodb:$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 do ENTRYPOINTscript 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

informação relacionada