Olá! Bem-vindo de volta.
Introdução
Na lição anterior, você aprendeu a gerenciar o ciclo de vida de uma aplicação multi-contêiner usando os comandos docker-compose up, down, e logs. Agora que você sabe como orquestrar seus serviços, o próximo passo lógico é aprender a configurá-los de forma flexível e segura.
Nesta lição, vamos nos concentrar em como fornecer variáveis de ambiente para seus serviços usando a chave environment e arquivos .env no Docker Compose. Este é um conceito fundamental no desenvolvimento de software moderno, pois permite desacoplar a configuração da sua aplicação do código e da imagem do contêiner. Para você, como desenvolvedor .NET, isso se alinha perfeitamente com a forma como o ASP.NET Core gerencia a configuração, lendo valores de fontes como arquivos appsettings.json e, crucialmente, variáveis de ambiente.
Ao final desta lição, você será capaz de construir aplicações Docker Compose que podem ser facilmente adaptadas para diferentes ambientes (desenvolvimento, teste, produção) simplesmente alterando a configuração, sem precisar reconstruir nenhuma imagem.
Por que Usar Variáveis de Ambiente?
Imagine que você tem uma API .NET que precisa de uma string de conexão para se comunicar com um banco de dados PostgreSQL. Uma abordagem ingênua seria colocar essa string de conexão diretamente no seu arquivo appsettings.json e copiá-la para a imagem Docker. O problema? Se você precisar apontar para um banco de dados diferente (por exemplo, de produção), terá que modificar o arquivo e reconstruir a imagem. Isso é ineficiente e viola o princípio de construir um artefato (a imagem Docker) que pode ser promovido através de diferentes ambientes.
As variáveis de ambiente resolvem isso. Elas permitem que você injete valores de configuração em um contêiner no momento em que ele é executado.
A imagem a seguir ilustra esse fluxo: a configuração é mantida fora do contêiner (em arquivos .env ou no seu shell) e o Docker Compose a injeta no ambiente do contêiner durante a inicialização.

Métodos para Fornecer Variáveis de Ambiente
O Docker Compose oferece várias maneiras de gerenciar variáveis de ambiente, cada uma com seu caso de uso específico.
1. A Chave environment
A maneira mais direta de definir uma variável de ambiente é usando a chave environment diretamente no serviço dentro do seu arquivo docker-compose.yml.
Você pode usar uma sintaxe de mapa (chave-valor) ou uma lista.
Sintaxe de Mapa:
services:
webapi:
image: my-aspnet-api
environment:
ASPNETCORE_ENVIRONMENT: "Development"
Logging__LogLevel__Default: "Information"
Sintaxe de Lista:
services:
webapi:
image: my-aspnet-api
environment:
- ASPNETCORE_ENVIRONMENT=Development
- Logging__LogLevel__Default=Information
Ambas as formas são equivalentes. A sintaxe de mapa costuma ser mais legível.
A documentação oficial do Docker oferece uma explicação concisa sobre o uso da chave environment. Recomendo a leitura para solidificar o conceito.
Leia a seção "Use the environment attribute". Preste atenção às duas sintaxes (mapa e lista) e como você pode usar a interpolação de variáveis, que veremos a seguir.
2. Arquivos .env para Externalizar a Configuração
Embora a chave environment seja útil, colocar valores sensíveis (como senhas de banco de dados) ou valores que mudam com frequência diretamente no docker-compose.yml não é uma boa prática. A melhor abordagem é externalizar esses valores para arquivos de ambiente.
a) O Arquivo Padrão .env
Por padrão, quando você executa docker-compose up, o Docker Compose procura por um arquivo chamado .env no mesmo diretório do seu docker-compose.yml. As variáveis definidas neste arquivo ficam disponíveis para substituição de variáveis dentro do próprio docker-compose.yml.
Crie um arquivo .env (observe o ponto no início):
# .env
TAG=1.0.0
WEB_PORT=8080
Agora, você pode usar essas variáveis no seu docker-compose.yml:
# docker-compose.yml
services:
webapi:
image: my-aspnet-api:${TAG} # Substituição de variável
ports:
- "${WEB_PORT}:80"
Neste caso, o Docker Compose substituirá ${TAG} por 1.0.0 e ${WEB_PORT} por 8080 antes de executar o serviço. Isso é extremamente poderoso para parametrizar suas definições.
Docker Environment Variables: Best Practices and Examples
Para ver a substituição de variáveis em ação, assista a este vídeo do canal Code with Nevyan. Ele demonstra como usar um arquivo .env para customizar dinamicamente nomes de contêineres e versões de imagens.
Assista ao vídeo do início até 1:36 e depois de 2:59 a 3:36. Observe como as variáveis definidas no arquivo .env são usadas com a sintaxe ${VARIABLE} dentro do docker-compose.yml para configurar dinamicamente a versão da imagem, mapeamentos de volume e prefixos de nome de contêiner.
b) A Chave env_file
E se você quiser passar o conteúdo de um arquivo de ambiente diretamente para dentro de um contêiner? Para isso, usamos a chave env_file. Isso é ideal para agrupar todas as variáveis de ambiente de um serviço específico em um único arquivo.
Crie um arquivo, por exemplo, database.env:
# database.env
POSTGRES_USER=myuser
POSTGRES_PASSWORD=mysecretpassword
POSTGRES_DB=mydatabase
Importante: Adicione este arquivo ao seu .gitignore para não cometer credenciais ao seu repositório!
Agora, use env_file no seu serviço de banco de dados:
# docker-compose.yml
services:
db:
image: postgres:14
env_file:
- database.env
volumes:
- postgres-data:/var/lib/postgresql/data
volumes:
postgres-data:
Neste caso, o contêiner db será iniciado com as variáveis POSTGRES_USER, POSTGRES_PASSWORD, e POSTGRES_DB definidas em seu ambiente interno.
Docker Compose Tutorial for Beginners (Networks - Volumes - Secrets - Postgres - Letsencrypt)
O vídeo a seguir, do canal Anton Putra, demonstra claramente o uso da chave env_file para separar configurações e segredos do arquivo Compose principal.
Assista do timestamp 26:00 a 28:17. O vídeo mostra como mover uma variável hardcoded para um arquivo de ambiente e usar a diretiva env_file para injetá-la no contêiner. Note a ênfase em não cometer o arquivo de ambiente ao Git.
Juntando Tudo: Exemplo Prático com .NET API e PostgreSQL
Vamos combinar esses conceitos em um cenário que você, como desenvolvedor .NET, encontrará com frequência. Queremos configurar a string de conexão de uma API para se conectar a um banco de dados Postgres, ambos rodando como contêineres.
-
Crie o arquivo
database.envcom as credenciais do Postgres:# database.env POSTGRES_USER=myuser POSTGRES_PASSWORD=mysecretpassword POSTGRES_DB=mydatabase -
Crie o arquivo
.envpara variáveis de substituição:# .env API_PORT=5000 -
Crie o
docker-compose.yml:version: '3.8' services: db: image: postgres:14 env_file: - database.env # Injeta as variáveis do arquivo no contêiner 'db' volumes: - postgres-data:/var/lib/postgresql/data networks: - my-network webapi: image: my-aspnet-api:latest ports: - "${API_PORT}:80" # Substitui a porta a partir do .env environment: # A string de conexão é construída usando variáveis injetadas no contêiner 'db' # O framework de configuração do .NET Core entende o formato ConnectionStrings__DefaultConnection ConnectionStrings__DefaultConnection: "Server=db;Port=5432;Database=${POSTGRES_DB};User Id=${POSTGRES_USER};Password=${POSTGRES_PASSWORD};" networks: - my-network volumes: postgres-data: networks: my-network:
Análise do Exemplo:
- O serviço
dblê suas credenciais diretamente dodatabase.envatravés deenv_file. - As variáveis em
database.envtambém estão disponíveis para substituição nodocker-compose.yml. - O serviço
webapiusa a substituição de variáveis para definir sua string de conexão na seçãoenvironment. Ele constrói a string usando as variáveis definidas nodatabase.env. - O nome do host na string de conexão é
db, o nome do serviço Postgres. O Docker Compose fornece resolução DNS interna na rede customizada.
Ordem de Precedência
Uma pergunta natural é: o que acontece se uma variável for definida em vários lugares? Entender a ordem de precedência é fundamental para depurar configurações.
Use An .env File in Docker Compose
Este artigo do Warp.dev detalha excelentemente as várias maneiras de usar arquivos de ambiente e, mais importante, a ordem de precedência.
Leia as seções "Understanding the order of precedence of environment variables", "Passing environment variables to services", e "Passing .env files to services". Foque na lista de precedência e na nota sobre como variáveis na chave environment têm maior prioridade que as da env_file.
Resumindo a precedência, do mais alto para o mais baixo:
- Variáveis de ambiente definidas no seu shell (por exemplo, com
export VAR=valor). - Variáveis definidas na seção
environmentdo seudocker-compose.yml. - Variáveis definidas através da chave
env_file. - Variáveis definidas no arquivo
.envpadrão na raiz do projeto.
Isso significa que você pode definir valores padrão no seu .env, mas sobrescrevê-los para uma sessão específica exportando uma variável no seu terminal antes de rodar docker-compose up.
Teste seu entendimento!
Considere a seguinte configuração:
Arquivo .env:
LOG_LEVEL=INFO
Arquivo docker-compose.yml:
services:
api:
image: my-api
environment:
LOG_LEVEL: "DEBUG"
API_KEY: "${API_KEY_FROM_SHELL}"
Antes de executar docker-compose up, você digita o seguinte comando no seu terminal:export LOG_LEVEL=WARNexport API_KEY_FROM_SHELL=xyz123
Qual será o valor final da variável de ambiente LOG_LEVEL dentro do contêiner api? E o valor de API_KEY?
Show answer
-
LOG_LEVELserá "DEBUG". A variável definida diretamente na chaveenvironmentdodocker-compose.ymltem maior precedência sobre a variável do shell e a do arquivo.envpara o ambiente interno do contêiner. -
API_KEYserá "xyz123". Aqui, estamos lidando com substituição de variáveis. O valor de${API_KEY_FROM_SHELL}é resolvido pelo Docker Compose antes de criar o contêiner. A variável do shell (export ...) tem a maior precedência para substituição, então seu valor é usado.
Este exercício destaca a sutil, mas importante, diferença entre definir uma variável para substituição no Compose e definir uma variável para o ambiente interno do contêiner.
Conclusão
Parabéns! Você agora sabe como configurar seus serviços de forma robusta e flexível usando variáveis de ambiente no Docker Compose. Esta é uma habilidade crucial para criar aplicações portáteis que se adaptam a diferentes ambientes sem modificação do código ou da imagem.
Principais Pontos:
- Desacoplamento: Use variáveis de ambiente para separar a configuração (strings de conexão, chaves de API, portas) do seu código.
environment: A chave para definir variáveis diretamente nodocker-compose.yml. Útil para valores não sensíveis e específicos do serviço..enve Substituição: O arquivo.envna raiz do projeto é usado para substituição de variáveis (${VAR}) dentro dodocker-compose.yml, permitindo parametrizar suas definições.env_file: A chave para injetar todas as variáveis de um arquivo diretamente no ambiente de um contêiner. Ideal para agrupar configurações de um serviço.- Precedência: Entender a ordem em que as variáveis são aplicadas (Shell >
environment>env_file>.env) é essencial para a depuração.
Na próxima lição, abordaremos outro aspecto crucial da orquestração de serviços: controlar a ordem de inicialização e as dependências entre os serviços usando a propriedade depends_on. Isso garantirá, por exemplo, que seu banco de dados esteja pronto para aceitar conexões antes que sua API tente se conectar a ele.