Wie führt man "apt-get" in einer Docker-Datei hinter einem Proxy aus?

75

Ich verwende eine virtuelle Maschine (Ubuntu 13.10) mit Docker (Version 0.8.1, Build a1598d1). Ich versuche, ein Image mit einer Docker-Datei zu erstellen. Zuerst möchte ich die Pakete aktualisieren (mit dem folgenden Code - der Proxy ist verschleiert), aber apt-getmit dem Fehler tritt eine Zeitüberschreitung auf : Could not resolve 'archive.ubuntu.com'.

FROM ubuntu:13.10
ENV HTTP_PROXY <HTTP_PROXY>
ENV HTTPS_PROXY <HTTPS_PROXY>
RUN export http_proxy=$HTTP_PROXY
RUN export https_proxy=$HTTPS_PROXY
RUN apt-get update && apt-get upgrade

Ich habe auch Folgendes im Host-System ausgeführt:

sudo HTTP_PROXY=http://<PROXY_DETAILS>/ docker -d &

Der Host kann problemlos ausgeführt apt-getwerden.

Wie kann ich die Docker-Datei so ändern, dass sie die Ubuntu-Server aus dem Container heraus erreicht?

Aktualisieren

Ich habe den Code in CentOS ausgeführt (Ändern FROM ubuntu:13.10in FROM centos) und es hat gut funktioniert. Es scheint ein Problem mit Ubuntu zu sein.

Christopher Louden
quelle
Ich habe gerade den http-Proxy in Centos (Yum Update) und im Ubuntu: 13.10 (Apt-Get Update) getestet. Beide Bilder funktionieren für mich, ich habe sogar versucht, DNS-Einstellungen aus dem Container zu entfernen, um den Proxy zu testen (es funktioniert ohne DNS in Ordnung, wie es sollte). Ich verwende nur http_proxy (kein https).
Jiri
Haben Sie tatsächlich "<HTTP_PROXY>" in Ihrer Docker-Datei oder ist dies ein Platzhalter?
Behe
Ich habe den eigentlichen Proxy in der Datei. Ich kann die Adresse einfach nicht teilen.
Christopher Louden
Schauen Sie sich diesen Artikel an: Verwenden von Docker hinter einem Proxy
Guillaume Husta

Antworten:

97

UPDATE :

Sie haben eine falsche Großschreibung von Umgebungsvariablen in ENV. Richtig ist http_proxy. Ihr Beispiel sollte sein:

FROM ubuntu:13.10
ENV http_proxy <HTTP_PROXY>
ENV https_proxy <HTTPS_PROXY>
RUN apt-get update && apt-get upgrade

oder

FROM centos
ENV http_proxy <HTTP_PROXY>
ENV https_proxy <HTTPS_PROXY>
RUN yum update 

Allen in ENV angegebenen Variablen wird jedem RUN-Befehl vorangestellt. Jeder RUN-Befehl wird in einem eigenen Container / einer eigenen Umgebung ausgeführt, sodass keine Variablen von früheren RUN-Befehlen geerbt werden!

Hinweis: Es ist nicht erforderlich, den Docker-Daemon mit Proxy aufzurufen, damit dies funktioniert. Wenn Sie jedoch Bilder usw. abrufen möchten, müssen Sie den Proxy auch für Docker-Deamon festlegen. Sie können den Proxy für den Daemon in /etc/default/dockerUbuntu festlegen (dies hat keine Auswirkungen auf die Containereinstellung).


Dies kann auch passieren, wenn Sie Ihren Proxy auf dem Host ausführen (z. B. localhost, 127.0.0.1). Localhost auf dem Host unterscheidet sich von localhost im Container. In diesem Fall müssen Sie eine andere IP-Adresse (z. B. 172.17.42.1) verwenden, um Ihren Proxy an 0.0.0.0 zu binden. Wenn Sie an 0.0.0.0 binden, können Sie während der Verbindung von Container 172.17.42.1 anstelle von 127.0.0.1 verwenden docker build.

