Moby: Docker-Schwarmmodus: Ports auf 127.0.0.1 sind 0.0.0.0 ausgesetzt

Erstellt am 2. Apr. 2017  ·  53Kommentare  ·  Quelle: moby/moby

Beschreibung

Im Docker-Schwarmmodus führt das Binden eines Ports an 127.0.0.1 dazu, dass der Port auch auf 0.0.0.0 geöffnet ist. Dies kann ein schwerwiegendes Sicherheitsproblem sein und sollte in der Dokumentation erläutert werden.

Schritte zum Reproduzieren des Problems:

  1. Erstellen Sie einen Dienst, z. B. MongoDB, in Ihrer Datei docker-compose.swarm.yml und veröffentlichen Sie den Port 27017 in localhost:
  mongodb:
    image: mongo:3.2
    volumes:
      - ./persistent-data/mongodb:/data
      - ./persistent-data/mongodb/db:/data/db
    networks:
      data:
        aliases:
          - mongo.docker
    logging:
      driver: syslog
      options:
        syslog-address: "udp://10.129.26.80:5514"
        tag: "docker[mongodb]"
    ports:
      - "127.0.0.1:27017:27017"
    deploy:
      placement:
        constraints: [node.labels.purpose == main-data]
  1. Stellen Sie Ihren Schwarm bereit
  2. Überprüfen Sie mit netcat, ob der Port von außerhalb Ihres Schwarms geöffnet ist

Beschreiben Sie die Ergebnisse, die Sie erhalten haben:

nc -vz PUBLIC_NODE_IP 27017
found 0 associations
found 1 connections:
[...]
Connection to PUBLIC_NODE_IP port 27017 [tcp/*] succeeded!

Beschreiben Sie die erwarteten Ergebnisse:
Der Port ist nur unter 127.0.0.1 verfügbar, zumindest in den Schwarmknoten, auf denen dieser Dienst ausgeführt wird.

Zusätzliche Informationen, die Sie für wichtig halten (z. B. tritt das Problem nur gelegentlich auf):

Ausgabe von docker version :

Docker version 17.03.1-ce, build c6d412e

Ausgabe von docker info :

Docker-Informationen für Schwarmmanager:

Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 1
Server Version: 17.03.1-ce
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 3
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins: 
 Volume: local
 Network: bridge host macvlan null overlay
Swarm: active
 NodeID: pk7ulemi0z0chgtsg0azfrjz5
 Is Manager: true
 ClusterID: 27etomlyjvtmygrm6rcdgr2ni
 Managers: 1
 Nodes: 6
 Orchestration:
  Task History Retention Limit: 5
 Raft:
  Snapshot Interval: 10000
  Number of Old Snapshots to Retain: 0
  Heartbeat Tick: 1
  Election Tick: 3
 Dispatcher:
  Heartbeat Period: 5 seconds
 CA Configuration:
  Expiry Duration: 3 months
 Node Address: 10.129.26.165
 Manager Addresses:
  10.129.26.165:2377
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 4ab9917febca54791c5f071a9d1f404867857fcc
runc version: 54296cf40ad8143b62dbcaa1d90e520a2136ddfe
init version: 949e6fa
Security Options:
 apparmor
 seccomp
  Profile: default
Kernel Version: 4.4.0-64-generic
Operating System: Ubuntu 16.04.2 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 992.4 MiB
Name: <HIDDEN>
ID: IMOK:QIR7:WU5Y:WTPP:EPRQ:F77G:ULGE:WOG4:O7S7:6AFE:V7QG:2XEK
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: <HIDDEN>
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

Zusätzliche Umgebungsdetails (AWS, VirtualBox, physisch usw.):
Getestet an den Tröpfchen von Digital Ocean.

areswarm kinbug

Hilfreichster Kommentar

Wirklich enttäuscht, dass einige der Docker-Entwickler fast zwei Jahre lang einen gültigen und sehr nützlichen Anwendungsfall ignorieren, wenn diese Funktionalität vorhanden sein muss: Wenn Sie eine enthaltene relationale Datenbank als Schwarmdienst an die lokale Schnittstelle binden möchten, um über den SSH-Tunnel sicher darauf zuzugreifen . Derzeit ist dieses Szenario nicht möglich.

Alle 53 Kommentare

Ja, dies sollte einen Fehler ausgeben. Dienste "veröffentlichen" (standardmäßig) über das "Ingress" -Netzwerk und unterstützen die Angabe einer IP-Adresse nicht, da nicht vorhergesagt werden kann, auf welchem ​​Knoten sie landen (daher nicht bekannt, welche IP-Adressen verfügbar sind - obwohl 127.0 .0.1 könnte möglich sein). Dieses Problem verfolgt die Funktion https://github.com/docker/docker/issues/26696 (und dieses "Epos" verfolgt andere Optionen, die (noch) nicht von den Diensten https://github.com/docker/docker/issues unterstützt werden / 25303)

Der Fehler hier ist, dass Docker einen Fehler erzeugen sollte, anstatt die Option stillschweigend zu ignorieren. reproduzierbar mit dieser minimalen Docker-Compose-Datei;

version: "3.2"
services:
  mongodb:
    image: nginx:alpine
    ports:
      - "127.0.0.1:27017:80"

ping @dnephin @vdemeester

@ fer2d2 Wenn Sie im Schwarmmodus etwas veröffentlichen ( ports für stack deploy ), wird es im Netzwerk ingress veröffentlicht und ist daher öffentlich. Es gibt ein paar Möglichkeiten, sich fortzubewegen, aber setzen Sie kind/bug darauf, weil wir die Leute zumindest davor warnen sollten, wenn Sie ein stack deploy mit Ports machen, die diese Notation haben (dh host:port:port ).

Um dies zu umgehen, gibt es einige Möglichkeiten:

  • Zunächst sollten Sie mongo -Ports nur veröffentlichen, wenn Sie möchten, dass sie öffentlich sind. Andernfalls ist sie über das Namenserkennungspaket im Docker verfügbar (ein anderer Container / Dienst im selben Netzwerk kann sie über mongo DNS-Name).
  • Wenn Sie es auf dem Host und nicht in ingress veröffentlichen möchten (also nicht öffentlich schwärmen, nur auf dem Host, auf dem es ausgeführt wird, genauso wie ohne Schwarmmodus), müssen Sie die erweiterte Syntax des Ports verwenden .
    ports:
      - mode: host
        target: 80
        published: 9005

Es macht dasselbe wie docker run -p 80:9005 … , bindet es also an 0.0.0.0 , ist jedoch auf den Host beschränkt.

Aber wie @thaJeztah sagte: "Der Fehler hier ist, dass Docker einen Fehler erzeugen sollte, anstatt die Option stillschweigend zu ignorieren."

/ cc @mavenugo @aboch, um zu sehen, ob es eine Möglichkeit gibt, es tatsächlich an eine bestimmte IP zu binden? (Wirklich schwierig zu erreichen, da die IP des Knotens anders sein wird.)

@vdemeester Kann ich mit dieser Notation localhost als Hostziel angeben?

    ports:
      - mode: host
        target: 127.0.0.1:80
        published: 9005

Da es sich um ein erweitertes Format für die Portkonfiguration handelt , sollte es ordnungsgemäß funktionieren.

Danke im Voraus

Es scheint, dass sowohl Ziel als auch veröffentlicht in der langen Syntax als ganzzahliger Typ erzwungen werden

Ich denke, dies ist nicht das gewünschte Verhalten, wenn Sie über SSH-Tunnel eine Verbindung zu einigen Diensten herstellen. Zum Beispiel, wenn Sie über SSH Tunnel MySQL oder MongoDB - Server auf 127.0.0.1 und eine Verbindung zu wollen, mit Docker Swarm müssen Sie die Datenbank - Port auf 0.0.0.0 aussetzen oder einen benutzerdefinierten Datenbankcontainer mit SSH erstellen innen läuft (und beiden Optionen sind sehr unsicher).

Es gibt viele Datenbankclients, die SSH-Tunnel verwenden, wie SQL Workbench oder Robomongo, die aufgrund dieser Einschränkung nicht verwendet werden können (spezifische Schnittstellenbindung).

Wir haben in unserem Unternehmen das gleiche Problem wie @ fer2d2 und versuchen, Mongobooster über einen SSH-Tunnel mit einem Docker-Schwarm zu verbinden. Die einzige Lösung, die wir gefunden haben, war das Öffnen des 27017-Ports und das Schützen der Datenbank mit Benutzer und Passwort.

Irgendwelche Neuigkeiten?

+1

+1

Ein weiterer Anwendungsfall für das Zulassen der IP- Adresse: Port- Paar für die Portzuordnung in Langform ist für Anycast-Adressen oder andere Adressen, die Loopback zugeordnet werden können. Diese ähneln einer 127.0.0.1-Adresse, da sie nur im Loopback-Netzwerk sichtbar sind. Ein Dienst, der auf Knoten mit dieser Eigenschaft beschränkt ist, möchte möglicherweise einen Port nur für eine Anycast-Adresse verfügbar machen, um Portkollisionen zu vermeiden und gleichzeitig iptables-Regeln für die Portübersetzung zu vermeiden.

Kann es möglicherweise eine Option sein, wenn Sie angeben:

placement:
        constraints:
          - node.id ==

Prost

+1

+1

+1

für mich habe ich dieses problem so gelöst:

iptables -I DOCKER-USER -i eth0 -j DROP
iptables -I DOCKER-USER -m state --state RELATED,ESTABLISHED -j ACCEPT

Der Docker berührt diese Regeln nicht. fügt einfach deine eigenen hinzu
-A DOCKER-USER -j RETURN
Infolgedessen lauscht der Port zwar auf 0.0.0.0, ist aber über die externe Schnittstelle eth0 nicht zugänglich

Dieses Verhalten verstößt gegen "Standardmäßig sicher", und das Einfügen einer Notiz in die Dokumente ist nicht gut genug. Im Moment sollte es einen Fehler verursachen.

Es hängt auch mit dem Modus zusammen: Ingress / Host (diese beiden Probleme scheinen in der Diskussion verwirrt zu sein). Der Eingangsmodus verhindert nicht, dass der Dienst an lokale Adressen auf allen Knoten gebunden wird, nicht jedoch an externe Adressen. Daher sollte 127.xxx erlaubt sein. (Im Nicht-Schwarm-Modus (mit Docker-Lauf) binde ich an 127.0.0.2:80 und 127.0.0.3:80 usw., um mehrere Server lokal in der Entwicklung zu testen.)

Das andere Problem ist, dass der Eingangsmodus die Standardeinstellung ist. Dies ist unerwartet und führt auch zu einem Sicherheitsproblem. Ich habe gerade versucht, einen Dienst auf einem Knoten zu starten, der sich auf einen privaten Teil des Netzwerks beschränkt, dessen Port an 127.0.0.3:80 gebunden ist. Es wurde dann auch an die öffentliche Schnittstelle des öffentlichen Knotens gebunden. (Das bedeutet, dass die IP-Adresse stillschweigend ignoriert und der Eingangsmodus stillschweigend verwendet wird und meine Daten öffentlich sind).

Anwendungsfälle

  • Anwendungsfälle, die mich beeinflusst haben (definitiv real)

    • 1 Binden Sie an den Port eines bestimmten Knotens, da der Port auf anderen Knoten verwendet wird. Sie können hierfür den Host-Modus verwenden, aber die Standardeinstellung ist eine Überraschung.

    • 2 Binden Sie an den Port eines bestimmten Knotens, da andere Knoten über öffentliche Schnittstellen verfügen. Sie können hierfür den Host-Modus verwenden, aber die Standardeinstellung verstößt gegen "Standardmäßig sicher" .

    • 3 Binden Sie lokal, da Sie nicht möchten, dass es für andere Hosts sichtbar ist. Die Standardeinstellung verstößt gegen "Standardmäßig sicher".

    • 4 Binden Sie an 127.0.0.3, da auf Ihrem Entwicklungscomputer viele Dinge gespeichert sind und 127.0.0.1 von diesem Port verwendet wird. Verwenden Sie /etc/hosts , damit jeder Domain-Name an einen anderen Container gesendet wird. Dies funktioniert mit docker run , aber nicht mit compose.

  • Andere Anwendungsfälle

    • Binden Sie an eine bestimmte Schnittstelle, z. B. 192.168.0.x, da dies ein internes Netzwerk ist. Standard ist ein Verstoß gegen "Standardmäßig sicher".

    • Binden Sie an einen bestimmten Knoten, ohne den Dienst auf diesem Knoten auszuführen. Dies ist ein ähnlicher Anwendungsfall wie 1 oder 2, jedoch ohne Verwendung von Einschränkungen. Der Verkehr würde durch den Schwarm geleitet.

Also zusammenfassend

  • Das Ignorieren der IP-Adresse und das Binden an 0.0.0.0 sowie der Standard-Eingangsmodus verstoßen beide gegen "Standardmäßig sicher". Fehler sollten ausgegeben werden, wenn die IP-Adresse angegeben und die Dokumente aktualisiert werden. Ein Fehler sollte ausgegeben werden, wenn der Modus nicht angegeben ist (kein Standard) und die Dokumente aktualisiert werden. (Dies behebt das Modusproblem und stoppt überraschende Sicherheitsprobleme.)
  • Im Host-Modus können dann IP-Adressen unterstützt werden.
  • Unterstützung für IP-Adressen im Eingangsmodus, die auf die lokalen Adressen 127.xxx beschränkt sind, könnte hinzugefügt werden. (Unterschiedliche lokale Adressen, z. B. 127.0.0.2 und 127.0.0.3, sollten als unterschiedlich behandelt werden (nur an das Betriebssystem übergeben).)

Das Zulassen der Bindung an lokale Adresse ist nützlich für eingeschränkte Knoten. Das Binden an eine bestimmte Adresse zulassen, würde für einen eingeschränkten Knoten funktionieren oder durch den Schwarm zu einer der Adressen auf einem der Knoten geleitet werden (möglicherweise nur im Eingangsmodus). Dieses Routing ist bereits abgeschlossen

@ richard-delorenzi Moby akzeptiert derzeit nicht einmal eine Host-IP. Außerhalb der Funktionsanforderung klingt dies wie ein clientseitiges Problem ... insbesondere, wie das Compose-Yaml in der Docker-CLI übersetzt wird.

Die Funktionsweise von Ingress ist ziemlich gut dokumentiert, aber ich bin mir einig, dass dies ein schlechtes Verhalten in der CLI ist.

+1

+1

+1

Ich habe eine Art Problemumgehung, die ich verwende. Ich führe eigenständige Container aus und verbinde sie mit einem Netzwerk namens "Core", das von allen unseren Back-End-Diensten (Mongo, Elasticsearch, Influxdb usw.) verwendet wird, die in einem Schwarm ausgeführt werden.

Ich kann nicht sehen, wie das in einer Compose-Datei gemacht wird, also führen wir nur eigenständige Container wie folgt aus:

docker run --name kibana --rm -d -v /var/lib/kibana:/usr/share/kibana/config -p 127.0.0.1:5601:5601 --network core docker.elastic.co/kibana/kibana:6.1.2

docker run --name chronograf --rm -d -v /var/lib/chronograf:/var/lib/chronograf -p 127.0.0.1:8888:8888 --network core chronograf:1.4 chronograf --influxdb-url=http://influxdb:8086

Nach dem Starten dieser zeigt Docker ps die neuen Container als an 127.0.0.1 gebunden an. Amen. Ich kann dann von meiner lokalen Workstation aus zum Docker-Host tunneln, um einen sicheren Zugriff zu erhalten.

ssh -i my_ssh_key.pem [email protected]  -L 8888:localhost:8888  -L 5601:localhost:5601 -N

Über meinen Browser kann ich dann eine Verbindung zu http: // localhost : 8888 oder http: // localhost : 5601 herstellen

Funktioniert bei mir.

Für den Fall, dass ein UNIX-Socket einen TCP / IP-Socket 127.0.0.1 ersetzen kann, finden Sie hier eine mögliche Problemumgehung, die ich für Fluent-Bit implementiert habe

Vielleicht könnte das Hinzufügen einer weiteren Option zu mode helfen. So etwas wie local zusätzlich zu host und ingress .

Bitte entfernen Sie den Wortlaut "Verwendbare Sicherheit: Moby bietet sichere Standardeinstellungen, ohne die Benutzerfreundlichkeit zu beeinträchtigen." auf der moby Readme-Datei . Dies ist definitiv falsche Werbung, siehe Kommentar von @ richard-delorenzi.

Dienste veröffentlichen standardmäßig keine Ports und sind daher nur verfügbar, wenn Sie angeben, dass sie einen Port veröffentlichen sollen. Die Bindung an eine bestimmte IP-Adresse wird derzeit nicht unterstützt. Wenn auf Ihren Dienst nicht zugegriffen werden soll, veröffentlichen Sie keine Ports und stellen Sie über ein internes (Overlay-) Netzwerk eine Verbindung zum Dienst her.

Das Hinzufügen von Unterstützung für das Binden an eine IP-Adresse wird unter https://github.com/moby/moby/issues/26696 erläutert, ist jedoch nicht trivial zu implementieren (unter Berücksichtigung von IP-Adressen, die nicht "localhost" sind).

Beim Bereitstellen eines Stapels wurde eine Warnung hinzugefügt.

docker stack deploy -c- test <<'EOF'
version: '3'
services:
  web:
    image: nginx:alpine
    ports:
      - "127.0.0.1:8080:80"
EOF

WARN[0000] ignoring IP-address (127.0.0.1:8080:80/tcp) service will listen on '0.0.0.0' 
Creating network test_default
Creating service test_web

Beim Versuch, einen Dienst mit einer angegebenen IP-Adresse bereitzustellen, kann er nicht mit einem Fehler bereitgestellt werden.

docker service create -p 127.0.0.1:9090:80 nginx:alpine
invalid argument "127.0.0.1:9090:80" for "-p, --publish" flag: hostip is not supported
See 'docker service create --help'.

@dalu Wenn Ihr System dem Internet ausgesetzt ist und Sie Docker angewiesen haben, einen Dienst im Cluster

Auf jeden Fall hat dieses Compose-Format, das Entwickler und tatsächliche Bereitstellungen erschüttert, einige grobe Kompromisse.

@ cpuguy83

Wenn Ihr System dem Internet ausgesetzt ist und Sie Docker angewiesen haben, einen Dienst im Cluster bereitzustellen, bin ich mir nicht sicher, warum die Erwartung etwas anderes sein würde.

Nee. Warum sollte es öffentlich zugänglich sein, wenn jemand es an eine nicht öffentliche IP wie 127.0.0.1 oder 10.0.0.0 bindet? Eigentlich ist das die richtige Antwort:

Die Bindung an eine bestimmte IP-Adresse wird derzeit nicht unterstützt

@dalu

Aber es sollte zugänglich sein, nur nicht öffentlich. Und das ist die ganze Sache hier.
Sie sind standardmäßig unsicher und umgehen einen Fix mit Semantik.
Das Problem ist seit fast 2 Jahren ohne angemessene Lösung offen.

Ich wechsle von Schwarm zu Kubernet, weil Schwarm nicht verwendbar ist. Ich bin total zufrieden mit dieser Entscheidung, auch wenn dieser Übergang sehr kostspielig ist.

@ Bessonv Es sagt dir

Das Problem ist, dass das Compose-Format für Entwickler-Umgebungen entwickelt wurde und zur Unterstützung von Cluster-Bereitstellungen entwickelt wurde. "Docker Stack" sollte nur ein Fehler sein, aber dann möchten die Leute in der Lage sein, eine Compose-Datei zu verwenden, um sie alle zu regieren, und so gibt es dieses Durcheinander.

@ cpuguy83
Ich bin mir nicht sicher, ob ich mit dieser Beschreibung zufrieden bin. Am Ende ist das Kompositionsformat nur eine Beschreibung des gewünschten Zustands. Einige Unterschiede zwischen einer Maschine (Verfassen) und einem Cluster (Schwarm) zu haben, ist völlig in Ordnung. Aus meiner Sicht gibt es überhaupt keinen Grund, das Komponieren zu unterstützen. Vor allem, weil das Aktivieren des Schwarmmodus so einfach ist. Dies erfordert jedoch die Reparatur des Schwarms.

Das Problem liegt überhaupt nicht im Schwarm und zu 100% im Compose-Format + der Implementierung in der Docker-CLI.
Beachten Sie, dass Stacks derzeit zu 100% eine clientseitige Implementierung sind.

Wir haben festgestellt, dass Sie innerhalb des Stacks keine Ports für interne Dienste wie Datenbank, Redis usw. explizit verfügbar machen müssen. Das Auslassen der ports -Konfiguration des internen Dienstes und das Referenzieren nach Namen funktioniert einwandfrei .

Beispiel db service innerhalb des Stacks

services:
  db:
    image: postgres:11-alpine
  networks:
    - backend

... kann vom Django app -Dienst standardmäßig wie folgt verwendet werden:

DATABASES = {
    'default': env.db(default='postgres://user:pass<strong i="13">@db</strong>:5432/catalog'),
}

Wenn Sie in diesem Fall explizit nur öffentliche Dienste verfügbar machen, sieht dies standardmäßig als

Das Problem liegt überhaupt nicht im Schwarm und zu 100% im Compose-Format + der Implementierung in der Docker-CLI.
Beachten Sie, dass Stacks derzeit zu 100% eine clientseitige Implementierung sind.

Was auch immer: Ich habe die Verwendung von Stack eingestellt (aufgrund dieses Problems) und kümmere mich nicht mehr darum. Beschuldige die Bibliothek, beschuldige Docker, beschuldige meine Katze.

Ich habe dieses Problem bei direkter Verwendung von Docker oder bei Verwendung von Compose nicht gesehen.

Dieser Ansatz kann anscheinend helfen (sollte auf jedem Knoten im Schwarm ausgeführt werden):

  1. Schwarm verlassen
  2. Entfernen Sie das Netzwerk docker_gwbridge
  3. Erstellen Sie das Netzwerk docker_gwbridge mit der zusätzlichen Option com.docker.network.bridge.host_binding_ipv4 = IP neu
  4. Schwarm zurück
    Funktioniert für Ports, die im Modus "Host" veröffentlicht wurden. Ohne Modus "Host" wird das Eingangsnetzwerk mit anderen Treibern und dem Bereich "Schwarm" verwendet.

Schreckliche Lösung:

$ mv /usr/bin/docker-proxy /usr/bin/docker-proxy-original
$ cat << 'EOF' > /usr/bin/docker-proxy
#!/bin/sh
exec /usr/bin/docker-proxy-original `echo $* | sed s/0.0.0.0/127.0.0.1/g`
EOF
$ chmod 755 /usr/bin/docker-proxy
$ service docker restart

@jsmouret Ich kann Docker-Proxy in der neuesten Docker-Version nicht einmal finden. Ist es ein Vermächtnis? Oder ist der Name anders?

Sieht so aus, als ob es darauf ankommt ...

$ apt-file search docker-proxy
docker-ce: /usr/bin/docker-proxy
docker.io: /usr/sbin/docker-proxy

Dieses Verhalten sollte irgendwie in der Dokumentation dokumentiert werden .
Derzeit wird der Host aus der Short-Port-Zuordnung einfach ignoriert. Und lautlos funktioniert nicht.

Eine andere seltsame Sache ist, dass Sie den Host nicht im langen Syntaxschema festlegen können.

Dieses Verhalten sollte irgendwie in der Dokumentation dokumentiert werden.

Genau; Ich dachte, es wurde irgendwo auf dieser Seite erwähnt, kann es aber nicht finden. Sie können ein Problem im Dokument-Repository öffnen. https://github.com/docker/docker.github.io/issues

Derzeit wird der Host aus der Short-Port-Zuordnung einfach ignoriert. Und lautlos funktioniert nicht.

Welche Docker-Version verwenden Sie? Es sollte eine Warnung (bei Verwendung von docker stack deploy ) oder ein Fehler (bei Verwendung von docker service create ) ausgegeben werden. Siehe https://github.com/moby/moby/issues/32299#issuecomment -472793444

Welche Docker-Version verwenden Sie? Es sollte eine Warnung (bei Verwendung der Docker-Stack-Bereitstellung) oder ein Fehler (bei Verwendung der Docker-Diensterstellung) ausgegeben werden.

Ugh, sieht so aus, als wäre es meine Schuld. Es funktioniert wirklich, als ich versuchte, einen Stack von der Konsole aus bereitzustellen.
Zuvor habe ich es über die Portainer-Benutzeroberfläche gemacht und es wurden keine Fehler oder Warnungen angezeigt.

Wirklich enttäuscht, dass einige der Docker-Entwickler fast zwei Jahre lang einen gültigen und sehr nützlichen Anwendungsfall ignorieren, wenn diese Funktionalität vorhanden sein muss: Wenn Sie eine enthaltene relationale Datenbank als Schwarmdienst an die lokale Schnittstelle binden möchten, um über den SSH-Tunnel sicher darauf zuzugreifen . Derzeit ist dieses Szenario nicht möglich.

Eine funktionsfähige, saubere Lösung besteht darin, einen SSH-Server in einem zweiten Container auszuführen, der mit demselben Docker-Netzwerk wie Ihre Datenbank verbunden ist. Der SSH-Port kann dann auf dem Host veröffentlicht werden (natürlich auf einem anderen Port als 22), sodass Sie über den SSH-Container an Ihre Datenbank weiterleiten können.

@nartamonov Ich sehe nicht, wie dies sicher vor dem Eindringen geschehen kann, es sei denn, das Protokoll selbst ist sicher.
Der sichere Zugriff erfolgt über eine verschlüsselte Datenebene ( --opt encrypted für übermäßige Netzwerke) und das Hochfahren eines Containers mit allen Tools, die Sie an dieses Netzwerk anschließen müssen.

Dies hat wahrscheinlich andere nicht verwandte Nebenwirkungen, aber das Setzen von "iptables": false in /etc/docker/daemon.json auch eine Problemumgehung. Eine weniger drastische Lösung besteht darin, nur die benutzerdefinierte Regel hinzuzufügen , wie sie von

In jedem Fall würde ich gerne nach 3 Jahren mehr Unterstützung dafür sehen.

Dieser Ansatz kann anscheinend helfen (sollte auf jedem Knoten im Schwarm ausgeführt werden):

1. leave swarm

2. remove network docker_gwbridge

3. recreate network docker_gwbridge with additional option com.docker.network.bridge.host_binding_ipv4=IP

4. join swarm back
   Works for ports published in mode "host". Without mode "host" ingress network is used with other driver and scope "swarm".

@ienovytskyi
Wenn ich mich nicht irre, werden alle veröffentlichten Ports an eine bestimmte Standardadresse von IP gebunden. Um klar zu sein, ist dies keine brauchbare Problemumgehung, wenn Sie nur die gebundene Schnittstelle für einige Ports einiger Dienste einschränken möchten.

Ich möchte meine Problemumgehung melden.

Anwendungsfall:
Einige Dienste in Swarm müssen alle Schnittstellen oder zumindest die öffentliche Schnittstelle überwachen - dieser Container in meinem Beispiel ist ein Reverse Proxy
In diesen Schwarmknoten gibt es auch eine Datenbankinstanz auf jedem Knoten. Diese verwenden ein Schwarmnetzwerk, definiert als:

docker network create --scope swarm NETWORK_NAME --attachable -d overlay

Webdienste, die eine Datenbankverbindung benötigen, müssen natürlich mit diesem NETWORK_NAME

Für Verwaltungszwecke ist es manchmal erforderlich, eine direkte Verbindung zur Datenbank herzustellen

Lösung:
Nur Dienste, die in allen Netzwerken verfügbar gemacht werden müssen (in meinem Beispiel Reverse-Proxys), können ports: ['SOMEPORT:ANOTHERPORT'] in ihrer Dienstdefinition enthalten

Für alle anderen Dienste muss auf dem Host ein gepaarter Docker-Container ohne Schwarm vorhanden sein.
Dieser Nicht-Schwarm-Container überbrückt den vorhandenen Port auf NETWORK_NAME/nodeXYZ:port mit localhost

Beispiel mit mongodb:

docker run --rm -it --net=NETWORK_NAME -d --name expose-mongo -p 127.0.0.1:27017:47017 alpine/socat tcp-listen:47017,fork,reuseaddr tcp-connect:mongo01:27017

Nachteil: Es sollte für jeden Schwarmknoten einen Nicht-Schwarm-Container geben, daher ist es bei vielen Knoten wirklich langweilig, es sei denn, es wird ansible / schwere Skripte verwendet

Meine Problemumgehung für das von @ fer2d2 erwähnte Problem "Wenn Sie über SSH-Tunnel eine Verbindung zu einigen Diensten herstellen" bestand darin, einen SSH-Dienst mit einer Docker-Datei wie den folgenden hinzuzufügen:

FROM alpine

RUN apk add --no-cache openssh
RUN mkdir ~/.ssh
RUN ssh-keygen -A
RUN echo "root:root" | chpasswd
RUN echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config
RUN echo 'Port 22' >> /etc/ssh/sshd_config
RUN echo -e " \
Match User root \n\
  AllowTcpForwarding yes\n\
  X11Forwarding no\n\
  AllowAgentForwarding no\n\
  ForceCommand /bin/false\n\
" >> /etc/ssh/sshd_config

EXPOSE 22
CMD /usr/sbin/sshd -D -e "$@"

Dann in der docker-compose.yml:

...
  db:
    image: mysql:5.6
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?err}
      MYSQL_ROOT_HOST: '%'
    volumes:
      - "./mysql:/var/lib/mysql"
    deploy:
      placement:
        constraints: [node.role == manager]

  sshd:
    image: maxisme/sshd:latest
    volumes:
      - "~/.ssh:/root/.ssh"
    ports:
      - "2223:22"
    deploy:
      placement:
        constraints: [node.role == manager]

Dadurch kann ich meine autorisierten Schlüssel zum Ordner ~/.ssh hinzufügen und dann mit dem Hostnamen db über den Port 2223 zu meiner Datenbank springen.

Eine funktionsfähige, saubere Lösung besteht darin, einen SSH-Server in einem zweiten Container auszuführen, der mit demselben Docker-Netzwerk wie Ihre Datenbank verbunden ist. Der SSH-Port kann dann auf dem Host veröffentlicht werden (natürlich auf einem anderen Port als 22), sodass Sie über den SSH-Container an Ihre Datenbank weiterleiten können.

gültig

Ein weiteres Beispiel, warum diese Funktion wichtig ist.
Ich habe einen Server mit plesk installiert, plesk hat bereits seine Konfigurationen, aber ich kann eine andere Konfiguration hinzufügen, nur um auf einen Docker-Schwarmdienst zu verweisen. Dieser plesk-Server ist ein Schwarmknoten.
Ich möchte plesk verwenden, um proxy_pass an einen Port zu senden. Dieser Port sollte veröffentlicht werden, da sich der Container im Overlay-Netzwerk befindet, aber einen externen Port für die Kommunikation mit der Welt benötigt.

Der Proxypass sollte also auf eine lokale Schnittstelle wie 127.0.0.1: someport verweisen
und der Container im Schwarm sollte den Port nur für localhost veröffentlichen.

Auf diese Weise ist der Container-Port nur über den Proxypass und nicht direkt von der Welt aus zugänglich

Ich mag Ihre Problemumgehung @maxisme , aber wie verwalten Sie den Besitz von authorized_keys ? Unter OS X funktioniert es für mich (der Mount gehört zu root ), aber auf einem Linux-Produktionscomputer bekomme ich:

Authentication refused: bad ownership or modes for file /root/.ssh/authorized_keys
Connection closed by authenticating user root 85.145.195.174 port 60535 [preauth]

Das Volume gehört zur UID des Hostbenutzers, die nicht root und SSHD weigert sich, damit zu arbeiten. Eine Problemumgehung zusätzlich zu Ihrer Problemumgehung besteht darin, configs wie folgt zu verwenden:

services:
  sshd:
    image: [...]/sshd:${version}
    configs:
      # FIXME: It would be much better to use a bind volume for this, as it
      # would always be in sync with the host configuration. So revoking a key
      # in the host machine would automatically revoke it in the container. But
      # I can't figure out how to give the volume right ownership. It keeps UID
      # from the host which doesn't align with the container user.
      - source: authorized_keys
        target: /root/.ssh/authorized_keys
        mode: 0600

configs:
  authorized_keys:
    file: ~/.ssh/authorized_keys

Ich verstehe, dass Sie aufgrund der Tatsache, dass Sie nicht wissen, auf welchem ​​Host ein Container bereitgestellt wird, den Dienst nicht anweisen können, an eine bestimmte Host-IP-Adresse zu binden.

Hosts haben jedoch häufig z. B. nach Norden und Süden gebundene Schnittstellen. Möglicherweise möchten Sie, dass die Schwarmports nur an die nach Norden gerichteten Schnittstellen aller Schwarmhosts gebunden werden.

Wenn die Schnittstellennamen aller Schnittstellen, an die ein Dienst gebunden werden soll, identisch sind (z. B. eth0), empfiehlt es sich möglicherweise, eine Option zum Angeben eines Schnittstellennamens anzubieten, an den Schwarmports gebunden werden sollen (im Abschnitt Serviceports).

    nginx:
      image: nvbeta/swarm_nginx
      networks:
        - demonet1
      ports:
        - "eth0:8088:80"

Wenn eth0 auf einem Schwarmknoten nicht verfügbar ist, wird der angegebene Port nicht an eine Schnittstelle gebunden.

@ tad-lispy Sie sollten in der Lage sein, UID und GID des Containerbenutzers so zu ändern, dass sie mit dem Volume-Eigentümer auf dem Host übereinstimmen.
Das Linuxserver-Image unterstützt dies durch Festlegen von Umgebungsvariablen (siehe https://hub.docker.com/r/linuxserver/openssh-server, User / Group Identifiers ).

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen