Ich versuche, einen Docker-Container zu erstellen, der sich wie eine voll funktionsfähige virtuelle Maschine verhält. Ich weiß, dass ich die EXPOSE-Anweisung in einer Docker-Datei verwenden kann, um einen Port verfügbar zu machen, und ich kann das -p
Flag mit verwenden docker run
, um Ports zuzuweisen. Gibt es jedoch einen Befehl zum Öffnen / Zuordnen zusätzlicher Ports, wenn ein Container tatsächlich ausgeführt wird?
Angenommen, ich habe einen Docker-Container, auf dem sshd ausgeführt wird. Jemand anderes, der den Container ssh verwendet, installiert httpd. Gibt es eine Möglichkeit, Port 80 auf dem Container verfügbar zu machen und ihn Port 8080 auf dem Host zuzuordnen, damit Benutzer den im Container ausgeführten Webserver besuchen können, ohne ihn neu zu starten?
Antworten:
Sie können dies nicht über Docker tun, aber Sie können vom Host-Computer aus auf den nicht exponierten Port des Containers zugreifen.
Wenn Sie einen Container haben, dessen Port 8000 ausgeführt wird, können Sie ihn ausführen
Führen Sie die folgenden 2 Befehle aus, um die IP-Adresse des Containers abzurufen:
Intern ruft Docker iptables auf, wenn Sie ein Image ausführen. Daher funktioniert möglicherweise eine Variation davon.
So legen Sie den Port 8000 des Containers auf dem Port 8001 Ihres lokalen Hosts frei:
Eine Möglichkeit, dies herauszufinden, besteht darin, einen anderen Container mit der gewünschten Portzuordnung einzurichten und die Ausgabe des Befehls iptables-save zu vergleichen (ich musste jedoch einige der anderen Optionen entfernen, die den Datenverkehr über das Docker erzwingen Proxy).
HINWEIS: Dies untergräbt den Docker und sollte daher mit dem Bewusstsein erfolgen, dass möglicherweise blauer Rauch entsteht
ODER
Eine andere Alternative besteht darin, die Option (neu? Post 0.6.6?) -P zu suchen, bei der zufällige Host-Ports verwendet werden, und diese dann zu verkabeln.
ODER
Mit 0.6.5 können Sie die LINKs-Funktion verwenden, um einen neuen Container aufzurufen, der mit dem vorhandenen kommuniziert, und einige zusätzliche Weiterleitungen an die -p-Flags dieses Containers. (Ich habe noch keine LINKs verwendet)
ODER
mit Docker 0.11? Sie können
docker run --net host ..
Ihren Container direkt an die Netzwerkschnittstellen des Hosts anschließen (dh das Netz hat keinen Namensabstand), sodass alle im Container geöffneten Ports verfügbar sind.quelle
CONTAINER_IP=$(docker inspect container_name | jq .[0].NetworkSettings.IPAddress | sed -r 's/\"([^\"]+)\"/\1/''])'); iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination ${CONTAINER_IP}:8000
jq
undsed
Sie können die-f
Option verwendendocker inspect
:CONTAINER_IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' container_name)
jshon -e 0 -e NetworkSettings -e Networks -e bridge -e IPAddress -u
Folgendes würde ich tun:
quelle
sudo docker
und nicht nurdocker
?docker commit
ich bereit, die Anwendung erneut zu testen, anstatt Stunden damit zu verbringen, alles neu zu installieren.Sie können zwar keinen neuen Port eines vorhandenen Containers verfügbar machen, aber Sie können einen neuen Container im selben Docker-Netzwerk starten und ihn dazu bringen, den Datenverkehr an den ursprünglichen Container weiterzuleiten.
Gearbeitetes Beispiel
Starten Sie einen Webdienst , der Port 80 überwacht , aber seinen internen Port 80 nicht verfügbar macht (oops!):
Suchen Sie die Docker-Netzwerk-IP:
Starten Sie
verb/socat
mit offengelegtem Port 8080 und leiten Sie den TCP-Verkehr an den Port 80 dieser IP weiter:Sie können jetzt unter http: // localhost: 8080 / auf pastebin zugreifen , und Ihre Anforderungen werden an
socat:1234
die weitergeleitet, an die es weitergeleitet wirdpastebin:80
, und die Antwort verläuft in umgekehrter Reihenfolge auf demselben Weg.quelle
verb/socat:alpine
, da das Image 5% des Footprints ausmacht (es sei denn, Sie stoßen auf libc- oder DNS-Inkompatibilitäten ).alpine/socat
--net myfoldername_default
meinenverb/socat
Startbefehl erweitern, da ich den nicht exponierten Container in einer Docker-Komposition gestartet habe, die ein Netzwerk erstellt.IPtables-Hacks funktionieren zumindest unter Docker 1.4.1 nicht.
Der beste Weg wäre, einen anderen Container mit dem exponierten Port zu betreiben und mit socat weiterzuleiten. Folgendes habe ich getan, um mit SQLPlus (vorübergehend) eine Verbindung zur Datenbank herzustellen:
Dockerfile:
quelle
FROM
Basis-Image wie Ihr DB-Container zu verwenden, um Ressourcen effizient zu nutzen.Hier ist eine andere Idee. Verwenden Sie SSH, um die Portweiterleitung durchzuführen. Dies hat den Vorteil, dass Sie auch unter OS X (und wahrscheinlich unter Windows) arbeiten können, wenn Ihr Docker-Host eine VM ist.
quelle
Ich musste mich mit demselben Problem befassen und konnte es lösen, ohne einen meiner laufenden Container anzuhalten. Dies ist eine Lösung, die ab Februar 2016 mit Docker 1.9.1 auf dem neuesten Stand ist. Wie auch immer, diese Antwort ist eine detaillierte Version der Antwort von @ ricardo-branco, aber für neue Benutzer ausführlicher.
In meinem Szenario wollte ich vorübergehend eine Verbindung zu MySQL herstellen, das in einem Container ausgeführt wird. Da andere Anwendungscontainer damit verknüpft sind, war das Stoppen, Neukonfigurieren und erneutes Ausführen des Datenbankcontainers kein Starter.
Da ich extern auf die MySQL-Datenbank zugreifen möchte (von Sequel Pro über SSH-Tunneling), werde ich den Port
33306
auf dem Host-Computer verwenden. (Nicht3306
, nur für den Fall, dass eine äußere MySQL-Instanz ausgeführt wird.)Ungefähr eine Stunde, in der Iptables optimiert wurden, erwies sich als erfolglos, obwohl:
Schritt für Schritt habe ich Folgendes getan:
Bearbeiten
dockerfile
, platzieren Sie dies in:Dann erstellen Sie das Bild:
Führen Sie es dann aus und verknüpfen Sie es mit Ihrem laufenden Container. (Verwenden Sie
-d
statt-rm
, um es im Hintergrund zu belassen, bis es explizit gestoppt und entfernt wird. Ich möchte, dass es in diesem Fall nur vorübergehend ausgeführt wird.)quelle
Um die akzeptierte Antwortlösung zu erweitern
iptables
, musste ich zwei weitere Befehle auf dem Host ausführen, um ihn für die Außenwelt zu öffnen.Hinweis: Ich habe Port https (443) geöffnet, meine Docker-interne IP war
172.17.0.2
Hinweis 2: Diese Regeln und temporären Regeln gelten nur bis zum Neustart des Containers
quelle
Sie können SSH verwenden, um einen Tunnel zu erstellen und Ihren Container in Ihrem Host verfügbar zu machen.
Sie können dies auf beide Arten tun, von Container zu Host und von Host zu Container. Sie benötigen jedoch ein SSH-Tool wie OpenSSH in beiden (Client in einem und Server in einem anderen).
Im Container können Sie dies beispielsweise tun
Die IP-Adresse des Containers finden Sie in dieser Zeile (im Container):
Dann können Sie im Host einfach Folgendes tun:
quelle
Falls für jemanden keine Antwort funktioniert - überprüfen Sie, ob Ihr Zielcontainer bereits im Docker-Netzwerk ausgeführt wird:
Speichern Sie es für später in der Variablen
$NET_NAME
:Wenn ja, sollten Sie den Proxy-Container im selben Netzwerk ausführen.
Suchen Sie als Nächstes den Alias für den Container:
Speichern Sie es für später in der Variablen
$ALIAS
:Führen Sie nun
socat
einen Container im Netzwerk aus,$NET_NAME
um eine Brücke zum$ALIAS
exponierten (aber nicht veröffentlichten) Port des ED-Containers zu schlagen:quelle
Sie können ein Overlay-Netzwerk wie Weave Net verwenden , das jedem Container eine eindeutige IP-Adresse zuweist und implizit alle Ports für jeden Containerteil des Netzwerks verfügbar macht.
Weave bietet auch die Integration des Host-Netzwerks . Es ist standardmäßig deaktiviert. Wenn Sie jedoch auch vom Host aus auf die Container-IP-Adressen (und alle ihre Ports) zugreifen möchten, können Sie sie einfach ausführen
weave expose
.Vollständige Offenlegung: Ich arbeite bei Weaveworks.
quelle
Es gibt eine praktische HAProxy-Hülle.
Dadurch wird ein HAProxy zum Zielcontainer erstellt. kinderleicht.
quelle
Hier sind einige Lösungen:
https://forums.docker.com/t/how-to-expose-port-on-running-container/3252/12
quelle
Lesen Sie zuerst Ricardos Antwort. Das hat bei mir funktioniert.
Es gibt jedoch ein Szenario, in dem dies nicht funktioniert, wenn der laufende Container mit Docker-Compose gestartet wurde. Dies liegt daran, dass Docker-Compose (ich verwende Docker 1.17) ein neues Netzwerk erstellt. Der Weg, um dieses Szenario anzugehen, wäre
docker network ls
Fügen Sie dann Folgendes hinzu
docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus --net network_name
quelle
Es ist nicht möglich, eine Live-Portzuordnung durchzuführen, aber es gibt mehrere Möglichkeiten, einem Docker-Container zu geben, was einer realen Schnittstelle wie einer virtuellen Maschine entspricht.
Macvlan-Schnittstellen
Docker enthält jetzt einen Macvlan-Netzwerktreiber . Dadurch wird ein Docker-Netzwerk an eine "reale" Schnittstelle angeschlossen, und Sie können diese Netzwerkadressen direkt dem Container zuweisen (wie im Bridged-Modus für virtuelle Maschinen).
pipework
Sie können auch eine reale Schnittstelle einem Container zuordnen oder eine Unterschnittstelle in älteren Docker-Versionen einrichten.IPs weiterleiten
Wenn Sie die Kontrolle über das Netzwerk haben, können Sie zusätzliche Netzwerke zur Verwendung in den Containern an Ihren Docker-Host weiterleiten.
Anschließend weisen Sie dieses Netzwerk den Containern zu und richten Ihren Docker-Host so ein, dass die Pakete über das Docker-Netzwerk weitergeleitet werden.
Shared Host-Schnittstelle
Mit dieser
--net host
Option kann die Hostschnittstelle für einen Container freigegeben werden. Aufgrund der gemeinsamen Nutzung ist dies jedoch wahrscheinlich keine gute Einrichtung, um mehrere Container auf einem Host auszuführen.quelle