Wie ordne ich einem vorhandenen Docker-Container eine Portzuordnung zu?

436

Ich bin nicht sicher, ob ich hier etwas falsch verstanden habe, aber es scheint, dass es nur möglich ist, Portzuordnungen festzulegen, indem aus einem Image ein neuer Container erstellt wird. Gibt es eine Möglichkeit, einem vorhandenen Docker-Container eine Portzuordnung zuzuweisen?

Thasmo
quelle
3
Die Verwendung von iptables kann wie
folgt funktionieren
2
Ich vermute, das ist beabsichtigt. Docker versucht, Sie zu zwingen, "wiederholbar" zu sein, und der Container ist eine Art "Aufzeichnungssystem". Alles, was Sie als Schritt tun, der den Container nicht beeinflusst, ist ein leicht verlorener manueller Schritt. Anders gesagt: Sie möchten, dass Ihr Container die gesamte Konfiguration darstellt, die für den Betrieb erforderlich ist. Wenn Sie also einen neuen Port öffnen möchten, müssen Sie einen neuen Container erstellen.
Lance Kind
2
Alte Frage und ich beantworte sie nicht, aber ich möchte sagen, dass Sie und die Leute, die diese Frage und Antworten auf den Kopf stellen, das Konzept des Dockers möglicherweise völlig missverstanden haben. Docker sind für zustandslose Anwendungen vorgesehen, die um ein Vielfaches vergrößert oder verkleinert werden können. Sie sollten niemals etwas im Container für eine Produktionsumgebung beibehalten, das nicht neu erstellt werden kann. Wenn Sie fortbestehen müssen, ordnen Sie die Verzeichnisse zu. Docker ist nicht so etwas wie eine "leichte VM". Vielleicht suchen Sie nach linuxcontainers.org. Lxd basiert auf dem Docker-Konzept, aber mit Blick auf eine "leichte VM".
Edgar Carvalho
Für den Fall, dass dies hilfreich sein könnte, können Sie mit dem Tool "Kitematic" bereits laufenden Containern eine Portzuordnung hinzufügen. Dies sollte bedeuten, dass es einen Docker-Befehl geben muss, um genau dasselbe zu tun, aber mit ein wenig googeln :) Viel Glück
Yaffah

Antworten:

298

Sie können die Portzuordnung ändern, indem Sie die hostconfig.jsonDatei direkt unter bearbeiten/var/lib/docker/containers/[hash_of_the_container]/hostconfig.json

Sie können den [Hash_des_Containers] über den docker inspect <container_name>Befehl ermitteln, und der Wert des Felds "Id" ist der Hash.

1) stop the container 
2) stop docker service (per Tacsiazuma's comment)
3) change the file
4) restart your docker engine (to flush/clear config caches)
5) start the container

Mit diesem Ansatz müssen Sie also kein Bild erstellen. Sie können hier auch das Neustart-Flag ändern.

PS Sie können https://docs.docker.com/engine/admin/ besuchen , um zu erfahren, wie Sie Ihre Docker-Engine gemäß Ihrem Host-Computer korrekt neu starten. Ich habe sudo systemctl restart dockermeine Docker-Engine, die unter Ubuntu 16.04 ausgeführt wird , neu gestartet

holdfenytolvaj
quelle
17
Wenn Docker stoppt, scheint es Ihre Änderungen zu überschreiben, also 2. Docker stoppen, 3. Datei ändern, 4. Docker-Engine starten
Tacsiazuma
5
Ich habe das oben versucht und es funktioniert. Für weitere Details siehe: mybrainimage.wordpress.com/2017/02/05/…
rohitmohta
11
Es ist wichtig , Behälter, Stop Docker Motor und Wechsel zu stoppen beide hostconfig.jsonund config.v2.jsondiese Arbeit zu machen. Verwenden Sie den von @rohitmohta bereitgestellten Link, um die Details anzuzeigen.
Kalpak Gadre
5
hat für mich funktioniert, nur eine Sache, wenn Sie die Docker-App auf einem Mac verwenden, befolgen Sie die Anweisungen hier, um zum Ordner / var / lib / docker / container zu gelangen: stackoverflow.com/a/41226917/2048266 , grundsätzlich ausführen screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/ttySobald Sie die tty zum Laufen gebracht haben, können Sie Navigieren Sie zu / var / lib /
docker
14
Kann mir jemand für Windows den Speicherort des Conatiners-Ordners mitteilen?
Vijay
463

