Artigos

Como estabelecer a comunicação entre contêineres e a máquina host

Docker é excelente. Todos sabemos que os contêineres ajudam a simplificar e automatizar o desenvolvimento e a configuração do ambiente de uma aplicação. Vamos explorar como estabelecer a comunicação entre contêineres e de seu interior para a máquina host.

Primeiro, vamos oferecer um pouco de contexto. Para entender como o processo de comunicação funciona, precisamos esclarecer alguns conceitos.

Rede do Docker

Quando você lista as redes depois de uma instalação tradicional do Docker e executa o comando docker network ls...

$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
dbb52b9c258f        bridge              bridge              local
0c35ae96fe77        host                host                local
cb85dfadb376        local_default       bridge              local
94431f37b012        none                null                local

...pode obter as redes integradas padrão:

  • Bridge
  • Host
  • None

Nota: como você provavelmente percebeu, há outra chamada local_default, que neste caso é uma rede bridge definida pelo usuário.

Um breve resumo extraído da documentação atual do Docker explica:

Rede bridge: o driver de rede padrão. Se você não especificar um driver, esse é o tipo de rede que está criando. As redes bridge costumam ser usadas quando suas aplicações são executadas em contêineres independentes que precisam se comunicar

Rede host: adiciona um contêiner à pilha de rede do host. Do ponto de vista da rede, não há isolamento entre a máquina host e o contêiner. Por exemplo, se você executar um contêiner com um servidor web na porta 80 usando a rede host, o servidor estará disponível na porta 80 da máquina host.

Rede none: geralmente é conhecida como uma rede específica do contêiner. Um contêiner pode ser conectado a uma rede none. Isso permite a comunicação interna entre contêineres isolados de redes externas. 1

Portanto, a rede responsável pela comunicação entre contêineres é, por padrão, a rede bridge ou as redes bridge definidas pelo usuário. Vamos nos concentrar nesse tipo de rede.

Redes bridge

$ ifconfig bridge0
bridge0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
  options=63<RXCSUM,TXCSUM,TSO4,TSO6>
  ether 82:17:02:be:ed:00
  Configuration:
    id 0:0:0:0:0:0 priority 0 hellotime 0 fwddelay 0
    maxage 0 holdcnt 0 proto stp maxaddr 100 timeout 1200
    root id 0:0:0:0:0:0 priority 0 ifcost 0 port 0
    ipfilter disabled flags 0x2
  member: en1 flags=3<LEARNING,DISCOVER>
          ifmaxaddr 0 port 5 priority 0 path cost 0
  member: en2 flags=3<LEARNING,DISCOVER>
          ifmaxaddr 0 port 6 priority 0 path cost 0
  Address cache:
  nd6 options=201<PERFORMNUD,DAD>
  media: <unknown type>
  status: inactive

Quando você inicia o Docker, uma rede bridge padrão, também chamada bridge0 ou docker0, é criada automaticamente, e os contêineres recém-iniciados se conectam a ela, a menos que seja especificado o contrário. Você também pode criar redes bridge personalizadas definidas pelo usuário. Elas são superiores à rede bridge padrão.

No Docker, uma rede bridge usa uma ponte de software que permite a comunicação entre contêineres conectados à mesma rede bridge, isolando-os dos contêineres que não estão conectados a ela. O driver bridge do Docker instala automaticamente regras na máquina host para que contêineres em diferentes redes bridge não possam se comunicar diretamente.

A comunicação só seria estabelecida se a rede bridge fosse fornecida e as permissões adequadas fossem concedidas nas regras do iptables.

Ping entre contêineres

Para entender a comunicação entre contêineres, vamos criar dois contêineres na mesma rede e verificar se conseguem se enxergar usando um comando ping.

  • Crie dois contêineres.
$ docker run -d --name nginx1  -p 8001:80 nginx:latest
$ docker run -d --name nginx2  -p 8002:80 nginx:latest
  • Crie uma rede personalizada.
$ docker network create my-custom-net
$ docker network inspect my-custom-net
  • Liste as redes. Você deve ver uma nova rede do tipo bridge.
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
dbb52b9c258f        bridge              bridge              local
0c35ae96fe77        host                host                local
cb85dfadb376        my-custom-net       bridge              local
94431f37b012        none                null                local
  • Conecte a rede aos contêineres.

docker network connect my-custom-net nginx1

docker network connect my-custom-net nginx2

  • Inspecione a rede. Você deve ver os contêineres conectados a ela.
$ docker network inspect my-custom-net
[
    {
        "Name": "my-custom-net",
        "Id": "cb85dfadb376cc7aa020410ee6c839137b6d5dedff7972b9eed0e37ec573b002",
        "Created": "2020-04-09T20:26:42.897203Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "172.19.0.0/16",
                    "Gateway": "172.19.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {},
        "Labels": {}
    }
]
  • Antes de tentar fazer ping, instale iputils-ping no contêiner para que funcione. Para isso, entramos no contêiner chamado nginx1.
$ docker exec -ti nginx1 bash
root@39484307e6ee:/# apt update
root@39484307e6ee:/# apt install iputils-ping
  • Você já pode executar um comando ping.
docker exec -ti nginx1 ping nginx2
PING nginx2 (172.18.0.3) 56(84) bytes of data.
64 bytes from nginx2.my-custom-net (172.18.0.3): icmp_seq=1 ttl=64 time=0.224 ms
64 bytes from nginx2.my-custom-net (172.18.0.3): icmp_seq=2 ttl=64 time=0.093 ms
64 bytes from nginx2.my-custom-net (172.18.0.3): icmp_seq=3 ttl=64 time=0.082 ms
64 bytes from nginx2.my-custom-net (172.18.0.3): icmp_seq=4 ttl=64 time=0.081 ms

Como conectar o contêiner a um serviço dentro da máquina host

O Docker permite acessar o host a partir dos contêineres por meio de um DNS especial chamado host.docker.internal.

Você pode executar ping dentro do contêiner nginx1. Receberá uma resposta com o IP atual da sua máquina host

root@39484307e6ee:/# ping host.docker.internal


Em resumo, entendemos melhor como as redes bridge do Docker facilitam a comunicação entre contêineres da mesma rede. Se necessário, podemos conectar os contêineres a qualquer serviço do host usando o nome especial host.docker.internal.


  1. "Visão geral das redes," Documentação do Docker. ↩

“Como estabelecer a comunicação entre contêineres e a máquina host” por Cesar Diaz está sob a licença CC BY SA. Os exemplos de código-fonte estão sob a licença MIT.

Foto de Miryam León.

Classificado em Pesquisa e aprendizado.

Leituras relacionadas