O docker é disponibilizado com três redes por padrão. Essas redes oferecem configurações específicas para gerenciamento do tráfego de dados. Para visualizar essas interfaces, basta utilizar o comando:
docker network ls
O retorno será:
Bridge
Cada container iniciado no docker é associado a uma rede específica. Essa é a rede padrão para qualquer container, a menos que associemos, explicitamente, outra rede a ele. Todos os containers que estão nessa rede poderão se comunicar via protocolo TCP/IP. Se você souber qual endereço IP do container deseja conectar, é possível enviar tráfego para ele. Todos estão na mesma rede IP (172.17.0.0/16).
Na versão 1.9 do Docker é possível criar basicamente dois tipos de rede: Bridge (forma tradicional, e acessível apenas de dentro do host), ou do tipo Overlay (que possibilita a comunicação entre outros hosts com Docker, possibilitando assim a criação de cluster de Docker).
Como os IPs são automaticamente cedidos, o docker facilmente consegue localizar o container de destino através da opção -link. Ela é responsável por associar o IP do container de destino ao seu nome. Caso inicie um container a partir de uma imagem docker do mysql com nome "bd", inicie outro em seguida com o nome "app" a partir da imagem tutum/apache-php. Se desejar que esse último container consiga conectar-se no mysql usando o nome "bd", inicie ambos os containers da seguinte forma:
docker container run -d --name bd -e MYSQL_ROOT_PASSWORD=minhasenha mysql
docker container run -d -p 80:80 --name app --link db tutum/apache-php
Após executá-los, o container "app" poderá se conectar ao container do mysql usando o nome "bd", sendo automaticamente resolvido para o IP da rede 172.17.0.0/16.
A fim de testes, utilize a funcionalidade exec para rodar o comando dentro de um container já existente, use o nome do container como parâmetro do comando abaixo:
docker container exec -it app ping db
Essa ação é responsável por executar o comando "ping db" dentro do container "app", o qual enviará pacotes icmp, normalmente usado para testar conectividade entre hosts, para o endereço "db". O nome "db" será traduzido para o IP que o container iniciado a partir da imagem o mysql obteve.
Os containers configurados para essa rede terão a possibilidade de tráfego externo utilizando as rotas das redes IP definidas no docker host. Caso o docker host tenha acesso a internet, automaticamente, os containers em questão também terão. Nessa rede é possível expor portas dos containers para todos os ativos com acesso ao docker host.
Redes quando definidas pelo usuário
O docker possibilita que o usuário crie redes. Essas redes são associadas ao elemento que o docker chama de driver de rede. Cada rede criada por usuário deve estar associada a um determinado driver. E, caso você não crie seu próprio driver, deve escolher entre os drivers disponibilizados pelo docker:
Bridge
É o driver de rede mais simples de usar, demanda pouca configuração e a rede assemelha-se à rede padrão docker "bridge". As redes criadas pelo usuário com o driver bridge tem todas as funcionalidades descritas na rede padrão, chamada bridge. Porém, com funcionalidades adicionais. Dentre uma das funcionalidades: a rede criada pelo usuário não precisa mais utilizar a opção antiga “–link”. Pois, toda rede criada pelo usuário com o driver bridge poderá utilizar o DNS interno do Docker que, associa, automaticamente, todos os nomes de containers dessa rede para seus respectivos IPs da rede IP correspondente.
Todos os containers que estiverem utilizando a rede padrão bridge não poderão usufruir da funcionalidade de DNS interno do Docker. Caso utilize essa rede, é preciso especificar a opção legada “–link” para tradução dos nomes em endereços IPs dinamicamente alocados no docker.
Para exemplificar a utilização de rede criada por usuário, crie a rede chamada isolated_nw com o driver bridge:
docker network create --driver bridge isolated_nw
Agora, verifique a rede:
docker network list/p>
O resultado deve ser:
Agora, inicie um container na rede isolated_nw:
docker container run -itd --net isolated_nw alpine sh
Lembrando que: um container que está em determinada rede não acessa outro container que está em outra rede. Mesmo que você conheça o IP de destino. Para que um container acesse outro container de outra rede, é necessário que a origem esteja presente nas duas redes que deseja alcançar. Os containers que estão na rede isolated_nw podem expor suas portas no docker host e essas portas podem ser acessadas tanto por containers externos a rede, chamada isolated_nw, como máquinas externas com acesso ao docker host.
Para descobrir quais containers estão associados a uma determinada rede, execute o comando abaixo:
docker network inspect isolated_nw
O resultado deve ser:
Dentro de "Containers" verifica-se quais containers fazem parte dessa rede. Todos os containers que estiverem na mesma rede poderão se comunicar através de seus respectivos nomes. Como visto acima, caso um container novo acesse a rede isolated_nw, ele poderá acessar o container amazing_noyce usando apenas o seu nome.
Utilizando redes no docker composer
Por padrão, o Compose já cria uma única rede para o seu aplicativo. Cada container entra na rede padrão e é tanto alcançável para os outros containers nessa mesma rede, quanto detectável por eles com um hostname idêntico ao nome do container. O nome da rede é dado baseado no "nome do projeto", que é baseado no nome do diretório em que está inserido. É possível dar override no nome do projeto com a flag --project-name ou a variável COMPOSE_PROJECT_NAME.
Digamos que o seu aplicativo esteja em um diretório chamado meuapp, e o seu docker-compose.yml esteja parecido com isso:
services:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
ports:
- "8001:5432"
Quando você roda docker compose up, acontece o seguinte:
1. Uma rede chamada meuapp_default é criada.
2. Um container é criado usando a configuração de web. Ele entra na rede meuapp_default com o nome web.
3. Um container é criado usando a configuração de db. Ele entra na rede meuapp_default com o nome db.
Cada container pode, agora, pesquisar o hostname web ou db e retornar o endereço IP do respectivo container. Por exemplo, o código de aplicação de web pode conectar à URL postgres://db:5432 e começar a usar o banco dados Postgres.
É importante notar a diferença entre HOST_PORT e CONTAINER_PORT. No exemplo acima, para db, HOST_PORT é 8001 e a port do container é 5432 (padrão postgres). A comunicação entre serviços de rede usa CONTAINER_PORT. Quando HOST_PORT é definida, o serviço é acessível externamente também.
Vincular containers
Vínculos permitem definir apelidos extras pelos quais um serviço é alcançável por outro. Eles não são necessários para habilitar a comunicação de serviços. Por padrão, qualquer serviço pode alcançar outro com aquele nome do serviço. Por exemplo, db é alcançável por web nos hostnames db e database:
services:
web:
build: .
links:
- "db:database"
db:
image: postgres
Redes com múltiplos hosts
Quando estamos usando uma aplicação Compose em uma engine Docker com o modo Swarm (recurso para gerenciar um cluster de Docker daemons) habilitado, é possível usar o driver overlay já incluído para habilitar a comunicação entre múltiplos hosts.
Redes overlay sempre são criadas como attachable, ou seja, que é possível separar um container privilegiado e ainda continuar a comunicação. É possível, opcionalmente, colocar a propriedade attachable como falsa.
Especificar redes personalizadas
Ao invés de apenas usar a rede padrão, você pode especificar a sua própria rede usando a chave de networks de alto nível. Isso permite a criação de topologias mais complexas e especificar drivers de rede personalizados. Também é possível usá-la para conectar serviços a redes criadas externamente que não são gerenciadas pelo Compose.
Cada serviço pode especificar a quais redes quer se conectar com a chave de networks de nível de serviço, que é uma lista de nomes referenciando entradas através chave de redes de alto nível.
O exemplo a seguir mostra um arquivo Compose que define ruas redes personalizadas. O serviço proxy é isolado do serviço db pois eles não têm uma rede em comum. Apenas app pode comunicar com ambos.
services:
proxy:
build: ./proxy
networks:
- frontend
app:
build: ./app
networks:
- frontend
- backend
db:
image: postgres
networks:
- backend
networks:
frontend:
# Use um driver personalizado
driver: driver-personalizado-1
backend:
# Use um driver personalizado que leva opções especiais
driver: driver-personalizado-2
driver_opts:
foo: "1"
bar: "2"
Redes podem ser configuradas com endereços de IP estáticos colocando o endereço ipv4 e/ou ipv6 para cada rede vinculada.
Redes também podem ter um nome personalizado:
services:
# ...
networks:
frontend:
name: frontend_personalizado
driver: driver-personalizado-1
Configurar a rede padrão
Ao invés de especificar as suas próprias redes, também podemos mudar as configurações da rede padrão do aplicativo definindo uma entrada networks chamada default:
services:
web:
build: .
ports:
- "8000:8000"
db:
image: postgres
networks:
default:
# Use um driver personalizado: .
driver: driver-personalizado-1
Usando uma rede já existente
Se você quer que seus containers entrem em uma rede já existente, use a opção external.
services:
# ...
networks:
network1:
name: minha-rede-existente
external: true
Ao invés de tentar criar uma rede chamada [nomeprojeto]_default, o Compose procura por uma rede chamada minha-rede-existente e conecta os containers do seu app a ela.