Ich interessiere mich auch für dieses Problem.

Wie bei @Thasmo erwähnt, können Portweiterleitungen NUR mit dem Befehl docker run(und docker create) angegeben werden.
Andere Befehle haben docker startkeine -pOption und zeigen docker portnur aktuelle Weiterleitungen an.

Um Portweiterleitungen hinzuzufügen, befolge ich immer die folgenden Schritte:

  1. Container nicht mehr laufen lassen

    docker stop test01
    
  2. Commit den Container

    docker commit test01 test02
    

    HINWEIS: Das obige test02ist ein neues Bild, das ich aus dem test01Container konstruiere .

  3. Wieder Lauf vom commited Bild

    docker run -p 8080:8080 -td test02
    

Dabei ist der erste 8080 der lokale Port und der zweite 8080 der Containerport.

Fujimoto Youichi
quelle
14
Was ist, wenn ich den Namen test01 behalten möchte?
user69715
12
Weiß jemand, ob es ein offenes Problem mit Docker gibt, mit dem die Portspezifikation (--publish) zugelassen werden kann docker start?
Elijah Lynn
8
Und was passiert mit den Volumes in diesem Szenario?
Andrew Savinykh
78
Dies ist eine schreckliche Lösung, ich habe keine Ahnung, wie es geschafft hat, 250 Upvotes zu verdienen. Vielleicht wussten diejenigen, die so gut bewertet waren, nicht, welche Art von Chaos diese Lösung verursacht. Ja, es ist schrecklich und es ist gleichbedeutend damit, einen neuen Container zu starten, der an einem anderen Port ausgeführt wird.
Arrrr
25
@Arrrr Vielleicht möchten Sie eine bessere Antwort hinterlassen? Ich bin sicher, wir würden uns alle freuen, wenn Sie uns den viel besseren Weg dazu nennen würden.
Crockeea
40

Wenn mit "vorhanden" "ausgeführt" gemeint ist, ist es (derzeit) nicht möglich, eine Portzuordnung hinzuzufügen.

Sie können jedoch dynamisch eine neue Netzwerkschnittstelle mit z. B. Pipework hinzufügen , wenn Sie einen Dienst in einem laufenden Container verfügbar machen müssen, ohne ihn anzuhalten / neu zu starten.

jpetazzo
quelle
4
Dies sollte die beste Antwort sein. Prägnant und es geht um die Frage von OP, die keiner der anderen tut! Manchmal ist ein negatives Ergebnis ein Ergebnis!
Teilweise bewölkt
19

Sie sind sich nicht sicher, ob Sie die Portzuordnung auf einen laufenden Container anwenden können. Sie können die Portweiterleitung anwenden, während Sie einen Container ausführen, der sich vom Erstellen eines neuen Containers unterscheidet.

$ docker run -p <public_port>:<private_port> -d <image>  

startet den Container. In diesem Tutorial wird die Portumleitung erläutert.

Rajalokan
quelle
2
Ja, es scheint also nur möglich zu sein, Optionen wie die Portzuordnung bei der Containererstellung festzulegen.
Thasmo
20
Zu Ihrer Information, diese Antwort ist nicht ganz richtig. docker runerstellt und startet einen neuen Container. Es ist gleichbedeutend mit Tun, docker creategefolgt von docker start.
Trevor Sullivan
19

