498 Stimmen

Exponieren eines Ports auf einem laufenden Docker-Container

Ich versuche, einen Docker-Container zu erstellen, der sich wie eine vollwertige virtuelle Maschine verhält. Ich weiß, dass ich die EXPOSE-Anweisung innerhalb eines Dockerfile verwenden kann, um einen Port freizugeben, und ich kann die -p Flagge mit docker run verwenden, um Ports zuzuweisen, aber sobald ein Container tatsächlich läuft, gibt es dann einen Befehl, um zusätzliche Ports live zu öffnen/zuzuweisen?

Zum Beispiel, sagen wir ich habe einen Docker-Container, der sshd ausführt. Jemand anderes, der den Container verwendet, loggt sich per SSH ein und installiert httpd. Gibt es eine Möglichkeit, Port 80 auf dem Container freizugeben und auf Port 8080 auf dem Host zu mappen, so dass die Leute den im Container laufenden Webserver besuchen können, ohne ihn neu zu starten?

399voto

SvenDowideit Punkte 4940

Sie können dies nicht über Docker tun, aber Sie können auf den nicht freigegebenen Port des Containers vom Hostrechner aus zugreifen.

Wenn Sie einen Container mit etwas laufendem auf seinem Port 8000 haben, können Sie Folgendes ausführen:

wget http://container_ip:8000

Um die IP-Adresse des Containers zu erhalten, führen Sie die 2 Befehle aus:

docker ps
docker inspect container_name | grep IPAddress

Intern ruft Docker beim Ausführen eines Images iptables auf, daher könnte irgendeine Variation davon funktionieren.

Um den Port 8000 des Containers auf Port 8001 Ihres localhost freizugeben:

iptables -t nat -A  DOCKER -p tcp --dport 8001 -j DNAT --to-destination 172.17.0.19:8000

Eine Möglichkeit, dies herauszufinden, besteht darin, einen anderen Container mit der Portzuordnung, die Sie möchten, einzurichten und die Ausgabe des iptables-save-Befehls zu vergleichen (obwohl ich einige der anderen Optionen entfernen musste, die den Datenverkehr über den Docker-Proxy zwingen).

HINWEIS: Dies unterläuft Docker, sollte also mit dem Bewusstsein durchgeführt werden, dass es wahrscheinlich blaue Rauch erzeugen wird.

ODER

Eine andere Alternative besteht darin, die (neue? nach 0.6.6?) -P-Option zu prüfen, die zufällige Host-Ports verwendet und diese dann verknüpft.

ODER

Mit 0.6.5 könnten Sie die LINKs-Funktion verwenden, um einen neuen Container hochzufahren, der mit dem vorhandenen spricht, wobei zusätzliche Relais zu den -p-Flags dieses Containers? (Ich habe LINKs noch nicht verwendet.)

ODER

Mit Docker 0.11? können Sie docker run --net host .. verwenden, um Ihren Container direkt an die Netzwerkinterfaces des Hosts anzuschließen (d. h. das Netzwerk ist nicht im Namespace), und somit werden alle Ports, die Sie im Container öffnen, freigegeben.

156voto

bosky101 Punkte 2156

Das wäre mein Vorgehen:

  • Den laufenden Container committen.
  • Den Container erneut mit dem neuen Image ausführen, mit geöffneten Ports (Ich würde empfehlen, ein gemeinsames Volume einzubinden und den SSH-Port ebenfalls zu öffnen)

    sudo docker ps sudo docker commit
    sudo docker run -i -p 22 -p 8000:80 -m /data:/data -t /bin/bash

91voto

RobM Punkte 7755

Während Sie keinen neuen Port eines bestehenden Containers freigeben können, können Sie einen neuen Container im selben Docker-Netzwerk starten und ihn dazu bringen, den Datenverkehr an den ursprünglichen Container weiterzuleiten.

# docker run \
  --rm \
  -p $PORT:1234 \
  verb/socat \
    TCP-LISTEN:1234,fork \
    TCP-CONNECT:$TARGET_CONTAINER_IP:$TARGET_CONTAINER_PORT

Arbeitsbeispiel

Starten Sie einen Webdienst, der auf Port 80 hört, ohne jedoch seinen internen Port 80 freizugeben (Oops!):

# docker run -ti mkodockx/docker-pastebin   # Vergessen, PORT 80 freizugeben!

Suchen Sie seine Docker-Netzwerk-IP:

# docker inspect 63256f72142a | grep IPAddress
                    "IPAddress": "172.17.0.2",

Starten Sie verb/socat mit freigegebenem Port 8080 und leiten Sie den TCP-Datenverkehr an Port 80 dieser IP weiter:

# docker run --rm -p 8080:1234 verb/socat TCP-LISTEN:1234,fork TCP-CONNECT:172.17.0.2:80

Sie können nun auf Pastebin unter http://localhost:8080/ zugreifen. Ihre Anfragen werden an socat:1234 gesendet, der sie an pastebin:80 weiterleitet. Die Antwort erfolgt auf dem gleichen Weg in umgekehrter Richtung.

42voto

Ricardo Branco Punkte 429

IPtables-Hacks funktionieren nicht, zumindest nicht bei Docker 1.4.1.

Der beste Weg wäre, einen weiteren Container mit dem freigegebenen Port auszuführen und über socat zu übermitteln. Das habe ich gemacht, um (vorübergehend) eine Verbindung zur Datenbank mit SQLPlus herzustellen:

docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus

Dockerfile:

VON debian:7

RUN apt-get update && \
    apt-get -y install socat && \
    apt-get clean

BENUTZER niemand

CMD socat -dddd TCP-LISTEN:1521,wieder verwenden, Gabel TCP:db:1521

37voto

Scott Carlson Punkte 3694

Hier ist eine weitere Idee. Verwenden Sie SSH, um die Portweiterleitung durchzuführen; dies hat den Vorteil, dass es auch in OS X (und wahrscheinlich Windows) funktioniert, wenn Ihr Docker-Host eine VM ist.

docker exec -it  ssh -R5432:localhost:5432 @

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X