Was ist der Unterschied zwischen "Belichten" und "Veröffentlichen" in Docker?

517

Ich experimentiere mit Dockerfiles und glaube, ich verstehe den größten Teil der Logik. In diesem Zusammenhang sehe ich jedoch keinen Unterschied zwischen dem "Offenlegen" und dem "Veröffentlichen" eines Ports.

Alle Tutorials, die ich zuerst gesehen habe, enthalten den EXPOSEBefehl in der Docker-Datei:

...
EXPOSE 8080
...

Sie erstellen dann ein Image aus dieser Docker-Datei:

$ docker build -t an_image - < Dockerfile

Veröffentlichen Sie dann denselben Port wie oben, wenn Sie das Image ausführen:

$ docker run -d -p 8080 an_image

oder veröffentlichen Sie alle Ports mit

$ docker run -d -P an_image

Was bringt es, einen Port in der Docker-Datei verfügbar zu machen, wenn er trotzdem veröffentlicht wird? Wäre es jemals notwendig, einen Port zuerst verfügbar zu machen und später nicht zu veröffentlichen? Tatsächlich möchte ich alle Ports angeben, die ich in der Docker-Datei beim Erstellen des Images verwenden werde, und mich dann nicht erneut mit ihnen befassen, sondern sie einfach ausführen mit:

$ docker run -d an_image

Ist das möglich?

user1496984
quelle

Antworten:

732

Grundsätzlich haben Sie drei Möglichkeiten:

  1. Weder angeben EXPOSEnoch-p
  2. Nur angeben EXPOSE
  3. Geben Sie EXPOSEund an-p

1) Wenn Sie weder EXPOSEnoch angeben -p, ist der Dienst im Container nur von innerhalb des Containers selbst zugänglich .

2) Wenn Sie EXPOSE einen Port haben, ist der Dienst im Container nicht von außerhalb von Docker, sondern von innerhalb anderer Docker-Container zugänglich. Das ist also gut für die Kommunikation zwischen Containern.

3) Wenn Sie EXPOSEund -pein Port, ist der Dienst im Container von überall zugänglich, auch außerhalb von Docker.

Der Grund, warum beide getrennt sind, ist IMHO, weil:

  • Die Auswahl eines Host-Ports hängt vom Host ab und gehört daher nicht zur Docker-Datei (andernfalls hängt dies vom Host ab).
  • und oft reicht es aus, wenn ein Dienst in einem Container von anderen Containern aus zugänglich ist.

In der Dokumentation heißt es ausdrücklich:

Die EXPOSEAnweisung macht Ports für die Verwendung in Links verfügbar.

Außerdem erfahren Sie, wie Sie Container verknüpfen Dies ist im Grunde die Kommunikation zwischen Containern, über die ich gesprochen habe.

PS: Wenn Sie dies tun -p, aber nicht EXPOSE, führt Docker eine implizite Aktion durch EXPOSE. Dies liegt daran, dass ein öffentlich zugänglicher Port automatisch auch für andere Docker-Container geöffnet ist. Daher -penthält EXPOSE. Deshalb habe ich es oben nicht als vierten Fall aufgeführt.

Golo Roden
quelle
57
Ich denke, dass Sie mit EXPOSE nicht korrekt sind. Von anderen Containern aus können Sie auf alle Containerports zugreifen, ohne sie verfügbar zu machen. Das habe ich versucht. Der Haken dabei ist, dass die IP-Adresse des Containers nicht vorhersehbar ist. Ich glaube, dass der Link verwendet wird, um anzugeben, welchen Container Sie verbinden möchten (also einen Link zu einer bestimmten Container-IP), und nicht, um die Verbindung zu aktivieren.
Jiri
7
„Wenn Sie irgendwelche von denen nicht angeben“, wäre nützlich , wenn Sie stellte klar , dass mit „denen“ Sie bedeuten EXPOSEund -pund nicht die die drei Aufzählungspunkte dagewesene. Habe mich da ein bisschen verwirrt.
Pithikos
4
Um vollständig zu sein, sollte diese Antwort auch einen vierten möglichen Fall ansprechen: Sie haben nicht angegeben EXPOSE, aber Sie haben angegeben -p. Nach meinem Verständnis ist es in Ordnung , wenn Sie immer -peinzelne Container verwenden und ausführen EXPOSE, dies wegzulassen, aber es wird nützlich / notwendig, wenn Sie -Poder verwenden --link. (Und da Sie nicht wissen, wie andere Personen Ihr Bild verwenden, EXPOSEsollte in allen öffentlichen Bildern angegeben werden.)
GrandOpener
6
In den Dokumenten wird nicht mehr angegeben, dass der Befehl EXPOSE Ports für die Verwendung in Links verfügbar macht.
Lorin Hochstein
11
Downvote, weil dies im Wesentlichen falsch ist. Expose ist im Grunde eine Dokumentation, und wenn Sie es nicht verwenden, wird der Zugriff nicht eingeschränkt. Dies ist ein gefährliches Missverständnis, wenn sich jemand darauf verlässt, um den Zugang zu beschränken.
mc0e
166