Das Bearbeiten von hostconfig.json scheint jetzt nicht zu funktionieren. Es endet nur damit, dass dieser Port verfügbar gemacht, aber nicht für den Host veröffentlicht wird. Das Festschreiben und Neuerstellen von Containern ist für mich nicht der beste Ansatz. Niemand erwähnt docker network?

Die beste Lösung wäre die Verwendung eines umgekehrten Proxys innerhalb desselben Netzwerks

  1. Erstellen Sie ein neues Netzwerk, wenn sich Ihr vorheriger Container nicht in einem benannten befindet.

    docker network create my_network

  2. Verbinden Sie Ihren vorhandenen Container mit dem erstellten Netzwerk

    docker network connect my_network my_existing_container

  3. Starten Sie einen umgekehrten Proxy-Dienst (z. B. nginx), der die benötigten Ports veröffentlicht und sich demselben Netzwerk anschließt

    docker run -d --name nginx --network my_network -p 9000:9000 nginx

    Entfernen Sie optional die Datei default.conf in nginx

    docker exec nginx rm /etc/nginx/conf.d/default.conf

  4. Erstellen Sie eine neue Nginx-Konfiguration

    server
    {
        listen 9000;
    
        location / {
            proxy_pass http://my_existing_container:9000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
    

    Kopieren Sie die Konfiguration in den Nginx-Container.

    docker cp ./my_conf.conf nginx:/etc/nginx/conf.d/my_conf.conf

  5. Starten Sie nginx neu

    docker restart nginx

Vorteile : Um neue Ports zu veröffentlichen, können Sie den Nginx-Container sicher stoppen / aktualisieren / neu erstellen, ohne den Geschäftscontainer zu berühren. Wenn Sie für nginx keine Ausfallzeit benötigen, können Sie weitere umgekehrte Proxy-Dienste hinzufügen, die demselben Netzwerk beitreten. Außerdem kann ein Container mehr als einem Netzwerk beitreten.

Bearbeiten:

Um Proxy-Nicht-http-Dienste umzukehren, ist die Konfigurationsdatei etwas anders. Hier ist ein einfaches Beispiel:

upstream my_service {
    server my_existing_container:9000;
}

server {
    listen 9000;
    proxy_pass my_service;
}
Sean C.
quelle
1
Es ist erstaunlich und praktisch, aber für Unternehmenssysteme scheint dieser Ansatz zu verschleiern. Es ist viel besser, ein einziges System den Workflow steuern zu lassen.
Afshin
1
@Afshin Nun, für Unternehmenssysteme oder Projekte ist diese Lösung meiner Meinung nach besser als das Neuerstellen (verursacht Ausfallzeiten) oder das Hacken der Datei hostconfig.json (zumindest nicht offiziell eingeführt). Der zusätzliche Container macht nur den internen Port Ihres Geschäftscontainers verfügbar, anstatt Änderungen daran vorzunehmen.
Sean C.
1
Super Ansatz. Ich musste nginx anders konfigurieren, damit mein Container hinter einem Proxy funktioniert, aber es scheint mir die richtige Vorgehensweise zu sein. Funktioniert auch für die blaugrüne Bereitstellung.
Brooks DuBois
17

In Fujimoto ist Youichis Beispiel test01ein Container, während test02es sich um ein Bild handelt.

Bevor docker runSie dies tun , können Sie den Originalcontainer entfernen und dem Container erneut denselben Namen zuweisen:

$ docker stop container01
$ docker commit container01 image01
$ docker rm container01
$ docker run -d -P --name container01 image01

(Verwenden -P, um Ports zufälligen Ports auszusetzen, anstatt sie manuell zuzuweisen).

Luca
quelle
12
Bitte beachten Sie. Sie verlieren alle Ihre Daten, abhängig von der darin enthaltenen Anwendung.
Barry
14

Wenn Sie es ausführen docker run <NAME>, wird ein neues Bild erzeugt, das höchstwahrscheinlich nicht Ihren Wünschen entspricht.

Wenn Sie ein aktuelles Bild ändern möchten, gehen Sie wie folgt vor:

docker ps -a

Nehmen Sie die ID Ihres Zielcontainers und gehen Sie zu:

cd /var/lib/docker/containers/<conainerID><and then some:)>

Stoppen Sie den Container:

docker stop <NAME>

Ändern Sie die Dateien

vi config.v2.json

"Config": {
    ....
    "ExposedPorts": {
        "80/tcp": {},
        "8888/tcp": {}
    },
    ....
},
"NetworkSettings": {
....
"Ports": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],

Und Datei ändern

vi hostconfig.json

"PortBindings": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],
     "8888/tcp": [
         {
             "HostIp": "",
             "HostPort": "8888"
         } 
     ]
 }

