Você está trabalhando com Docker em uma rede corporativa, em um servidor com acesso restrito ou deseja que seus contêineres acessem a internet através de um IP específico? Sem a configuração correta do proxy, o Docker simplesmente não conseguirá baixar imagens do Docker Hub ou de qualquer outro registro. Neste artigo, abordaremos todos os níveis de proxy — do daemon até um contêiner separado.
Por que o Docker precisa de um proxy
O Docker é uma ferramenta que constantemente acessa recursos externos. A cada docker pull ou docker build, o daemon acessa o Docker Hub, GitHub Container Registry, Google Container Registry ou seu registro privado. E é aqui que os problemas começam.
Situações em que um proxy é indispensável:
- Rede corporativa com firewall — todo o tráfego deve passar por um servidor proxy corporativo, caso contrário, a conexão é bloqueada.
- Geo-restrições — Docker Hub ou registros específicos não estão disponíveis em seu país ou data center.
- Servidor restrito sem acesso direto à internet — VPS em um circuito fechado, onde a internet está disponível apenas através de um gateway.
- Controle do tráfego de saída dos contêineres — você deseja que aplicativos dentro dos contêineres acessem a rede através de um IP específico, por exemplo, para scraping, chamadas de API ou testes de conteúdo geograficamente dependente.
- Anonimização de solicitações — ocultar o IP real do servidor ao acessar serviços externos a partir do contêiner.
- Rate limiting — Docker Hub limita o número de pull requests para usuários anônimos (100 pulls a cada 6 horas). Através de um proxy com rotação de IP, é possível contornar essa limitação.
É importante entender que o Docker não é um único aplicativo, mas um sistema composto por vários componentes. O daemon (dockerd) vive no host e faz pull de imagens. Os contêineres são processos isolados com suas próprias configurações de rede. Portanto, a configuração do proxy para o daemon e para os contêineres são duas tarefas diferentes que são resolvidas de maneiras distintas.
Três níveis de proxy no Docker
Antes de mexer nas configurações, é preciso entender a arquitetura. No Docker, existem três níveis independentes, cada um dos quais requer uma configuração de proxy separada:
| Nível | O que faz | Onde é configurado |
|---|---|---|
| Docker daemon | Baixa imagens (docker pull), acessa registros | substituição do systemd ou daemon.json |
| Docker build | Executa comandos durante a construção da imagem (RUN apt-get, pip install, etc.) | ARG e ENV no Dockerfile ou --build-arg |
| Contêiner em execução | Aplicativo em execução que faz solicitações HTTP | ENV ao executar docker run ou no docker-compose.yml |
Um erro comum é configurar o proxy apenas em um nível e se surpreender por que as imagens ainda não estão sendo baixadas ou o aplicativo não vê o proxy. Vamos analisar cada nível em detalhes.
Configuração de proxy para o Docker daemon (pull de imagens)
Esta é a configuração mais importante se você deseja baixar imagens através de um proxy. O Docker daemon é um serviço do sistema que é iniciado através do systemd. As variáveis de ambiente do seu usuário ou até mesmo do root não são visíveis para ele. É preciso passar o proxy exatamente para o ambiente do serviço.
Método 1: através da substituição do systemd (recomendado)
Crie um diretório para substituir as configurações do serviço:
sudo mkdir -p /etc/systemd/system/docker.service.d
Crie um arquivo /etc/systemd/system/docker.service.d/http-proxy.conf com o seguinte conteúdo:
[Service] Environment="HTTP_PROXY=http://username:password@proxy-host:port" Environment="HTTPS_PROXY=http://username:password@proxy-host:port" Environment="NO_PROXY=localhost,127.0.0.1,::1,your-private-registry.example.com"
Se o proxy não requer autenticação, basta remover username:password@. Após criar o arquivo, recarregue a configuração do systemd e reinicie o Docker:
sudo systemctl daemon-reload sudo systemctl restart docker
Verifique se as configurações foram aplicadas:
sudo systemctl show --property=Environment docker
Na saída, suas variáveis HTTP_PROXY e HTTPS_PROXY devem aparecer.
Método 2: através de ~/.docker/config.json (Docker Desktop e versões mais recentes)
A partir do Docker Engine 23.0, surgiu uma maneira mais conveniente — configurar o proxy através do arquivo de configuração do cliente. Crie ou edite o arquivo ~/.docker/config.json:
{
"proxies": {
"default": {
"httpProxy": "http://username:password@proxy-host:port",
"httpsProxy": "http://username:password@proxy-host:port",
"noProxy": "localhost,127.0.0.1,::1"
}
}
}
Este método é conveniente porque não requer privilégios de root e não precisa reiniciar o daemon. As configurações são automaticamente passadas para os contêineres durante a construção como argumentos de build. No entanto, para gerenciar as pull requests do próprio daemon, ainda é necessário o método através do systemd.
💡 Importante sobre NO_PROXY
Sempre adicione ao NO_PROXY os endereços dos seus registros e serviços internos. Caso contrário, o Docker tentará acessá-los através do proxy e receberá erros de conexão. Uma lista típica: localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
Proxy dentro do contêiner durante a construção (build-time)
Quando o Docker constrói uma imagem e executa comandos como RUN apt-get install, RUN pip install ou RUN npm install — esses comandos são executados dentro de um contêiner temporário. Por padrão, ele não tem acesso ao proxy do host. É necessário passar explicitamente o proxy através de argumentos de build.
Passando o proxy através de --build-arg
docker build \ --build-arg HTTP_PROXY=http://proxy-host:port \ --build-arg HTTPS_PROXY=http://proxy-host:port \ --build-arg NO_PROXY=localhost,127.0.0.1 \ -t my-image .
Configuração no Dockerfile
Se o proxy for necessário apenas na fase de construção e você não deseja que ele apareça na imagem final — use ARG, e não ENV:
FROM ubuntu:22.04 # Declarando argumentos de construção ARG HTTP_PROXY ARG HTTPS_PROXY ARG NO_PROXY # Usando-os nos comandos RUN apt-get update && apt-get install -y curl wget # Após este bloco, o proxy não estará no ENV do contêiner
Se o proxy for necessário também no contêiner em execução — use ENV:
FROM python:3.11 ENV HTTP_PROXY=http://proxy-host:port ENV HTTPS_PROXY=http://proxy-host:port ENV NO_PROXY=localhost,127.0.0.1 RUN pip install requests beautifulsoup4 CMD ["python", "app.py"]
⚠️ Atenção: segurança
Não insira o login e a senha do proxy diretamente no Dockerfile, se a imagem for pública ou for para um repositório. Use --build-arg e passe os valores das variáveis de ambiente do sistema CI/CD. O comando docker history pode mostrar os valores de ARG, portanto, para segredos, use os segredos do Docker BuildKit.
Proxy para contêiner em execução (runtime)
Este é o cenário mais comum para aplicativos que fazem solicitações HTTP durante a execução — scrapers, bots, microserviços que precisam de acesso através de um IP específico. Aqui, a configuração é bem simples: é necessário passar as variáveis de ambiente ao iniciar o contêiner.
Através do docker run
docker run \ -e HTTP_PROXY=http://username:password@proxy-host:port \ -e HTTPS_PROXY=http://username:password@proxy-host:port \ -e NO_PROXY=localhost,127.0.0.1 \ my-image
A maioria das bibliotecas HTTP populares captura automaticamente as variáveis HTTP_PROXY e HTTPS_PROXY: Python requests, curl, wget, Go's net/http, Node.js https-proxy-agent e outras. Não é necessário adicionar nada extra no código.
Através do arquivo .env
É mais conveniente armazenar as configurações em um arquivo .env e passá-lo inteiro:
# arquivo .env HTTP_PROXY=http://username:password@proxy-host:port HTTPS_PROXY=http://username:password@proxy-host:port NO_PROXY=localhost,127.0.0.1
docker run --env-file .env my-image
Proxy SOCKS5 no contêiner
Se você estiver usando um proxy SOCKS5 (por exemplo, proxies residenciais geralmente suportam esse protocolo), a sintaxe é um pouco diferente:
docker run \ -e ALL_PROXY=socks5://username:password@proxy-host:port \ my-image
Observe: nem todas as bibliotecas suportam SOCKS5 através da variável de ambiente sem dependências adicionais. Python requests requer a instalação de requests[socks], e o curl deve ser compilado com suporte a libcurl-socks.
Proxy no Docker Compose
Em projetos reais, raramente se usa o docker run puro. A maioria das vezes, trabalha-se com o Docker Compose, onde vários serviços são descritos em um único arquivo. A configuração do proxy aqui é feita no nível de cada serviço ou através de um arquivo de variáveis.
Opção 1: environment no docker-compose.yml
version: '3.8'
services:
scraper:
image: my-scraper:latest
environment:
- HTTP_PROXY=http://username:password@proxy-host:port
- HTTPS_PROXY=http://username:password@proxy-host:port
- NO_PROXY=localhost,127.0.0.1
restart: unless-stopped
api:
image: my-api:latest
# Este serviço sem proxy — acessa apenas recursos internos
ports:
- "8080:8080"
Opção 2: através do arquivo .env (recomendado)
Crie um .env no diretório com o docker-compose.yml. O Docker Compose captura automaticamente este arquivo:
# .env PROXY_HOST=proxy-host PROXY_PORT=8080 PROXY_USER=username PROXY_PASS=password
version: '3.8'
services:
scraper:
image: my-scraper:latest
environment:
- HTTP_PROXY=http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}
- HTTPS_PROXY=http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}
- NO_PROXY=localhost,127.0.0.1
Proxy durante a construção no Compose
Se no Compose houver uma seção build e for necessário passar o proxy na fase de construção:
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
args:
HTTP_PROXY: http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}
HTTPS_PROXY: http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}
environment:
- HTTP_PROXY=http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}
- HTTPS_PROXY=http://${PROXY_USER}:${PROXY_PASS}@${PROXY_HOST}:${PROXY_PORT}
Qual tipo de proxy escolher para o Docker
A escolha do tipo de proxy depende da tarefa. Para ambientes Docker, três tipos principais são relevantes, cada um com seu nicho:
| Tipo de proxy | Velocidade | Anonimato | Melhor cenário para Docker |
|---|---|---|---|
| Data center | ⚡ Alta | Média | Pull de imagens, pipelines CI/CD, contornar rate limiting do Docker Hub |
| Residencial | 🔄 Média | Alta | Scraping de sites com proteção, APIs com geo-restrições, testes |
| Móvel | 🔄 Média | Máxima | Aplicativos que trabalham com APIs móveis (Instagram, TikTok) |
Para pull de imagens e CI/CD, os proxies de data center são ideais — eles oferecem a máxima velocidade ao baixar grandes imagens (vários gigabytes) e uma conexão estável para longas construções.
Para contêineres scraper, que precisam contornar a proteção de sites e parecer usuários normais, os proxies residenciais são mais adequados. Eles têm IPs de usuários residenciais reais, o que reduz a probabilidade de bloqueio mesmo com solicitações intensas.
Para aplicativos que trabalham com plataformas móveis — Instagram Graph API, TikTok API, versões móveis de serviços — vale a pena considerar proxies móveis. Eles usam IPs de operadoras de telefonia celular e levantam o mínimo de suspeitas em sistemas anti-bot.
Protocolos: HTTP vs SOCKS5
O Docker daemon suporta apenas proxies HTTP/HTTPS — SOCKS5 não funciona para pull de imagens. Se você tiver um proxy SOCKS5 e precisar baixar imagens, será necessário usar um conversor local como privoxy ou microsocks, que aceitará HTTP e fará proxy através de SOCKS5.
Para contêineres em execução, a situação é melhor: a maioria das bibliotecas HTTP suporta SOCKS5 diretamente através da variável ALL_PROXY=socks5://....
Erros comuns e como corrigi-los
Vamos analisar os problemas mais comuns que surgem ao configurar proxies no Docker:
Erro 1: Proxy configurado no host, mas o Docker não o vê
Sintoma:
Error response from daemon: Get "https://registry-1.docker.io/v2/": dial tcp: connection refused
Razão: O Docker daemon é iniciado como um serviço do sistema e não herda as variáveis de ambiente do usuário atual, mesmo que você tenha definido export HTTPS_PROXY=... no terminal.
Solução: Configure o proxy através da substituição do systemd (método 1 da seção acima). Certifique-se de executar systemctl daemon-reload && systemctl restart docker.
Erro 2: apt-get / pip / npm não funcionam durante a construção
Sintoma:
Err:1 http://archive.ubuntu.com/ubuntu focal InRelease
Could not connect to archive.ubuntu.com:80
Razão: A configuração do proxy para o daemon não se aplica automaticamente aos comandos dentro de RUN no Dockerfile. Esses são dois contextos diferentes.
Solução: Passe o proxy através de --build-arg ou use ~/.docker/config.json com a seção proxies (Docker 23.0+, passa automaticamente os argumentos durante a construção).
Erro 3: Serviços internos não estão acessíveis através do proxy
Sintoma:
curl: (7) Failed to connect to internal-service.local port 8080: Connection refused
Razão: O proxy tenta encaminhar solicitações para endereços internos que não estão acessíveis externamente.
Solução: Adicione todos os domínios e sub-redes internos ao NO_PROXY. Para redes corporativas, uma lista típica é: localhost,127.0.0.1,::1,.internal,.local,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
Erro 4: Autenticação do proxy não funciona — caracteres especiais na senha
Se a senha contém caracteres especiais (@, #, %), a URL é analisada incorretamente.
Solução: Codifique a senha em URL-encoding. Por exemplo, p@ss#word → p%40ss%23word. Em Python, você pode rapidamente obter a versão codificada:
python3 -c "from urllib.parse import quote; print(quote('p@ss#word', safe=''))"
# Saída: p%40ss%23word
Erro 5: Proxy funciona, mas o certificado SSL não é verificado
Proxies corporativos frequentemente realizam inspeção SSL (MITM) e substituem certificados. O Docker, nesse caso, gera o erro:
x509: certificate signed by unknown authority
Solução: Adicione o certificado raiz corporativo aos confiáveis no host e reinicie o Docker. No Ubuntu/Debian:
sudo cp corporate-ca.crt /usr/local/share/ca-certificates/ sudo update-ca-certificates sudo systemctl restart docker
Erro 6: Kubernetes / Docker Swarm — proxy não funciona em todos os nós
Em ambientes de cluster, é necessário configurar o proxy em cada nó separadamente. Para Kubernetes, é necessário configurar variáveis de ambiente nos manifestos dos pods ou através do ConfigMap. Isso pode ser automatizado com Ansible ou outras ferramentas de gerenciamento de configuração.
Conclusão
A configuração do proxy no Docker não é uma única configuração, mas sim três níveis independentes: daemon para pull de imagens, build-time para construção e runtime para contêineres em execução. Ao entender essa arquitetura, você poderá gerenciar de forma flexível qual tráfego passa pelo proxy e qual vai diretamente.
Um breve checklist para uma configuração correta:
- ✅ Para pull de imagens — configure a substituição do systemd com as variáveis HTTP_PROXY e HTTPS_PROXY
- ✅ Para construção — passe o proxy através de
--build-argou~/.docker/config.json - ✅ Para runtime — use variáveis de ambiente através de
-eou--env-file - ✅ Sempre configure NO_PROXY para endereços internos
- ✅ Não armazene senhas de proxy no Dockerfile — use build-args e arquivos .env
- ✅ Para pipelines CI/CD, escolha proxies rápidos de data center
- ✅ Para contêineres scraper — proxies residenciais ou móveis
Se seus aplicativos em contêiner fazem solicitações a serviços externos, fazem scraping de dados ou trabalham com APIs que têm geo-restrições, recomendamos usar proxies residenciais — eles oferecem um alto nível de confiança por parte dos serviços e um risco mínimo de bloqueios, mesmo com trabalho intenso.