Conteúdo
Tutorial de variáveis de ambiente no Docker: configure variáveis e arquivos .env
A mesma imagem pode precisar se conectar a bancos de dados diferentes e usar configurações diferentes nos ambientes de desenvolvimento, teste e produção. A forma mais comum de fazer isso é guardar essas configurações em variáveis de ambiente e passá-las ao executar o contêiner.
Configure com -e
$ docker run --rm -e NODE_ENV=production -e PORT=8080 alpine:3.23 sh -c "echo \$NODE_ENV \$PORT"
production 8080
$ export API_KEY=abc123 && docker run --rm -e API_KEY alpine:3.23 sh -c "echo API_KEY=\$API_KEY"
API_KEY=abc123
-e NOME=VALORdefine o valor diretamente.- Se você escrever apenas
-e NOME(sem valor), será usada a variável de ambiente de mesmo nome que estiver definida no host.
Leia um arquivo com --env-file
Quando há muitas variáveis, é difícil gerenciá-las na linha de comando. Coloque-as em um arquivo:
$ cat app.env
# app.env
NODE_ENV=production
PORT=8080
GREETING="hello world"
DATABASE_URL=postgres://app:secret@db:5432/app
$ docker run --rm --env-file app.env alpine:3.23 env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=e311730363f7
NODE_ENV=production
PORT=8080
GREETING="hello world"
DATABASE_URL=postgres://app:secret@db:5432/app
HOME=/root
Observe a linha GREETING: no arquivo está escrito "hello world", e o valor recebido pelo contêiner inclui as aspas. As regras de docker run --env-file são:
- Uma linha para cada
KEY=VALUE; linhas que começam com#são comentários. - Não coloque aspas nos valores; elas serão tratadas como parte do valor.
- Não há suporte à expansão de variáveis como
$OTHER_VAR.
(Como você verá a seguir, ao ler o mesmo arquivo, o Compose remove as aspas. O comportamento é diferente.)
Defina valores padrão no Dockerfile
ENV NODE_ENV=production \
PORT=3000
ENV define valores padrão, que podem ser substituídos por docker run -e. É adequado para configurações que "não mudam muito e não são confidenciais".
Ordem de precedência
Da maior para a menor prioridade:
docker run -edocker run --env-fileENVdo DockerfileENVda imagem base
As variáveis de ambiente ficam visíveis?
As variáveis de ambiente são práticas, mas não são seguras. Qualquer pessoa que possa executar docker inspect consegue vê-las:
$ docker run -d --name envdemo -e SECRET_TOKEN=abc123 alpine:3.23 sleep 60
431168d97dc8187ec79e420638155b2f53fd78a9d82f8a6d13eb6bd9aec09bcb
$ docker inspect --format '{{json .Config.Env}}' envdemo
["SECRET_TOKEN=abc123","PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]
$ docker rm -f envdemo
envdemo
Além disso, as variáveis de ambiente podem aparecer nos logs quando um programa falha, e os processos filhos também as herdam. Por isso, siga as recomendações em "Como lidar com dados confidenciais" ao usar senhas e chaves de API.
Variáveis de ambiente no Docker Compose
No Compose, há dois tipos de "variáveis de ambiente" que podem ser confundidos. Veja este exemplo. compose.yaml:
services:
app:
image: alpine:3.23
command: ["sh", "-c", "env | sort | grep -E 'APP_|DATABASE|NODE_ENV|PORT|GREETING'"]
environment:
APP_VERSION: ${APP_VERSION}
DATABASE_PASSWORD: ${DB_PASSWORD}
env_file:
- app.env
1. Variáveis passadas ao contêiner: environment e env_file
environment é escrito diretamente em compose.yaml; env_file lê um arquivo (neste caso, o app.env usado acima).
2. Variáveis que substituem valores em compose.yaml: .env
O Compose lê automaticamente o arquivo .env na pasta do projeto para substituir ${...} em compose.yaml. Com docker compose config, você pode ver a configuração final após a substituição:
$ cat .env
APP_VERSION=1.4.2
DB_PASSWORD=change-me
$ docker compose config app
name: ch15
services:
app:
command:
- sh
- -c
- env | sort | grep -E 'APP_|DATABASE|NODE_ENV|PORT|GREETING'
environment:
APP_VERSION: 1.4.2
DATABASE_PASSWORD: change-me
DATABASE_URL: postgres://app:secret@db:5432/app
GREETING: hello world
NODE_ENV: production
PORT: "8080"
image: alpine:3.23
networks:
default: null
networks:
default:
name: ch15_default
$ docker compose run --rm app
[+] run 1/1
✔ Network ch15_default Created 0.0s
Container ch15-app-run-dfbcf95b7271 Creating
Container ch15-app-run-dfbcf95b7271 Created
APP_VERSION=1.4.2
DATABASE_PASSWORD=change-me
DATABASE_URL=postgres://app:secret@db:5432/app
GREETING=hello world
NODE_ENV=production
PORT=8080
${APP_VERSION}e${DB_PASSWORD}foram substituídos pelos valores de.env.- Depois que o Compose lê
GREETING="hello world"emapp.env, o valor fica sem aspas, ao contrário dedocker run --env-file. - As aspas em
PORT: "8080"indicam que o valor é uma string (variáveis de ambiente são sempre strings).
O .env não é passado automaticamente ao contêiner; ele serve apenas para substituir valores em compose.yaml. Para passá-lo ao contêiner, você precisa referenciá-lo em environment (por exemplo, APP_VERSION: ${APP_VERSION}) ou usar env_file: .env.
Valores padrão e validação de campos obrigatórios
| Forma | Significado |
|---|---|
${VAR} | Substitui pelo valor de VAR |
${VAR:-valor-padrao} | Usa o valor padrão se a variável não estiver definida ou estiver vazia |
${VAR:?mensagem-de-erro} | Gera um erro se a variável não estiver definida ou estiver vazia |
${VAR:?} é útil para variáveis que precisam ser definidas, como senhas. Se você esquecer de defini-las, a execução será interrompida imediatamente, em vez de iniciar com uma senha vazia:
services:
db:
image: postgres:18
environment:
POSTGRES_PASSWORD: ${MISSING_PASSWORD:?Defina MISSING_PASSWORD em .env}
$ docker compose -f compose.required.yaml config
error while interpolating services.db.environment.POSTGRES_PASSWORD: required variable MISSING_PASSWORD is missing a value: Defina MISSING_PASSWORD em .env
Como lidar com dados confidenciais
- Não coloque senhas em
ENVouARGno Dockerfile; elas permanecerão na imagem (veja os testes deARGem Referência completa das instruções do Dockerfile). - Não envie
.envpara o Git. Adicione.envao.gitignoree forneça também um.env.examplesem valores reais. - Adicione
.envao.dockerignorepara evitar que ele seja incluído na imagem porCOPY . ..
Passe dados confidenciais em arquivos (Compose secrets)
Muitas imagens oficiais aceitam variáveis terminadas em _FILE para ler senhas de um arquivo:
services:
db:
image: postgres:18
environment:
POSTGRES_PASSWORD_FILE: /run/secrets/db_password
secrets:
- db_password
secrets:
db_password:
file: ./secrets/db_password.txt
$ docker compose up -d db
[+] up 1/1
✔ Container ch15-db-1 Started 0.3s
$ docker compose exec db sh -c "ls -l /run/secrets; cat /run/secrets/db_password; echo; env | grep POSTGRES"
total 4
-rw-rw-r-- 1 1001 1001 16 Oct 12 14:25 db_password
s3cret-from-file
POSTGRES_PASSWORD_FILE=/run/secrets/db_password
$ docker compose down
[+] down 2/2
✔ Container ch15-db-1 Removed 0.1s
✔ Network ch15_default Removed 0.1s
O conteúdo confidencial aparece como arquivo em /run/secrets/db_password no contêiner. A variável de ambiente contém apenas o caminho do arquivo, POSTGRES_PASSWORD_FILE; docker inspect não mostra a senha em si.
Dados confidenciais necessários durante o build
Por exemplo, se você precisa de um token para instalar um pacote privado, use uma montagem de secret do BuildKit:
# syntax=docker/dockerfile:1
RUN --mount=type=secret,id=npm_token \
NPM_TOKEN=$(cat /run/secrets/npm_token) npm ci
docker build --secret id=npm_token,env=NPM_TOKEN -t myapp .
O token só existe durante a execução desse RUN e não permanece em nenhuma camada.
Resumo
- Ordem de precedência:
-e/environment>--env-file/env_file>ENVdo Dockerfile. .envsubstitui${VAR}em compose.yaml e não é passado automaticamente ao contêiner.docker run --env-filenão remove aspas dos valores; o Compose remove.- Passe dados confidenciais em arquivos (secrets); não os coloque na imagem.
Exercícios
Exercício 1: A imagem define ENV MODE=prod. Se você executar docker run -e MODE=dev, qual será o valor de MODE no contêiner?
Resposta
dev. -e tem precedência sobre ENV do Dockerfile.
Exercício 2: Em compose.yaml, você define POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD is required}, mas .env não contém DB_PASSWORD. O que acontece ao executar docker compose up?
Resposta
O Compose gera um erro e interrompe a execução, mostrando DB_PASSWORD is required. O banco de dados não é criado com uma senha vazia.
Perguntas frequentes
As variáveis de ambiente do contêiner não mudaram depois que editei o .env. Por quê?
As variáveis de ambiente são definidas quando o contêiner é criado. Depois de editá-las, recrie o contêiner: no Compose, use docker compose up -d; restart não aplica as alterações.
Minha senha fica visível com docker inspect?
Sim. Os valores passados com -e aparecem em docker inspect. Para dados confidenciais, use arquivos (secrets).
Qual é a diferença entre ${VAR:-valor-padrao} e ${VAR:?mensagem}?
A primeira forma usa o valor padrão quando a variável não está definida; a segunda gera um erro e interrompe a execução se ela não estiver definida. É adequada para senhas obrigatórias, pois evita que fiquem vazias.
Atualizado 14 de outubro de 2026