Lavori con Docker in una rete aziendale, su un server con accesso limitato o vuoi che i tuoi container accedano a Internet tramite un IP specifico? Senza la corretta configurazione del proxy, Docker non sarà in grado di scaricare immagini da Docker Hub o da qualsiasi altro registro. In questo articolo esamineremo tutti i livelli di proxy — dal demone a un container separato.
Perché Docker ha bisogno di un proxy
Docker è uno strumento che accede costantemente a risorse esterne. Ad ogni docker pull o docker build, il demone accede a Docker Hub, GitHub Container Registry, Google Container Registry o al tuo registro privato. Ed è qui che iniziano i problemi.
Situazioni in cui un proxy è indispensabile:
- Rete aziendale con firewall — tutto il traffico deve passare attraverso il proxy aziendale, altrimenti la connessione viene bloccata.
- Geo-restrizioni — Docker Hub o registri specifici non sono accessibili dal tuo paese o data center.
- Server limitato senza accesso diretto a Internet — VPS in un circuito chiuso, dove Internet è accessibile solo tramite un gateway.
- Controllo del traffico in uscita dei container — vuoi che le applicazioni all'interno dei container accedano alla rete tramite un IP specifico, ad esempio per scraping, richieste API o test di contenuti geo-dipendenti.
- Anonimizzazione delle richieste — nascondere il vero IP del server quando si accede a servizi esterni dal container.
- Rate limiting — Docker Hub limita il numero di richieste pull per gli utenti anonimi (100 pull ogni 6 ore). Attraverso un proxy con rotazione IP è possibile aggirare questa limitazione.
È importante comprendere che Docker non è un'unica applicazione, ma un sistema composto da più componenti. Il demone (dockerd) vive sull'host e fa pull delle immagini. I container sono processi isolati con le proprie impostazioni di rete. Pertanto, la configurazione del proxy per il demone e per i container è un compito diverso, che richiede approcci distinti.
Tre livelli di proxy in Docker
Prima di immergersi nelle configurazioni, è necessario comprendere l'architettura. In Docker ci sono tre livelli indipendenti, ognuno dei quali richiede una configurazione del proxy separata:
| Livello | Cosa fa | Dove si configura |
|---|---|---|
| Demone Docker | Scarica immagini (docker pull), accede ai registri | override systemd o daemon.json |
| Docker build | Esegue comandi durante la costruzione dell'immagine (RUN apt-get, pip install, ecc.) | ARG e ENV nel Dockerfile o --build-arg |
| Container in esecuzione | Applicazione in esecuzione che effettua richieste HTTP | ENV durante docker run o nel docker-compose.yml |
Un errore comune è configurare il proxy solo su un livello e chiedersi perché le immagini non vengano comunque scaricate o perché l'applicazione non veda il proxy. Esaminiamo ogni livello in dettaglio.
Configurazione del proxy per il demone Docker (pull di immagini)
Questa è la configurazione più importante se vuoi scaricare immagini tramite un proxy. Il demone Docker è un servizio di sistema che viene avviato tramite systemd. Le variabili d'ambiente del tuo utente o anche di root non sono visibili. Devi passare il proxy esattamente nell'ambiente del servizio.
Metodo 1: tramite override systemd (raccomandato)
Crea una directory per sovrascrivere le impostazioni del servizio:
sudo mkdir -p /etc/systemd/system/docker.service.d
Crea un file /etc/systemd/system/docker.service.d/http-proxy.conf con il seguente contenuto:
[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 il proxy non richiede autenticazione, basta rimuovere username:password@. Dopo aver creato il file, ricarica la configurazione di systemd e riavvia Docker:
sudo systemctl daemon-reload sudo systemctl restart docker
Controlla che le impostazioni siano state applicate:
sudo systemctl show --property=Environment docker
Nell'output dovrebbero apparire le tue variabili HTTP_PROXY e HTTPS_PROXY.
Metodo 2: tramite ~/.docker/config.json (Docker Desktop e versioni recenti)
A partire da Docker Engine 23.0, è stato introdotto un metodo più semplice — configurare il proxy tramite il file di configurazione del client. Crea o modifica il file ~/.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"
}
}
}
Questo metodo è comodo perché non richiede privilegi di root e il riavvio del demone. Le impostazioni vengono automaticamente trasferite ai container durante la costruzione come argomenti di build. Tuttavia, per gestire le richieste pull del demone stesso, è comunque necessario un metodo tramite systemd.
💡 Importante su NO_PROXY
Aggiungi sempre agli indirizzi NO_PROXY i tuoi registri e servizi interni. Altrimenti, Docker cercherà di accedervi tramite il proxy e riceverà errori di connessione. Un elenco tipico: localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
Proxy all'interno del container durante la costruzione (build-time)
Quando Docker costruisce un'immagine ed esegue comandi come RUN apt-get install, RUN pip install o RUN npm install, questi comandi vengono eseguiti all'interno di un container temporaneo. Di default, non ha accesso al proxy dell'host. Devi passare esplicitamente il proxy tramite argomenti di build.
Passaggio del proxy tramite --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 .
Configurazione nel Dockerfile
Se il proxy è necessario solo durante la fase di costruzione e non vuoi che venga incluso nell'immagine finale, usa ARG invece di ENV:
FROM ubuntu:22.04 # Dichiarazione degli argomenti di build ARG HTTP_PROXY ARG HTTPS_PROXY ARG NO_PROXY # Utilizzali nei comandi RUN apt-get update && apt-get install -y curl wget # Dopo questo blocco, il proxy non sarà presente in ENV del container
Se invece il proxy è necessario anche nel container in esecuzione, usa 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"]
⚠️ Attenzione: sicurezza
Non hardcodare il login e la password del proxy direttamente nel Dockerfile, se l'immagine sarà pubblica o andrà in un repository. Usa --build-arg e passa i valori dalle variabili d'ambiente del sistema CI/CD. Il comando docker history può mostrare i valori ARG, quindi per i segreti utilizza i segreti di Docker BuildKit.
Proxy per il container in esecuzione (runtime)
Questo è lo scenario più comune per le applicazioni che effettuano richieste HTTP durante l'esecuzione — scraper, bot, microservizi che necessitano di uscire tramite un IP specifico. Qui la configurazione è massimamente semplice: devi passare le variabili d'ambiente durante l'avvio del container.
Attraverso 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
La maggior parte delle librerie HTTP popolari acquisisce automaticamente le variabili HTTP_PROXY e HTTPS_PROXY: Python requests, curl, wget, Go's net/http, Node.js https-proxy-agent e altre. Non è necessario scrivere nulla di aggiuntivo nel codice.
Attraverso il file .env
È più comodo memorizzare le impostazioni in un file .env e passarlo interamente:
# file .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 nel container
Se utilizzi un proxy SOCKS5 (ad esempio, i proxy residenziali supportano spesso proprio questo protocollo), la sintassi è leggermente diversa:
docker run \ -e ALL_PROXY=socks5://username:password@proxy-host:port \ my-image
Nota: non tutte le librerie supportano SOCKS5 tramite variabile d'ambiente senza dipendenze aggiuntive. Python requests richiede l'installazione di requests[socks], curl deve essere compilato con supporto per libcurl-socks.
Proxy in Docker Compose
Nei progetti reali, raramente si utilizza il semplice docker run. Più spesso si lavora con Docker Compose, dove più servizi sono descritti in un unico file. La configurazione del proxy qui viene effettuata a livello di ciascun servizio o tramite un file di variabili.
Opzione 1: environment in 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
# Questo servizio senza proxy — accede solo a risorse interne
ports:
- "8080:8080"
Opzione 2: tramite file .env (raccomandato)
Crea un .env nella directory con docker-compose.yml. Docker Compose acquisisce automaticamente questo file:
# .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 la costruzione in Compose
Se in Compose è presente una sezione build e hai bisogno di passare il proxy durante la fase di costruzione:
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}
Quale tipo di proxy scegliere per Docker
La scelta del tipo di proxy dipende dal compito. Per gli ambienti Docker, ci sono tre tipi principali, ognuno con la propria nicchia:
| Tipo di proxy | Velocità | Anonimato | Miglior scenario per Docker |
|---|---|---|---|
| Data center | ⚡ Alta | Media | Pull di immagini, pipeline CI/CD, aggirare il rate limiting di Docker Hub |
| Residenziali | 🔄 Media | Alta | Scraping di siti protetti, API con geo-restrizioni, testing |
| Mobile | 🔄 Media | Massima | Applicazioni che lavorano con API mobili (Instagram, TikTok) |
Per pull di immagini e CI/CD sono ottimali proxy di data center — forniscono la massima velocità durante il download di grandi immagini (diversi gigabyte) e una connessione stabile per lunghe costruzioni.
Per i container scraper, che devono aggirare la protezione dei siti e apparire come un utente normale, i proxy residenziali sono più adatti. Hanno IP di utenti domestici reali, il che riduce la probabilità di blocchi anche con richieste intensive.
Per le applicazioni che lavorano con piattaforme mobili — Instagram Graph API, TikTok API, versioni mobili dei servizi — è consigliabile considerare i proxy mobili. Utilizzano IP di operatori di telefonia mobile e suscitano il minimo sospetto nei sistemi anti-bot.
Protocolli: HTTP vs SOCKS5
Il demone Docker supporta solo proxy HTTP/HTTPS — SOCKS5 non funziona per il pull delle immagini. Se hai un proxy SOCKS5 e devi scaricare immagini, dovrai utilizzare un convertitore locale come privoxy o microsocks, che accetterà HTTP e lo proxyserà tramite SOCKS5.
Per i container in esecuzione, la situazione è migliore: la maggior parte delle librerie HTTP supporta SOCKS5 direttamente tramite la variabile ALL_PROXY=socks5://....
Errori comuni e come risolverli
Esaminiamo i problemi più comuni che si incontrano durante la configurazione del proxy in Docker:
Errore 1: Proxy configurato sull'host, ma Docker non lo vede
Sintomo:
Errore di risposta dal demone: Get "https://registry-1.docker.io/v2/": dial tcp: connection refused
Motivo: Il demone Docker viene eseguito come servizio di sistema e non eredita le variabili d'ambiente dell'utente corrente, anche se hai impostato export HTTPS_PROXY=... nel terminale.
Soluzione: Configura il proxy tramite override systemd (metodo 1 della sezione precedente). Assicurati di eseguire systemctl daemon-reload && systemctl restart docker.
Errore 2: apt-get / pip / npm non funzionano durante la costruzione
Sintomo:
Err:1 http://archive.ubuntu.com/ubuntu focal InRelease
Impossibile connettersi a archive.ubuntu.com:80
Motivo: La configurazione del proxy per il demone non si applica automaticamente ai comandi all'interno di RUN nel Dockerfile. Questi sono due contesti diversi.
Soluzione: Passa il proxy tramite --build-arg o utilizza ~/.docker/config.json con la sezione proxies (Docker 23.0+, trasferisce automaticamente gli argomenti durante la costruzione).
Errore 3: Servizi interni non accessibili tramite proxy
Sintomo:
curl: (7) Impossibile connettersi a internal-service.local porta 8080: Connessione rifiutata
Motivo: Il proxy tenta di proxyare le richieste agli indirizzi interni, che non sono accessibili dall'esterno.
Soluzione: Aggiungi tutti i domini e le sottoreti interni in NO_PROXY. Per le reti aziendali, un elenco tipico è: localhost,127.0.0.1,::1,.internal,.local,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
Errore 4: Autenticazione del proxy non funziona — caratteri speciali nella password
Se la password contiene caratteri speciali (@, #, %), l'URL viene analizzato in modo errato.
Soluzione: Codifica la password in URL-encoding. Ad esempio, p@ss#word → p%40ss%23word. In Python puoi rapidamente ottenere la versione codificata:
python3 -c "from urllib.parse import quote; print(quote('p@ss#word', safe=''))"
# Output: p%40ss%23word
Errore 5: Il proxy funziona, ma il certificato SSL non viene verificato
I proxy aziendali spesso eseguono ispezioni SSL (MITM) e sostituiscono i certificati. Docker restituisce quindi un errore:
x509: certificato firmato da un'autorità sconosciuta
Soluzione: Aggiungi il certificato radice aziendale ai certificati fidati sull'host e riavvia Docker. Su Ubuntu/Debian:
sudo cp corporate-ca.crt /usr/local/share/ca-certificates/ sudo update-ca-certificates sudo systemctl restart docker
Errore 6: Kubernetes / Docker Swarm — il proxy non funziona su tutti i nodi
Negli ambienti cluster, è necessario configurare il proxy su ogni nodo separatamente. Per Kubernetes, è necessario configurare anche le variabili d'ambiente nei manifesti dei pod o tramite ConfigMap. Questo può essere automatizzato tramite Ansible o altri strumenti di gestione della configurazione.
Conclusione
La configurazione del proxy in Docker non è una singola impostazione, ma tre livelli indipendenti: il demone per il pull delle immagini, il build-time per la costruzione e il runtime per i container in esecuzione. Comprendendo questa architettura, sarai in grado di gestire in modo flessibile quale traffico passa attraverso il proxy e quale direttamente.
Un breve checklist per una corretta configurazione:
- ✅ Per il pull delle immagini — configura l'override di systemd con le variabili HTTP_PROXY e HTTPS_PROXY
- ✅ Per la costruzione — passa il proxy tramite
--build-argo~/.docker/config.json - ✅ Per il runtime — utilizza le variabili d'ambiente tramite
-eo--env-file - ✅ Configura sempre NO_PROXY per gli indirizzi interni
- ✅ Non memorizzare le password del proxy nel Dockerfile — utilizza build-args e file .env
- ✅ Per le pipeline CI/CD, scegli proxy di data center veloci
- ✅ Per i container scraper — proxy residenziali o mobili
Se le tue applicazioni containerizzate effettuano richieste a servizi esterni, eseguono scraping di dati o lavorano con API che hanno geo-restrizioni, ti consigliamo di utilizzare proxy residenziali — forniscono un alto livello di fiducia da parte dei servizi e un rischio minimo di blocchi anche durante un utilizzo intensivo.