Hier können Sie auch nach einem Beispiel suchen: Wie kann eine Docker-Datei mithilfe des Cache schnell wiederhergestellt werden?

Jiri
quelle
Ich habe keinen Proxy auf dem Host. Es ist ein Corporate Proxy, hinter dem ich stehe. Der gleiche Code funktioniert unter CentOS (nur ändern FROM) mit den gleichen Proxy-Einstellungen.
Christopher Louden
3
Mit dem aktuellen Status von Docker sieht es so aus, als müssten Sie ENV http_proxy corporate-proxy.comin Ihrer Docker-Datei sein. Das ist ziemlich ekelhaft, da Sie Ihre Docker-Datei nicht mit anderen Personen außerhalb Ihres Unternehmens teilen können. Ich habe dies gerade überprüft, indem ich polipo in einem Container ausgeführt habe, während ich versucht habe, apt-get installBefehle für die Entwicklung von Docker-Dateien zwischenzuspeichern. Vielleicht wird eine zukünftige Version von Docker eine magische iptables-Konfiguration haben, die ein transparentes Proxying von HTTP-Anforderungen ermöglicht?
Tim Potter
@ TimPotter Ich denke, es ist nicht so schlimm (keine fortgeschrittene Magie notwendig). Sie müssen polipo auf dem Host mit dem übergeordneten Proxy ( polipo parentProxy=corporate-proxy.com) einrichten und anschließend den transparenten Proxy mit iptables einrichten : iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner <polipo-user> --dport 80 -j REDIRECT --to-port 8123.
Jiri
1
Ich habe gerade ein Projekt zusammengestellt, das Squid, das in einem Container ausgeführt wird, mit den entsprechenden Befehlen iptables / ip rules bereitstellt, um den gesamten anderen Containerverkehr durch den Squid-Container für transparentes Proxying umzuleiten. Dies kann nützlich sein für das, was Sie beschreiben? silarsis.blogspot.com.au/2014/03/proxy-all-containers.html
KevinL
Haben Sie eine Möglichkeit, die http_proxy-Einstellung im Docker-Daemon (/ etc / defailt / docker) aus dem Docker-Container abzurufen? so kann ich Skript hinzufügen, um in Dockerfile zu injizieren
Larry Cai
49

Aktualisiert am 02/10/2018

Mit der neuen Funktion in der Docker-Option --configmüssen Sie den Proxy in Dockerfile nicht mehr festlegen. Sie können dieselbe Docker-Datei für die Verwendung in und außerhalb der Unternehmensumgebung verwenden.

--config string      Location of client config files (default "~/.docker")

oder Umgebungsvariable DOCKER_CONFIG

`DOCKER_CONFIG` The location of your client configuration files.

$ export DOCKER_CONFIG=~/.docker

https://docs.docker.com/engine/reference/commandline/cli/

https://docs.docker.com/network/proxy/

