Docker-Ports sind nicht verfügbar

78

Ich habe in Docker einen einfachen Knotenserver eingerichtet.

Dockerfile

FROM node:latest
RUN apt-get -y update
ADD example.js .
EXPOSE 1337   
CMD node example.js

example.js

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n'+new Date);
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

Erstellen Sie nun das Image

$ docker build -t node_server .

Jetzt im Container laufen lassen

$ docker run -p 1337:1337 -d node_server  
$ 5909e87302ab7520884060437e19ef543ffafc568419c04630abffe6ff731f70

Stellen Sie sicher, dass der Container ausgeführt wird und die Ports zugeordnet sind:

$ docker ps  

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
5909e87302ab        node_server         "/bin/sh -c 'node exa"   7 seconds ago       Up 6 seconds        0.0.0.0:1337->1337/tcp   grave_goldberg

Lassen Sie uns nun eine Verbindung zum Container herstellen und überprüfen, ob der Server im Inneren ausgeführt wird:

$ docker exec -it 5909e87302ab7520884060437e19ef543ffafc568419c04630abffe6ff731f70 /bin/bash 

Und in der Container-Befehlszeile geben Sie Folgendes ein:

root@5909e87302ab:/# curl http://localhost:1337
Hello World
Mon Feb 15 2016 16:28:38 GMT+0000 (UTC)

Sieht gut aus, oder?

Das Problem

Wenn ich denselben Curl-Befehl auf dem Host ausführe (oder mit meinem Browser zu http: // localhost: 1337 navigiere ), wird nichts angezeigt .

Irgendeine Idee, warum die Portzuordnung zwischen Container und Host nicht funktioniert?

Dinge, die ich bereits versucht habe:

  • Laufen mit der --expose 1337Flagge
Assaf Shomer
quelle
Sie "laufen nicht mit --expose". Sie erstellen ein Image mit der EXPOSEDirektive und führen es dann mit --publish(oder -p) aus. Siehe meine Antwort unten.
VonC

Antworten:

117

Ihre Ports werden korrekt angezeigt, aber Ihr Server überwacht Verbindungen 127.0.0.1in Ihrem Container:

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n'+new Date);
}).listen(1337, '127.0.0.1');

Sie müssen Ihren Server folgendermaßen ausführen:

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n'+new Date);
}).listen(1337, '0.0.0.0');

Beachten Sie die 0.0.0.0 anstelle von 127.0.0.1.

Chris McKinnel
quelle
3
Das Hören auf 0.0.0.0 sieht sehr seltsam aus, nicht sofort ersichtlich, was es bedeutet. Es scheint jedoch die Standardeinstellung zu sein, so dass Sie dieses Argument einfach in der listen()Funktion weglassen können, was meiner Meinung nach einfacher zu erfassen ist. Nodejs.org/api/…
Davos
5
Das Abhören von 0.0.0.0 bedeutet "Abhören aller Schnittstellen". Es ist oft übertrieben, manchmal ein Sicherheitsbedenken, aber im Allgemeinen harmlos. In einem Docker-Container ist dies sinnvoll.
Jim Stewart
1
Vielen Dank, diese Lösung behebt das Problem mit allen Arten von Servern, die in Docker ausgeführt werden, wie z. B. Java oder Node.js Express-Server. Die Schnittstelle MUSS auf jeden Fall sein: Wenn 0.0.0.0der Port derjenige ist, der mit der -P $PORT:$PORT/tcpOption exportiert wird , würde normalerweise ein Server zur export HOST=0.0.0.0Laufzeit nachsehen.
Loretoparisi
1
Vielen Dank dafür - ich habe endlose Stunden gebraucht, um es zu lösen!
Readikus
34

Hinzufügen von EXPOSE 1337 zur Docker-Datei

EXPOSE ist verpflichtend Wenn Sie diesen Port anderen Containern "aussetzen" möchten.

Wie BMitch kommentiert:

Exposewird nicht benötigt, um einen Port zu veröffentlichen oder Container über ein gemeinsam genutztes Docker-Netzwerk mit Container zu verbinden.
Es handelt sich um Metadaten zum Veröffentlichen aller Ports mit -Pund zum Überprüfen des Images / Containers.

Damit:

Laufen mit der --expose 1337Flagge

Nicht genau: Sie müssen es mit Docker ausführen-p 1337:1337

Sie benötigen entweder:

  • Erstellen Sie ein Image mit der darin enthaltenen EXPOSEDirektive (verwendet von -P).
  • oder führen Sie es mit dem auf dem Host veröffentlichten Port aus-p 1337:1337

Der Test curl http://localhost:1337wurde aus dem Container heraus durchgeführt (keine EXPOSEoder Veröffentlichung erforderlich).
Wenn Sie möchten, dass es vom Linux-Host aus funktioniert, benötigen Sie EXPOSE+-P oder benötigen Sie -p 1337:1337.
Entweder.

Allein zu deklarieren ist gut, um die Absicht zu dokumentieren, macht aber nichts alleine.

Zum Beispiel:

https://i.stack.imgur.com/wmKgd.png

In dieser Abbildung ist 8080 EXPOSE'd, veröffentlicht auf dem Linux-Host 8888.
Und wenn dieser Linux-Host nicht der tatsächliche Host ist, muss derselbe Port schnell auf den tatsächlichen Host übertragen werden. Siehe " Zugriff auf Tomcat, der im Docker-Container vom Browser ausgeführt wird? ".

Wenn localhost vom Linux-Host aus nicht funktioniert, versuchen Sie es mit seiner IP-Adresse:

CID=$(docker run -p 1337:1337 -d node_server)
CIP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${CID})
curl http://${CIP}:1337

Oder lassen Sie Ihren Server, wie oben erwähnt, Verbindungen von einer beliebigen IP- Adresse abhören: 0.0.0.0Dies ist die Broadcast-Adresse oder das Null-Netzwerk .

VonC
quelle
Vielen Dank für den Kommentar, aber wie oben erwähnt, habe ich bereits versucht, die EXPOSE 1337 hinzuzufügen, und es funktioniert auch nicht
Assaf Shomer
@AssafShomer Sie brauchen beide, das ist der
springende
@AssafShomer Ich habe die Antwort bearbeitet, um diesen Punkt klarer zu machen.
VonC
2
Danke natürlich, ich habe es mit beiden versucht. Nämlich: Mit EXPOSE 1337 erstellen und mit -p 1337: 1337 ausführen, immer noch nichts. Ich habe die Frage geändert, um dies widerzuspiegeln.
Assaf Shomer
@AssafShomer Sind Sie direkt unter Linux oder verwenden Sie Docker über eine boot2docker-VM unter Windows oder Mac?
VonC