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?

11voto

dstj Punkte 4430

Um zur akzeptierten Antwort der iptables-Lösung hinzuzufügen, musste ich zwei weitere Befehle auf dem Host ausführen, um es für die Außenwelt zu öffnen.

HOST> iptables -t nat -A DOCKER -p tcp --dport 443 -j DNAT --to-destination 172.17.0.2:443
HOST> iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source 172.17.0.2 --destination 172.17.0.2 --dport https
HOST> iptables -A DOCKER -j ACCEPT -p tcp --destination 172.17.0.2 --dport https

Hinweis: Ich habe den Port https (443) geöffnet, meine interne Docker-IP war 172.17.0.2

Hinweis 2: Diese Regeln sind vorübergehend und gelten nur bis der Container neu gestartet wird

8voto

Excalibur Punkte 3099

Ich musste dieses gleiche Problem angehen und konnte es lösen, ohne einen meiner laufenden Container anzuhalten. Dies ist eine Lösung, die Stand Februar 2016 aktuell ist und Docker 1.9.1 verwendet. So, diese Antwort ist eine ausführlichere Version von @ricardo-branco's Antwort, jedoch detaillierter für neue Benutzer.

In meinem Szenario wollte ich vorübergehend auf MySQL zugreifen, das in einem Container läuft, und da andere Anwendungscontainer damit verknüpft sind, war es keine Option, den Datenbankcontainer anzuhalten, neu zu konfigurieren und neu zu starten.

Da ich auf die MySQL-Datenbank extern zugreifen möchte (von Sequel Pro über SSH-Tunneling), werde ich den Port 33306 auf der Host-Maschine verwenden. (Nicht 3306, nur für den Fall, dass eine externe MySQL-Instanz läuft.)

Etwa eine Stunde des Feinabstimmens von iptables blieb erfolglos, obwohl:

Schritt für Schritt, hier ist was ich gemacht habe:

mkdir db-expose-33306
cd db-expose-33306
vim Dockerfile

Bearbeiten Sie die Datei dockerfile und fügen Sie dies ein:

# Port 3306 im verknüpften Container "db" freigeben, um unter host:33306 erreichbar zu sein
FROM ubuntu:latest # (Empfohlen, die gleiche Basis wie der DB-Container zu verwenden)

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

USER nobody
EXPOSE 33306

CMD socat -dddd TCP-LISTEN:33306,reuseaddr,fork TCP:db:3306

Dann bauen Sie das Image:

docker build -t your-namespace/db-expose-33306 .

Führen Sie es dann aus, indem Sie es mit Ihrem laufenden Container verknüpfen. (Verwenden Sie -d anstelle von -rm, um es im Hintergrund zu halten, bis es ausdrücklich angehalten und entfernt wird. Ich möchte es nur vorübergehend in diesem Fall laufen lassen.)

docker run -it --rm --name=db-33306 --link the_live_db_container:db -p 33306:33306  your-namespace/db-expose-33306

7voto

ton Punkte 3011

Sie können SSH verwenden, um einen Tunnel zu erstellen und Ihren Container auf Ihrem Host freizugeben.

Sie können es auf beide Arten tun, vom Container zum Host und vom Host zum Container. Aber Sie brauchen ein SSH-Tool wie OpenSSH in beiden (Client in einem und Server in einem anderen).

Zum Beispiel können Sie im Container folgendes tun:

$ yum install -y openssh openssh-server.x86_64
service sshd restart
Stopping sshd:                                             [FAILED]
Generating SSH2 RSA host key:                              [  OK  ]
Generating SSH1 RSA host key:                              [  OK  ]
Generating SSH2 DSA host key:                              [  OK  ]
Starting sshd:                                             [  OK  ]
$ passwd # Sie müssen ein Root-Passwort festlegen..

Sie können die Container-IP-Adresse aus dieser Zeile finden (im Container):

$ ifconfig eth0 | grep "inet addr" | sed 's/^[^:]*:\([^ ]*\).*/\1/g'
172.17.0.2

Dann im Host können Sie einfach Folgendes tun:

sudo ssh -NfL 80:0.0.0.0:80 root@172.17.0.2

5voto

Paul Engel Punkte 73

Basierend auf Robms Antwort habe ich ein Docker-Image und ein Bash-Skript namens portcat erstellt.

Mit portcat können Sie ganz einfach mehrere Ports einem vorhandenen Docker-Container zuordnen. Hier ein Beispiel mit dem (optionalen) Bash-Skript:

curl -sL https://raw.githubusercontent.com/archan937/portcat/master/script/install | sudo bash
portcat my-awesome-container 3456 4444:8080

Und da haben Sie es! Portcat ordnet folgendes zu:

  • Port 3456 zu my-awesome-container:3456
  • Port 4444 zu my-awesome-container:8080

Bitte beachten Sie, dass das Bash-Skript optional ist. Die folgenden Befehle:

ipAddress=$(docker inspect my-awesome-container | grep IPAddress | grep -o '[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}' | head -n 1)
docker run -p 3456:3456 -p 4444:4444 --name=alpine-portcat -it pmelegend/portcat:latest $ipAddress 3456 4444:8080

Ich hoffe, dass portcat für euch nützlich sein wird. Prost!

3voto

kwerle Punkte 1748

Es gibt einen praktischen HAProxy-Wrapper.

docker run -it -p LOCALPORT:PROXYPORT --rm --link TARGET_CONTAINER:EZNAME -e "BACKEND_HOST=EZNAME" -e "BACKEND_PORT=PROXYPORT" demandbase/docker-tcp-proxy

Dies erstellt einen HAProxy für den Zielcontainer. Ganz einfach.

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