Olá! Vamos continuar nossa jornada com o Docker Compose.
Introdução
Na lição anterior, você aprendeu a definir uma aplicação com múltiplos serviços usando um único arquivo docker-compose.yml. Vimos como o Docker Compose simplifica a orquestração ao criar uma rede padrão, permitindo que os serviços se comuniquem usando seus nomes como hostnames.
Embora a rede padrão seja conveniente, ela oferece um controle limitado. Da mesma forma, embora saibamos que os volumes são essenciais para a persistência de dados (como você concluiu na lição anterior sobre armazenamento), a maneira como os integramos em nosso fluxo de trabalho pode ser otimizada.
Nesta lição, vamos aprofundar nosso controle sobre o ecossistema da aplicação. Você aprenderá a integrar redes customizadas e volumes nomeados diretamente no seu arquivo docker-compose.yml. O objetivo é tornar a definição da sua aplicação mais explícita, organizada e robusta. Isso alinha-se perfeitamente com o objetivo de entender "como as coisas funcionam" por baixo dos panos, em vez de apenas seguir receitas.
Gerenciando a Comunicação com Redes Customizadas
Por padrão, docker-compose up cria uma única rede bridge e conecta todos os serviços a ela. Isso é suficiente para muitas aplicações, mas em cenários mais complexos, talvez você queira mais controle.
Por que usar uma rede customizada?
- Isolamento: Você pode criar múltiplas redes e conectar seletivamente os serviços a elas. Por exemplo, em uma aplicação com um frontend, um backend e um banco de dados, você poderia ter uma rede
frontend-networke umabackend-network. O backend poderia se conectar a ambas, mas o banco de dados só se conectaria àbackend-network, impedindo qualquer acesso direto do frontend. Esse princípio de isolamento é análogo ao uso de VLANs ou sub-redes para segmentar o tráfego, um conceito que você deve conhecer de seus estudos de rede. - Organização: Nomear suas redes (ex:
api-network,data-network) torna sua configuração mais legível e auto-documentada. - Conexão com Contêineres Externos: Permite que seus serviços do Compose se conectem a contêineres que não são gerenciados pelo mesmo arquivo
docker-compose.yml.