Kurze Antwort:

  • EXPOSEist eine Art zu dokumentieren
  • --publish(oder -p) ist ein Weg , der die Abbildung eines Host - Port zu einem laufenden Containerhafen

Beachten Sie darunter:

  • EXPOSEbezieht sich auf Dockerfiles( dokumentieren )
  • --publishbezieht sich auf docker run ...( Ausführung / Laufzeit )

Ports verfügbar machen und veröffentlichen

Im Docker-Netzwerk gibt es zwei verschiedene Mechanismen, an denen Netzwerkports direkt beteiligt sind: Offenlegen und Veröffentlichen von Ports. Dies gilt für das Standardbrückennetz und benutzerdefinierte Brückennetzwerke.

  • Sie machen Ports EXPOSEverfügbar , indem Sie das Schlüsselwort in der Docker-Datei oder das --exposeFlag verwenden, das vom Docker ausgeführt werden soll. Durch das Anzeigen von Ports wird dokumentiert, welche Ports verwendet werden, es werden jedoch keine Ports zugeordnet oder geöffnet . Das Freilegen von Ports ist optional.

  • Sie veröffentlichen Ports mit dem Flag --publishoder --publish-allan docker run. Dadurch wird Docker mitgeteilt, welche Ports auf der Netzwerkschnittstelle des Containers geöffnet werden sollen. Wenn ein Port veröffentlicht wird, wird er einem verfügbaren Port höherer Ordnung (höher als 30000) auf dem Hostcomputer zugeordnet, es sei denn, Sie geben den Port an, dem zur Laufzeit auf dem Hostcomputer zugeordnet werden soll. Sie können den Port, dem Sie auf dem Hostcomputer zuordnen möchten, nicht angeben, wenn Sie das Image erstellen (in der Docker-Datei), da nicht garantiert werden kann, dass der Port auf dem Hostcomputer verfügbar ist, auf dem Sie das Image ausführen .

von: Docker Container Networking

Update Oktober 2019 : Der obige Text befindet sich nicht mehr in den Dokumenten, aber eine archivierte Version ist hier: docs.docker.com/v17.09/engine/userguide/networking/#exposing-and-publishing-ports

Möglicherweise ist die aktuelle Dokumentation die folgende:

Veröffentlichte Ports

Wenn Sie einen Container erstellen, veröffentlicht er standardmäßig keinen seiner Ports für die Außenwelt. Um einen Port zur Verfügung zu stellen , um Dienstleistungen außerhalb von Docker oder zu Docker - Containern, die nicht an den Behälter Netzwerk verbunden ist , verwenden Sie die --publishoder -pFlagge. Dadurch wird eine Firewall-Regel erstellt, die einen Container-Port einem Port auf dem Docker-Host zuordnet.

und finden Sie hier: docs.docker.com/config/containers/container-networking/#published-ports

Ebenfalls,

ENTLARVEN

... Die EXPOSEAnweisung veröffentlicht den Port nicht . Es fungiert als eine Art Dokumentation zwischen der Person, die das Image erstellt, und der Person, die den Container ausführt, über die Ports veröffentlicht werden sollen.

von: Dockerfile-Referenz






Servicezugriff, wenn EXPOSE/ --publishnicht definiert sind:

Bei der Antwort von @Golo Roden heißt es:

"Wenn Sie keine davon angeben, ist der Dienst im Container nur von innerhalb des Containers aus zugänglich."

Vielleicht war das zu der Zeit der Fall, als die Antwort geschrieben wurde, aber jetzt scheint es, dass selbst wenn Sie nicht verwenden, EXPOSEoder --publish, das hostund anderecontainers aus dem gleichen Netzwerk einen Dienst zugreifen können wird Ihnen innerhalb dieser Behälter beginnen kann.

So testen Sie dies:

Ich habe folgendes verwendet Dockerfile. Grundsätzlich beginne ich mit Ubuntu und installiere einen winzigen Webserver:

FROM ubuntu
RUN apt-get update && apt-get install -y mini-httpd

Ich habe builddas Bild als "testexpose" und runeinen neuen Container mit:

docker run --rm -it testexpose bash

Innerhalb des Containers starte ich einige Instanzen von mini-httpd:

root@fb8f7dd1322d:/# mini_httpd -p 80
root@fb8f7dd1322d:/# mini_httpd -p 8080
root@fb8f7dd1322d:/# mini_httpd -p 8090

Ich kann dann curlvom Host oder anderen Containern die Homepage von abrufen mini-httpd.

tgogos
quelle
16
Das ist jetzt die richtige Antwort. Die akzeptierte Antwort basiert anscheinend auf früheren Versionen.
Luke W
Welchen Host-Port haben Sie für Curl verwendet?
Brain Storm
Ich habe die IP des Containers (so etwas wie 172.17.0.2) und alle Ports verwendet, die ich erwähne. Wenn Sie Docker für Mac / Windows verwenden, ist das Netzwerk anders. Es gibt keine docker0Brücke.
Tgogos
Wie kann ich beim Veröffentlichen aller EXPOSEd-Ports mit dem Flag "-P" feststellen, welcher Port auf dem Host verwendet wird?
Sixty4bit
1
@ sixty4bit werfen Sie einen Blick auf diese Frage: Wie finde ich heraus, welchen zufälligen Port Docker gewählt hat? .
Tgogos
9

Siehe die offizielle Dokumentationsreferenz: https://docs.docker.com/engine/reference/builder/#expose

Mit dieser EXPOSEOption können Sie private (Container) und öffentliche (Host) Ports definieren, die zum Zeitpunkt der Image-Erstellung verfügbar gemacht werden sollen, wenn der Container ausgeführt wird, wenn Sie den Container mit ausführen -P.

$ docker help run
...
  -P, --publish-all                    Publish all exposed ports to random ports
...

Der öffentliche Port und das Protokoll sind optional. Wenn kein öffentlicher Port angegeben ist, wird vom Docker ein zufälliger Port auf dem Host ausgewählt, um den angegebenen Container-Port in Dockerfile verfügbar zu machen.

Eine gute Übung ist, keinen öffentlichen Port anzugeben, da nur ein Container pro Host begrenzt ist (ein zweiter Container wirft einen bereits verwendeten Port).

Sie können mit -pin docker runkontrollieren , was öffentlich - Port die freiliegenden Containerhäfen verbindbar sein.

Auf jeden Fall werden keine Ports verfügbar gemacht, wenn Sie weder EXPOSE(mit einem -PDocker-Lauf) noch verwenden -p.

Wenn Sie immer -pbei docker runverwenden, brauchen Sie nicht, EXPOSEaber wenn Sie EXPOSEIhren docker runBefehl verwenden, kann dies einfacher sein, EXPOSEkann nützlich sein, wenn Sie sich nicht darum kümmern, welcher Port auf dem Host verfügbar gemacht wird, oder wenn Sie sicher sind, dass nur ein Container geladen wird.

Tonne
quelle
das ist richtig. Wenn Sie EXPOSE portNumber in Dockerfile haben, denken Sie daran, den Docker-Lauf mit -P aufzurufen.
KunYu Tsai
6

Sie machen Ports mit dem Schlüsselwort EXPOSE in der Docker-Datei oder dem Flag --expose für die Docker-Ausführung verfügbar. Durch das Anzeigen von Ports wird dokumentiert, welche Ports verwendet werden, es werden jedoch keine Ports zugeordnet oder geöffnet. Das Freilegen von Ports ist optional.

Quelle: Github Commit

mzalazar
quelle
3

Die meisten Leute verwenden Docker Compose mit Netzwerken. In der Dokumentation heißt es:

Die Docker-Netzwerkfunktion unterstützt das Erstellen von Netzwerken, ohne dass Ports innerhalb des Netzwerks verfügbar gemacht werden müssen. Detaillierte Informationen finden Sie in der Übersicht über diese Funktion.

Wenn Sie also Netzwerke für die Kommunikation zwischen Containern verwenden, müssen Sie sich keine Gedanken über die Freigabe von Ports machen.

Herm
quelle
-5

EXPOSE wird verwendet, um den Port des lokalen Portcontainers zuzuordnen, dh wenn Sie in der Docker-Datei wie expose angeben

EXPOSE 8090

Durch den Vorgang wird der lokale Host-Port 8090 dem Container-Port 8090 zugeordnet

Mansur Ali
quelle