Ich empfehle, den Proxy mit httpProxy, httpsProxy, ftpProxyund festzulegen noProxy((Im offiziellen Dokument fehlt die Variable, ftpProxywas manchmal nützlich ist).

{
 "proxies":
 {
   "default":
   {
     "httpProxy": "http://127.0.0.1:3001",
     "httpsProxy": "http://127.0.0.1:3001",
     "ftpProxy": "http://127.0.0.1:3001",
     "noProxy": "*.test.example.com,.example2.com"
   }
 }
}

Passen Sie die Proxy-IP und den Port bei Bedarf an und speichern Sie unter ~/.docker/config.json

Nachdem Sie es richtig eingestellt haben, können Sie Docker Build und Docker Run wie gewohnt ausführen.

$ docker build -t demo . 

$ docker run -ti --rm demo env|grep -ri proxy
(standard input):http_proxy=http://127.0.0.1:3001
(standard input):HTTPS_PROXY=http://127.0.0.1:3001
(standard input):https_proxy=http://127.0.0.1:3001
(standard input):NO_PROXY=*.test.example.com,.example2.com
(standard input):no_proxy=*.test.example.com,.example2.com
(standard input):FTP_PROXY=http://127.0.0.1:3001
(standard input):ftp_proxy=http://127.0.0.1:3001
(standard input):HTTP_PROXY=http://127.0.0.1:3001

Alte Antwort (Stillgelegt)

Die folgende Einstellung in Dockerfile funktioniert für mich. Getestet habe ich in CoreOS, Vagrantund boot2docker. Angenommen, der Proxy-Port ist3128

In Centos:

ENV http_proxy=ip:3128 
ENV https_proxy=ip:3128

In Ubuntu:

ENV http_proxy 'http://ip:3128'
ENV https_proxy 'http://ip:3128'

Achten Sie auf das Format, einige haben http, andere nicht, andere mit einem einzigen Kontingent. Wenn die IP-Adresse 192.168.0.193 lautet, lautet die Einstellung wie folgt:

In Centos:

ENV http_proxy=192.168.0.193:3128 
ENV https_proxy=192.168.0.193:3128

In Ubuntu:

ENV http_proxy 'http://192.168.0.193:3128'
ENV https_proxy 'http://192.168.0.193:3128'

Wenn Sie in Coreos einen Proxy festlegen müssen, um beispielsweise das Image abzurufen

cat /etc/systemd/system/docker.service.d/http-proxy.conf

[Service]
Environment="HTTP_PROXY=http://192.168.0.193:3128"
BMW
quelle
1
Möglicherweise müssen Sie auch die https-Proxy-Einstellung hinzufügen, da apt-get sichere Verbindungen verwendet. [Service] Environment = "HTTP_PROXY = Ihr-Proxy-Server: Port " HTTPS_PROXY = Ihr-Proxy-Server: Port: 3128 "" NO_PROXY = localhost, 127.0.0.0 / 8 "
pharsfalvi
Beachten Sie, dass Sie für Centos die Portnummer explizit hinzufügen müssen, auch wenn es sich um den Standardport handelt 80: stackoverflow.com/a/46949277/1654763
Munchkin
1
Das hat funktioniert. Danke für das Beispiel. Docker-Dokumente sind nicht klar.
ToTenMilan
2
$DOCKER_CONFIGsollte auf ein Verzeichnis verweisen und nicht direkt auf die config.jsonDatei
Jakub Bochenski
42

Sie können die --build-argOption verwenden, wenn Sie mit einer Docker-Datei erstellen möchten.

Einen Link unter https://github.com/docker/docker/issues/14634 finden Sie im Abschnitt "Erstellen mit --build-arg mit mehreren HTTP_PROXY":

[root@pppdc9prda2y java]# docker build 
  --build-arg https_proxy=$HTTP_PROXY --build-arg http_proxy=$HTTP_PROXY 
  --build-arg HTTP_PROXY=$HTTP_PROXY --build-arg HTTPS_PROXY=$HTTP_PROXY 
  --build-arg NO_PROXY=$NO_PROXY  --build-arg no_proxy=$NO_PROXY -t java .

ANMERKUNG: Stellen Sie auf Ihrem eigenen System sicher, dass Sie die Umgebungsvariablen HTTP_PROXY und NO_PROXY festgelegt haben.

zhanxw
quelle
Dies ist eine unangenehme Problemumgehung. Für eine dauerhafte Einrichtung sollten Sie Dockerfile verwenden, wie @Reza Farshi ein Beispiel gegeben hat
Paweł Smołka
18
Böse Problemumgehung? In einigen (den meisten) Fällen ist es vorzuziehen, keinen eigenen Proxy in das Image einzubinden, wenn Ihr Image (zum Beispiel) von Personen in anderen Teilen Ihres Unternehmens verwendet werden soll, die möglicherweise hinter einem anderen Proxy stehen.
Ventolin
11

Vor jedem apt-get-Befehl in Ihrer Docker-Datei sollten Sie diese Zeile einfügen

COPY apt.conf /etc/apt/apt.conf

Dont'f vergessen erstellen apt.conf im selben Ordner , dass Sie das haben Dockerfile , den Inhalt der apt.conf sollte Datei wie folgt sein:

Acquire::socks::proxy "socks://YOUR-PROXY-IP:PORT/";
Acquire::http::proxy "http://YOUR-PROXY-IP:PORT/";
Acquire::https::proxy "http://YOUR-PROXY-IP:PORT/";

Wenn Sie Benutzername und Passwort verwenden, um eine Verbindung zu Ihrem Proxy herzustellen, sollte die apt.conf wie folgt aussehen:

Acquire::socks::proxy "socks://USERNAME:PASSWORD@YOUR-PROXY-IP:PORT/";
Acquire::http::proxy "http://USERNAME:PASSWORD@YOUR-PROXY-IP:PORT/";
Acquire::https::proxy "http://USERNAME:PASSWORD@YOUR-PROXY-IP:PORT/";

zum Beispiel :

Acquire::https::proxy "http://foo:[email protected]:8080/";

Wobei das foo der Benutzername und die Leiste das Passwort ist.

Reza Farshi
quelle
apt unterstützt SOCKS-Proxys überhaupt nicht. Acquire::socks::proxybedeutet, den Proxy für alle URLs festzulegen, die mit einem socksSchema beginnen. Da Sie sources.listkeine socks://URLs haben, wird diese Zeile vollständig ignoriert. Ich werde eine Bearbeitung einreichen, um dies zu korrigieren.
Hans-Christoph Steiner
Sie haben /etc/apt/apt.conf.d/<config>on jessie, daher muss die Dockerfile- COPYDirektive hier aktualisiert werden.
Ain Tohvri
Dies war die einzige Antwort, die für mich funktioniert hat (Docker für Windows hinter Corporate Proxy ausführen).
Connor Goddard
7

Verwenden Sie --build-arg in Umgebungsvariablen in Kleinbuchstaben:

docker build --build-arg http_proxy=http://proxy:port/ --build-arg https_proxy=http://proxy:port/ --build-arg ftp_proxy=http://proxy:port --build-arg no_proxy=localhost,127.0.0.1,company.com -q=false .
Gaetan
quelle
5

Wie von anderen Antworten vorgeschlagen, --build-argkann die Lösung sein. In meinem Fall musste ich --network=hostzusätzlich zu den --build-argOptionen hinzufügen .

docker build -t <TARGET> --build-arg http_proxy=http://<IP:PORT> --build-arg https_proxy=http://<IP:PORT> --network=host .
user4780495
quelle
Wenn es nur bei Verwendung von --network = host funktioniert, könnte dies ein Problem mit dnsmasq sein. Siehe wisbuckys Antwort unten. Nachdem Sie die richtigen DNS in / etc / resolv, conf auf dem Host erhalten haben, sollten Sie --network = host
user2707671
4

Eine leichte Alternative zu der Antwort von @Reza Farshi (die in meinem Fall besser funktioniert) besteht darin, die Proxy-Einstellungen für die /etc/apt/apt.confVerwendung echoüber die Docker-Datei zu schreiben, z.

FROM ubuntu:16.04

RUN echo "Acquire::http::proxy \"$HTTP_PROXY\";\nAcquire::https::proxy \"$HTTPS_PROXY\";" > /etc/apt/apt.conf

# Test that we can now retrieve packages via 'apt-get'
RUN apt-get update

Der Vorteil dieses Ansatzes besteht darin, dass die Proxy-Adressen zum Zeitpunkt der Image-Erstellung dynamisch übergeben werden können, anstatt die Einstellungsdatei vom Host kopieren zu müssen.

z.B

docker build --build-arg HTTP_PROXY=http://<host>:<port> --build-arg HTTPS_PROXY=http://<host>:<port> .

gemäß Docker Build Docs.

Connor Goddard
quelle
3

Ich hatte das gleiche Problem und fand eine weitere kleine Problemumgehung: Ich habe ein Provisioner-Skript, das aus der Docker-Build-Umgebung hinzugefügt wird. Im Skript setze ich die Umgebungsvariable abhängig von einer Ping-Prüfung:

Dockerfile:

ADD script.sh /tmp/script.sh
RUN /tmp/script.sh

script.sh:

if ping -c 1 ix.de ; then
    echo "direct internet doing nothing"
else
    echo "proxy environment detected setting proxy"
    export http_proxy=<proxy address>
fi

das ist noch etwas grob aber hat bei mir funktioniert

user3813609
quelle
Das hat bei dir funktioniert? Ich kann das Skript einwandfrei ausführen, aber die Umgebungsvariablen stehen nur dem Skript zur Verfügung. Dinge wie apt-get, cURL und wget sehen die Umgebungsvariablen nicht.
Ryan J. McDonough
3

Wenn Sie die Proxys korrekt eingerichtet haben und das Internet immer noch nicht erreichen können, kann dies an der DNS-Auflösung liegen. Überprüfen Sie /etc/resolve.confdie Host-Ubuntu-VM. Wenn es enthält nameserver 127.0.1.1, ist das falsch.

Führen Sie die folgenden Befehle auf der Ubuntu-VM des Hosts aus, um das Problem zu beheben:

sudo vi /etc/NetworkManager/NetworkManager.conf
# Comment out the line `dns=dnsmasq` with a `#`

# restart the network manager service
sudo systemctl restart network-manager

cat /etc/resolv.conf

Jetzt /etc/resolv.confsollte ein gültiger Wert für den Nameserver vorhanden sein, der von den Docker-Containern kopiert wird.

wisbucky
quelle
Vielen Dank! Diese Antwort war äußerst hilfreich und hat mir schließlich geholfen, pip installmit Docker hinter einem Proxy zu arbeiten. Das wollte das OP nicht wirklich, hat mir aber sehr geholfen! :)
Colidyre
Gleich hier, danke! Hier gibt es mehr Infos zu diesem Thema: superuser.com/questions/681993/...
user2707671
1