Starten Sie Ihren Docker neu und es sollte funktionieren.

Docker-Noob
quelle
2
Dies funktionierte bei Docker Version 17.09.0-ce nicht. Nach dem Start wurden die Container-Konfigurationsdateien wieder auf alte Werte überschrieben.
Thegeko
3
Starten
Sie den
1
das funktioniert! tks! 1. Container stoppen, 2. Dateien ändern, 3. Docker neu starten, 4. Container zurück
starten
12

Der andere Weg um Sie herum, wenn Sie mit Docker-Tiefenkonfiguration IPtables nicht vertraut sind, wäre Ihr Freund.

iptables -t nat -A DOCKER -p tcp --dport ${YOURPORT} -j DNAT --to-destination ${CONTAINERIP}:${YOURPORT}

iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source ${CONTAINERIP} --destination ${CONTAINERIP} --dport ${YOURPORT}

iptables -A DOCKER -j ACCEPT -p tcp --destination ${CONTAINERIP} --dport ${YOURPORT}

Dies ist nur ein Trick, der nicht empfohlen wird. Dies funktioniert mit meinem Szenario, da ich den Container nicht stoppen konnte. Ich hoffe, dass er Ihnen auch helfen wird.

Mansur Ali
quelle
Das ist eine großartige Antwort! Vielen Dank! Wenn ich will , kartieren DOCKER_PORTzuMACHINE_PORT , sollten die Teile geändert werden?
Ciprian Tomoiagă
Beachten Sie, dass Docker nichts über diese manuelle Ergänzung weiß. SO-Einträge werden nicht entfernt, wenn Sie den Dienst später neu starten, wobei der Docker die Ports ordnungsgemäß verfügbar macht. Wenn sich also etwas ändert, überprüfen Sie iptables unbedingt sorgfältig. Achten Sie besonders auf doppelte Einträge!
Anthony
8

Wir verwenden handliche Tools wie ssh, um dies einfach zu erreichen.

Ich habe Ubuntu Host und Ubuntu-basiertes Docker-Image verwendet.

  1. Im Docker ist openssh-client installiert.
  2. Außerhalb des Dockers (Hosts) ist der OpenSh-Server-Server installiert.

Wenn ein neuer Port zugeordnet werden muss,

Führen Sie im Docker den folgenden Befehl aus

ssh -R8888:localhost:8888 <username>@172.17.0.1

172.17.0.1 war die IP der Docker-Schnittstelle (Sie können diese erhalten, indem Sie sie ifconfig docker0 | grep "inet addr" | cut -f2 -d":" | cut -f1 -d" "auf dem Host ausführen ).

Hier hatte ich den lokalen 8888-Port wieder den Hosts 8888 zugeordnet. Sie können den Port nach Bedarf ändern.

Wenn Sie einen weiteren Port benötigen, können Sie den SSH beenden und mit dem neuen Port eine weitere Zeile -R hinzufügen.

Ich habe dies mit Netcat getestet.

Melchi
quelle
2
  1. Stoppen Sie die Docker-Engine und diesen Container.
  2. Zum /var/lib/docker/containers/${container_id}Verzeichnis gehen und bearbeitenhostconfig.json
  3. Bearbeiten PortBindings.HostPort Sie, dass Sie die Änderung möchten.
  4. Starten Sie die Docker-Engine und den Container.