Definindo e Usando Redes no docker-compose.yml
Para usar redes customizadas, você as declara em uma seção networks no nível superior do seu arquivo e, em seguida, as atribui a cada serviço.
Primeiro, assista a este vídeo para entender o conceito de redes definidas pelo usuário e seus benefícios. Embora os comandos sejam da CLI do Docker, os princípios de isolamento e DNS por nome são os mesmos que o Docker Compose aplica.
Docker networking is CRAZY!! (you NEED to learn it)
Para entender por que as redes customizadas são a prática recomendada, assista a este segmento do vídeo "Docker networking is CRAZY!!" do canal NetworkChuck. Ele demonstra claramente os benefícios de isolamento e a resolução de DNS por nome de contêiner que as redes definidas pelo usuário oferecem em comparação com a rede bridge padrão.
Assista do timestamp 10:22 a 13:13. Foque em por que o Docker recomenda o uso de redes definidas pelo usuário ('user-defined bridge') e o benefício da resolução de DNS pelo nome do contêiner, que não está disponível da mesma forma na rede padrão.
Agora que você viu o "porquê", vamos ver o "como" no Docker Compose. A leitura a seguir detalha a sintaxe e a aplicação.
A Deep Dive into Docker Compose
Este artigo, "A Deep Dive into Docker Compose", tem uma excelente seção sobre redes. Ele mostra como definir redes customizadas e atribuí-las a serviços para controlar a comunicação.
No artigo, leia as seguintes partes: a breve introdução à chave networks no início; a subseção Networks sob Configuring Services; e a seção inteira Networking in Docker Compose. Preste atenção especial em como criar uma rede customizada e atribuir serviços a ela.
Resumindo a sintaxe:
version: '3.8'
services:
webapi:
build: .
ports:
- "8080:80"
networks: # Atribui este serviço à rede 'backend'
- backend
database:
image: postgres:16-alpine
networks: # Atribui este serviço também à rede 'backend'
- backend
# Declaração das redes no nível superior
networks:
backend:
driver: bridge # Especifica o driver de rede. 'bridge' é o mais comum.
Neste exemplo, webapi e database podem se comunicar porque ambos estão na rede backend. Se tivéssemos outro serviço em uma rede diferente (ou em nenhuma rede customizada), ele não conseguiria se comunicar com eles.
Gerenciando a Persistência de Dados com Volumes Nomeados
Na lição anterior, você viu como o Docker Compose pode montar volumes, mas não declaramos o volume em si. Agora vamos dar o próximo passo: definir e gerenciar volumes nomeados dentro do próprio arquivo docker-compose.yml.
Por que declarar volumes no docker-compose.yml?
Assim como nas redes, declarar volumes torna sua stack de aplicação auto-contida e declarativa. Em vez de precisar executar docker volume create my-volume separadamente, o docker-compose up cuidará da criação do volume para você. Isso garante que qualquer pessoa que execute sua aplicação terá o ambiente de persistência correto, sem passos manuais.
Para uma rápida recapitulação visual de como os volumes funcionam e como são definidos no Compose, assista a este segmento.
Docker Volumes explained in 6 minutes
O vídeo "Docker Volumes explained in 6 minutes" do canal TechWorld with Nana explica de forma concisa o que são volumes e como usá-los no Docker Compose.
Assista do timestamp 02:08 a 05:36. Foque na distinção entre os tipos de volume e, principalmente, em como os volumes nomeados (named volumes) são definidos e referenciados em um arquivo docker-compose.yml.
Definindo e Usando Volumes no docker-compose.yml
A sintaxe é semelhante à das redes: uma declaração no nível superior e uma referência dentro do serviço.
version: '3.8'
services:
database:
image: postgres:16-alpine
environment:
# ... credenciais do banco de dados ...
volumes:
# Mapeia o volume nomeado 'postgres-data' para o diretório de dados do Postgres
- postgres-data:/var/lib/postgresql/data
# Declaração dos volumes no nível superior
volumes:
postgres-data:
driver: local # 'local' é o driver padrão, que armazena os dados no host do Docker.
Com esta configuração:
- Quando você executar
docker-compose up, o Docker verificará se um volume chamadopostgres-data(com escopo para este projeto) existe. Se não existir, ele o criará. - O contêiner
databaseserá iniciado com este volume montado. - Se você executar
docker-compose down(sem-v), os contêineres serão removidos, mas o volumepostgres-datae seus dados persistirão. - Na próxima vez que você executar
docker-compose up, o contêinerdatabaseserá recriado e o mesmo volume será montado novamente, restaurando o estado anterior do seu banco de dados.
Para um aprofundamento textual, o artigo que você já consultou sobre redes também possui uma excelente seção sobre volumes.
A Deep Dive into Docker Compose
Para complementar o vídeo, leia a seção sobre volumes no artigo "A Deep Dive into Docker Compose". Ele aborda a definição, o anexo a serviços e a diferença em relação aos bind mounts.
Leia as seções Volumes (a introdução inicial), Volumes and Persistent Storage in Docker Compose e a subseção Use Named Volumes for Data Persistence. Isso solidificará sua compreensão da sintaxe e das melhores práticas.
Teste seu entendimento!
Você tem um docker-compose.yml com dois serviços, api e database, ambos na rede app-net. Você também tem um serviço de logging de terceiros chamado log-collector que deve receber logs da api, mas não deve ter acesso ao database.
Como você modificaria as definições de rede para impor essa regra?
Show answer
Você criaria duas redes customizadas, por exemplo, data-net e log-net.
- O serviço
databaseseria conectado apenas àdata-net. - O serviço
log-collectorseria conectado apenas àlog-net. - O serviço
apiseria conectado a ambas as redes,data-netelog-net, permitindo que ele se comunique tanto com o banco de dados quanto com o coletor de logs.
services:
api:
# ...
networks:
- data-net
- log-net
database:
# ...
networks:
- data-net
log-collector:
# ...
networks:
- log-net
networks:
data-net:
log-net:
Exemplo Prático: API .NET com PostgreSQL
Agora, vamos unir tudo em um exemplo prático e completo, perfeitamente alinhado com seu background e objetivos. O artigo a seguir mostra como configurar uma API .NET com um banco de dados PostgreSQL, usando um docker-compose.yml que define explicitamente a rede e o volume.
Custom Web Portal Starter Kit: Setting Up PostgreSQL with Docker Compose
O artigo "Custom Web Portal Starter Kit: Setting Up PostgreSQL with Docker Compose" fornece um exemplo real e bem explicado de um arquivo docker-compose.yml que utiliza os conceitos que acabamos de discutir.
Analise o arquivo docker-compose.yml completo na seção 'Creating the Docker Compose File'. Em seguida, leia as explicações detalhadas para 'PostgreSQL Service' e 'API Service'. Preste atenção especial em como as chaves volumes e networks são usadas nos serviços. Por fim, leia a seção 'What Happens When You Run This Command' e 'Accessing Your Services' para entender como o Compose orquestra a criação dos recursos e a comunicação entre eles.
Analisando o arquivo do artigo, podemos ver a implementação clara dos nossos conceitos:
version: '3.8'
services:
postgres:
# ... (definições de imagem, environment, etc.)
volumes:
# Referencia o volume nomeado 'postgres-data'
- postgres-data:/var/lib/postgresql/data
networks:
# Conecta o serviço à rede 'portal-network'
- portal-network
# ...
api:
# ... (definições de build, environment, etc.)
depends_on:
postgres:
condition: service_healthy
networks:
# Conecta a API à mesma rede 'portal-network'
- portal-network
# ...
# Definição do volume nomeado no nível superior
volumes:
postgres-data:
driver: local
# Definição da rede customizada no nível superior
networks:
portal-network:
driver: bridge
Este exemplo demonstra o padrão ideal:
- A persistência dos dados do PostgreSQL é gerenciada pelo volume nomeado
postgres-data. - A comunicação entre a
apie opostgresé habilitada e isolada pela rede customizadaportal-network. - A string de conexão da API usará
Host=postgresporque ambos estão na mesma rede e o Docker Compose fornece a resolução de DNS.
Conclusão
Parabéns por concluir esta lição! Você agora tem o conhecimento para criar arquivos docker-compose.yml que não apenas funcionam, mas são robustos, organizados e seguem as melhores práticas da indústria.
Principais Pontos:
- Redes Customizadas (
networks): Permitem isolar e organizar a comunicação entre os serviços. São definidas no nível superior e atribuídas a cada serviço. - Volumes Nomeados (
volumes): São a maneira declarativa e preferida de gerenciar a persistência de dados no Docker Compose. Também são definidos no nível superior e montados em diretórios específicos dentro dos serviços. - Aplicação Auto-contida: Ao definir redes e volumes no
docker-compose.yml, toda a definição da sua aplicação (código, configuração, rede e armazenamento) vive em um único lugar, facilitando a portabilidade e a colaboração. - Ciclo de Vida: O comando
docker-compose upcria redes e volumes se eles não existirem, edocker-compose down -vé usado para remover tudo, incluindo os volumes de dados.
Na próxima lição, vamos explorar mais a fundo o gerenciamento do ciclo de vida da sua aplicação, mergulhando nos comandos docker-compose up, down, logs e outros utilitários essenciais para o dia a dia do desenvolvimento.