Wir machen ...

ENV http_proxy http://9.9.9.9:9999
ENV https_proxy http://9.9.9.9:9999

und am Ende der Docker-Datei ...

ENV http_proxy ""
ENV https_proxy ""

Auf diese Weise (bis Docker Build-Env-Variablen einführt) können die Proxy-Env-Variablen NUR für den Build verwendet werden, ohne sie verfügbar zu machen

Die Alternative zur Lösung besteht NICHT darin, Ihre Bilder lokal hinter einem Proxy zu erstellen, sondern Docker Ihre Bilder mithilfe von "automatisierten Builds" für Docker für Sie erstellen zu lassen. Da Docker die Images hinter Ihrem Proxy nicht erstellt, ist das Problem behoben. Ein Beispiel für einen automatisierten Build finden Sie unter ...

https://github.com/danday74/docker-nginx-lua (GITHUB-Repo)

https://registry.hub.docker.com/u/danday74/nginx-lua (DOCKER-Repo, das das Github-Repo mithilfe eines automatisierten Builds überwacht und einen Docker-Build auf einem Push zum Github-Master-Zweig ausführt)

danday74
quelle
Ich wollte nur erwähnen, dass diese ENV-Variablen, da sie in JEDEM Zwischencontainer verfügbar sind, durch Deaktivieren am Ende nicht ausgeblendet werden und dennoch recht einfach zugänglich sind. Soweit
Squadrons
1

und Wenn Sie einen Proxy für wget festlegen möchten, sollten Sie diese Zeile in Ihre Docker-Datei einfügen

ENV http_proxy YOUR-PROXY-IP:PORT/
ENV https_proxy YOUR-PROXY-IP:PORT/
ENV all_proxy YOUR-PROXY-IP:PORT/
Reza Farshi
quelle
1

Wie Tim Potter betonte, ist es schrecklich, einen Proxy in der Docker-Datei zu setzen. Beim Erstellen des Images fügen Sie einen Proxy für Ihr Unternehmensnetzwerk hinzu, stellen ihn jedoch möglicherweise in der Cloud oder in einer DMZ bereit, in der kein Proxy erforderlich ist oder der Proxyserver anders ist.

Sie können Ihr Bild auch nicht mit anderen Personen außerhalb Ihres Unternehmens teilen.

Dhawal
quelle