ezileli
quelle
0

Als Ergänzung zur Antwort von @ Fujimoto-Youichi

Sie können $ docker run -P CONTAINER Ports auch zufällig zuordnen, während Sie Ihren Container erstellen. Seien Sie jedoch vorsichtig mit Sicherheitsaspekten!

-PGleichung zu --publish-all: "Es veröffentlicht alle exponierten Ports in zufälligen Ports",

Führen Sie dann die docker inspect CONTAINERZuordnung der Fin-Ports aus, wie in der folgenden Abbildung dargestellt:

. Docker Inspect für einen Rabbitmq-Container zeigt alle Ports Mapping

Lesen Sie mehr über docker run -P in Docker Run

ans1genie
quelle
Das heißt NICHT, den Port einem vorhandenen LIVE-Container hinzuzufügen!
Anthony
Wie oben im Kommentar erwähnt, ist es nur ein Extra !! Und für den Befehl: wie aus dem Docker-Dokumentationslink bereitgestellt: -publish-all, -P Veröffentlichen Sie alle exponierten Ports an zufälligen Ports
ans1genie
-1

Für Windows- und Mac-Benutzer gibt es eine weitere recht einfache und benutzerfreundliche Möglichkeit, den Zuordnungsport zu ändern:

  1. kitematic herunterladen

  2. Gehen Sie zur Einstellungsseite des Containers. Auf der Registerkarte Ports können Sie den veröffentlichten Port dort direkt ändern.

  3. Starten Sie den Container erneut

John
quelle
2
Ich habe diesen Ansatz versucht. Kinematic hat die Port-Mappings tatsächlich angewendet. Um sie jedoch anzuwenden, wurde mein Container aus dem Originalbild neu erstellt. Wenn Sie also Angst haben, die im Container selbst vorgenommenen Änderungen zu verlieren, verwenden Sie diese Methode nicht.
VeganHunter
1
Ich habe das vorgezogen, ich verstehe, dass es die Frage nicht beantwortet und einen neuen Container erstellt. Aber zumindest funktioniert es und dieses SO-Ergebnis wurde während meiner Suche angezeigt. +1
2b77bee6-5445-4c77-b1eb-4df3e5
-7

Kurze Antwort: Sie können einem vorhandenen Docker-Container keine Portzuordnung zuweisen

Sie brauchen einen neuen Container ... kümmern Sie sich darum.

surfer190
quelle
4
Keine Notwendigkeit für die Einstellung. Auch dieser Antwort fehlen völlig Details.
Lovefaithswing
1
Keine Notwendigkeit für das Detail. Der Ton ist entscheidend, um diese zeitsparende Antwort und die Vergänglichkeit von Containern zu vermitteln.
surfer190
-11

Wenn Sie einfach den Port des laufenden Containers ändern möchten, gehen Sie wie folgt vor:

  1. vorhandenen Container stoppen

    sudo docker stop NAME

  2. Starten Sie jetzt mit der neuen Portzuordnung neu

    sudo docker run -d -p 81:80 NAME

wohingegen:

"-d" zum Hintergrund / Deamon des Dockers

"-p" aktiviert die Portzuordnung

Externer (exponierter) Port "81", auf den Sie mit Ihrem Browser zugreifen

Interner Docker-Container-Listen-Port "80"

Vlad Gulin
quelle
4
Das ist einfach falsch. In dem docker runBefehl, NAMEder Name des Bildes einen Behälter aus laufen, wohingegen in docker stopdem NAMEauf den Namen des Behälters zu stoppen bezieht.
Jonatan
1
"Docker Run" erstellt einen neuen Container. Es kann nicht derselbe Containername verwendet werden, der gestoppt wurde, da Sie nur einen Container mit diesem Namen haben können. Sie müssten also Folgendes tun: "Docker stoppen NAME", Docker-Container rm NAME und dann "Docker-Run -d -p 81:80 NAME", wie Sie es geschrieben haben.
Lance Kind