Ich habe ausführlich darüber geschrieben, wie man SSH in einen Docker-Container einfügt. Dieses Tutorial bringt dasselbe Konzept auf eine andere Ebene, indem es den Remote-Zugriff auf Docker ermöglicht.
Beim Docker-Remote-Zugriff werden die Auswirkungen jedes Mal, wenn Sie einen Docker-Befehl auf Ihrem lokalen Host ausführen, auf dem Remote-Server ausgeführt.
Lassen Sie mich das im Detail erklären.
Was ist Docker-Fernzugriff?
Bevor Sie sich mit dem Setup befassen, lassen Sie mich daran erinnern, wie Docker funktioniert.
Docker arbeitet in einer sogenannten Client-Server-Architektur. Die Hauptkomponente, die alle Ihre Container, Volumes, Netzwerke usw. verwaltet, ist der Docker-Daemon, der im Hintergrund ausgeführt wird.
Der docker
Befehl ist nichts anderes als die Client-Anwendung. Der Client und der Daemon kommunizieren über die Docker-API über einen herkömmlichen Unix-Socket, den Sie unter /run/docker.sock
finden oder /var/run/docker.sock
. Der Client fordert den Daemon auf, etwas zu tun oder Informationen abzurufen, und der Daemon tut genau das.
Wie interessiert Sie das? Da das zwischen dem Docker-Client und dem Server verwendete Kommunikationsprotokoll einfaches HTTP ist, sollten Sie in der Lage sein, Anfragen aus der Ferne an den Server zu senden, wenn Sie den Daemon dazu bringen können, HTTP-Anfragen an einem Port statt an einem lokalen UNIX-Socket abzuhören.
Wie sich herausstellt, können Sie das absolut tun. Der Daemon kann tatsächlich nicht nur den UNIX-Socket, sondern auch einen TCP-Port abhören. Als ob das nicht genug wäre, können Sie ab der Docker-Version 18.09 sogar SSH als Kommunikationsprotokoll verwenden.
In diesem Tutorial werde ich Sie durch den gesamten Prozess führen, wie Sie Ihren Host und einen Remote-Server konfigurieren können, damit Sie docker
verwenden können Befehle von einem Host und lassen es auf einem anderen Host laufen, ohne SSH-ing in den Remote-Server.
Vorteile der Verwendung von remote-docker-Zugriff
Fragen Sie sich immer noch nach den Vorteilen dieses Ansatzes? Hier sind einige davon:
- Sie müssen sich nicht bei einem Server anmelden, um einen Dienst zu starten oder zu stoppen. Alles kann aus der Ferne erledigt werden.
- Viele Überwachungstools wie Portainer benötigen Zugriff auf den Docker-API-Endpunkt, um Details wie Netzwerke, laufende Container usw. zu überwachen. Normalerweise müssten Sie einen Portainer-Agenten auf dem Server bereitstellen, um einen Server zur Endpunktliste hinzuzufügen zuerst und binden Sie einen Port vom Container an den Host. Stattdessen könnten Sie ihn einfach direkt auf den Docker-Daemon zugreifen lassen, das würde eine Menge Ihrer Ressourcen sparen.
- Sie könnten verschiedene Automatisierungsskripte direkt auf Ihrem lokalen Computer schreiben, um einen oder mehrere entfernte Docker-Server zu steuern/verwalten. Da Sie keine SSH-Verbindung zum Remote-Server herstellen müssen, müssen Sie keine stabile Verbindung aufrechterhalten. Dies könnte eine gute Option sein, wenn Sie eine instabile oder langsame Internetverbindung haben.
- Wenn Ihr lokales System nicht leistungsfähig genug ist, um Container auszuführen, oder wenn Sie sagen, dass Sie nicht genügend Speicherplatz haben, können Sie einen Remote-Server für Ihren Docker-Host verwenden und ihn über einen TCP-Port oder SSH fernsteuern. li>
- Um den vorherigen Punkt zu erweitern, sind Server in der Cloud heutzutage sehr skalierbar. Solange Sie mit den Kosten einverstanden sind, können Sie den Docker-Host so weit wie nötig skalieren, ohne sich Gedanken über den Kauf einer neueren SSD oder HDD (falls Sie sie noch verwenden) machen zu müssen.
Die Vorteile selbst können nach oben oder unten skaliert werden, je nachdem, ob die betreffende Person dies wirklich braucht oder nicht. Wenn nicht, ist das in Ordnung. Aber wenn ja, dann sind Sie hier genau richtig.
Ist Docker-Fernzugriff sicher?
Freunde von docker haben sich das schon überlegt. Die Verwendung von SSH für das Zwischenprotokoll ist so sicher wie Ihre SSH-Sitzungen. Mehr dazu im späteren Abschnitt dieses Tutorials.
Wenn Sie SSH nicht verwenden möchten, ist es jetzt nicht gerade die beste Idee, die API über einen öffentlichen Port ohne jegliche Form der Authentifizierung verfügbar zu machen, oder?
Deshalb haben wir TLS-Authentifizierung. Sofern nicht jemand anderes ein von Ihrer CA signiertes Zertifikat (zusammen mit dem CA-Zertifikat) hat, sollte er/sie Ihnen keinen Schaden zufügen können.
Das folgende Diagramm erklärt dies:
Ich werde zuerst darüber sprechen, wie Sie Ihre lokalen und Remote-Server für dieses Setup mit SSH konfigurieren können. Es ist viel einfacher und ich empfehle Ihnen, diesen Weg zu gehen, wenn Ihnen die andere Methode etwas schwierig erscheint.
Was benötigen Sie für dieses Setup?
Bevor Sie fortfahren, benötigen Sie ein paar Dinge, einige obligatorisch, andere optional.
- Da dies bereits ziemlich klar ist, benötigen Sie einen Server in der Cloud, ich persönlich empfehle Linode.
- Docker muss auf diesem Remote-Server installiert sein. Weitere Informationen finden Sie in unserem Leitfaden zur Installation von Docker unter Ubuntu und CentOS.
- Optional einige Kenntnisse von
openssl
kann von Vorteil sein, wenn Sie vorhaben, die TCP-Port-Methode zu verwenden. - Zugriff auf den Server über SSH-Public-Key-Authentifizierung.
Methode 1:Richten Sie den Remote-Docker-Zugriff über SSH ein
Eines der besten Dinge an der Verwendung von SSH hier ist, dass es viel weniger Arbeit erfordert als die andere Methode. Wenn Sie bereits SSH-Schlüssel eingerichtet haben, ist dies buchstäblich ein Vorgang in einem Schritt.
Bevor Sie fortfahren, möchte ich, dass Sie dieses mentale Bild haben, um zu verstehen, wie diese SSH-Methode funktioniert und warum sie so konfiguriert ist, wie sie konfiguriert ist.
Bei Verwendung des SSH-Protokolls für den Remote-Docker-Zugriff führt der Docker-Client tatsächlich einen ssh-Befehl auf dem lokalen Host aus, mit einem versteckten Docker-Befehl (docker system dial-stdio) auf dem Remote-Host, der eine Verbindung zum Remote-Host herstellt Dockerd-Endpunkt, der fast immer /var/run/docker.sock ist, und leiten Sie die Verbindung an die Befehle stdio weiter.
Um die obige Aussage zu bestätigen, führen Sie einen beliebigen docker
aus Befehl am Ende dieses Abschnitts (beim Testen) mit -l debug
Flagge. Dadurch wird der genaue Befehl gedruckt, der auf Ihrem lokalen Computer ausgeführt wird.
Voraussetzungen
Die Voraussetzungen für diese Konfiguration sind wie folgt:
1. SSH-Public-Key-Authentifizierung
Zwischen den teilnehmenden Computern muss die SSH-Public-Key-Authentifizierung aktiviert sein. Hier ist eine kurze Zusammenfassung, wie Sie dies tun können,
- Verwenden Sie den Befehl
ssh-keygen
um ein Paar aus öffentlichem und privatem Schlüssel zu generieren. - Verwenden Sie
ssh-copy-id [email protected]
Befehl zum Kopieren des öffentlichen Schlüssels auf den Remote-Server. - Stellen Sie sicher, dass
PubKeyAuthentication
vorhanden ist aufyes
gesetzt ist in der Remote-SSHD-Konfigurationsdatei. Außerdem empfehle ich, die Passwortauthentifizierung auszuschalten (setzen SiePasswordAuthentication
aufno
).
2. Der Anmeldebenutzer muss in der Docker-Gruppe sein
Da Sie sich effektiv als ein Benutzer anmelden und den docker
anfordern Server einige Informationen oder um etwas zu tun, muss der Remote-Benutzer (als der Sie sich anmelden) über ausreichende Berechtigungen verfügen, um die Anfrage über den "lokalen DOCKER_HOST" der Remote zu senden (was, wie bereits erwähnt, meistens /var/run/docker.sock
). Sie können diese Berechtigung erhalten, indem Sie diesen Remote-Benutzer zum docker
hinzufügen Gruppe.
Mit "remote local DOCKER_HOST" meine ich den lokalen DOCKER_HOST des Remote-Servers.
Dies kann für viele wie mich eine Abschaltung sein, da ich persönlich den docker
nicht gerne verwende Gruppe für ein sudo
-weniger Ausführung.
Sie können den usermod-Befehl verwenden, um einen bestehenden Benutzer zum docker
hinzuzufügen Gruppe.
sudo usermod -aG docker [username]
Konfigurationsänderungen auf Ihrem lokalen System
Hier sind die Dinge, die Sie auf Ihrem lokalen, persönlichen System optimieren müssen, von wo aus Sie die Docker-Server steuern werden.
1. Ändern Sie DOCKER_HOST auf Ihrem lokalen System
Ob Sie es glauben oder nicht, hier gibt es nur eine Sache zu tun. Setzen Sie die Umgebungsvariable DOCKER_HOST
auf die richtige Kombination aus Remote-Benutzername, Server-IP und dem Port, auf dem sshd läuft. So:
DOCKER_HOST=ssh://[email protected]:22
Alternativ können Sie auch das -H
verwenden kennzeichnen, wie ich es hier mit dem docker
getan habe Befehl
docker -H ssh://[email protected] info
Sie können stattdessen einen Alias in Linux wie folgt hinzufügen:
alias docker="docker -H ssh://[email protected]:22"
Testen Sie die Konfiguration
Es spielt keine Rolle, für welche Methode Sie sich entschieden haben (Umgebungsvariable oder Alias), um dies zu testen, müssen Sie nur einen einfachen Docker-Befehl wie docker info
ausführen .
Versuchen Sie auch, docker -l debug info
auszuführen und beachten Sie, dass der Befehl ausgeführt wird.
Methode 2:Verwenden eines öffentlichen TCP-Ports mit TLS-Authentifizierung
Diese Methode ist komplizierter als die vorherige, hat aber ihre Vorteile, z. B. dass Sie das docker
nicht verwenden müssen Gruppe überhaupt.
Die Idee hier ist einfach, Sie werden Ihre eigenen Zertifikate und privaten Schlüssel erstellen und dann einen TCP-Port verwenden, um auf den docker
zuzugreifen Daemon durch nicht einfaches HTTP, sondern einen sicheren HTTPS-Kanal.
Es ist vergleichbar mit einer Website. Im Falle einer Website konfigurieren Sie sie mit einem Webserver, um verschiedene Schlüssel und Zertifikate zu verwenden, die später vom Browser bestätigt werden, dass sie gültig sind, und sie werden von einer vertrauenswürdigen Organisation (wie Let's Encrypt oder DigiCert) verifiziert. Sobald diese Überprüfung abgeschlossen ist, werden verschlüsselte HTTP-Anforderungen an den Webserver gesendet, um die erforderlichen Daten zu erhalten.
In ähnlicher Weise konfigurieren Sie hier anstelle eines herkömmlichen Webservers den docker
Daemon-Server, bestimmte Zertifikate und private Schlüssel zu verwenden. Wenn also jemand eine Anfrage an den Daemon-Server senden möchte, besteht der erste Schritt darin, sicherzustellen, dass die Teilnehmer vertrauenswürdig sind, solange der Client dasselbe CA-Zertifikat hat und die Zertifikate von dieser CA signiert sind, wird eine Verbindung hergestellt und der Client kann [verschlüsselte] Anfragen an den Server senden.
Vorbereitung der Zertifikate und Schlüssel
In den folgenden Schritten generieren Sie Zertifikate und private Schlüssel für Ihren Server und Client.
Zertifizierungsstelle
Um die Transaktionen zu vereinfachen, verwende ich meinen Client-Computer, um alle Dateien zu generieren. Bei Bedarf können Sie dafür eine separate Maschine verwenden. Ein CA-Zertifikat ist nichts anderes als ein selbstsigniertes Zertifikat.
Aber zuerst müssen Sie den privaten Schlüssel Ihrer CA generieren. Verwenden Sie dazu den folgenden Befehl
openssl genrsa -aes256 -out ca-key.pem 4096
Lassen Sie uns den Befehl aufschlüsseln:
- genrsa :Diese Option teilt
openssl
mit um einen privaten Schlüssel basierend auf dem RSA-Algorithmus zu generieren. - -aes256 :Dies verschlüsselt den privaten Schlüssel mit einer vom Benutzer bereitgestellten Passphrase unter Verwendung von 256-Bit-AES. AES ist einfach eine Verschlüsselungstechnik (Advanced Encryption Standard).
- -aus :Gibt den Namen der Ausgabedatei an.
- Schließlich gebe ich die Schlüssellänge (in Bits) ein.
Geben Sie eine Passphrase an, um den Schlüssel zu sichern. Als Nächstes erstellen Sie ein Zertifikat für Ihre Zertifizierungsstelle, das mit dem soeben erstellten Schlüssel signiert wird. Erstellen Sie das mit dem folgenden Befehl:
openssl req -x509 -new -key ca-key.pem -days 365 -subj '/CN=CertificateAuthority' -out ca-cert.pem
Für viele mag dies wie ein Rätsel erscheinen, was genau macht es? Nun, lassen Sie es mich für Sie aufschlüsseln:
- erforderlich :Diese Option wird hauptsächlich zum Erstellen von CSRs verwendet. Hier verwenden wir es, um ein selbstsigniertes Zertifikat zu erstellen.
- -x509 :Dies teilt
openssl
mit um ein signiertes Zertifikat anstelle einer CSR zu generieren. - neu :Dies erstellt eine neue Zertifikatsanforderung und fragt den Benutzer nach den relevanten Feldwerten.
- -Taste :Der Schlüssel, der verwendet werden soll.
- -Tage :Gültigkeit des Zertifikats in Tagen.
- -subj :Anstatt für jedes einzelne Detail abgefragt zu werden, weisen wir mit dieser Option direkt die relevanten Feldwerte zu. Ich habe hier nur den Common Name eingestellt. Sie können dieses Flag weglassen, und Sie werden zu jedem einzelnen Detail aufgefordert.
- -aus :Der Ausgabedateiname.
Geben Sie die Passphrase für den Schlüssel ein, wenn Sie dazu aufgefordert werden.
Docker-Server
Als Nächstes müssen Sie die Zertifikate und privaten Schlüssel Ihres Servers generieren.
Dazu erstellen Sie zuerst eine CSR, eine Zertifikatsignierungsanforderung, und diese wird dann von der Zertifizierungsstelle signiert. Generieren Sie zuerst den privaten Schlüssel:
openssl genrsa -out server-key.pem 2048
Die Syntax ist mit Ausnahmen dieselbe wie zuvor. Erstens, den Schlüssel dieses Mal nicht zu verschlüsseln. Da andere Programme diese Datei unbeaufsichtigt lesen müssen, treten bei einer Verschlüsselung einige Fehler auf. Zweitens beträgt die Schlüssellänge hier 256 Bytes. Ich habe mich für einen längeren Schlüssel für die CA entschieden. Sie können die gleiche Länge auch für dieses verwenden, um Ihnen die verschiedenen Optionen zu zeigen, die Ihnen zur Verfügung stehen.
Generieren Sie als Nächstes die CSR:
openssl req -new -key server-key.pem -subj '/CN=docker-host' -out server.csr
Bearbeiten Sie /etc/hosts
-Datei und fügen Sie die IP des Docker-Hosts mit einem konstanten Hostnamen hinzu. Sie müssen dies allen Ihren Clients hinzufügen, die auf diesen Host zugreifen möchten. Wenn dieser Host seiner IP einen FQDN zugewiesen hat, können Sie diesen stattdessen verwenden. Ein FQDN, Fully Qualified Domain Name, ist ein Domänenname, der Ihrer IP auf den DNS-Servern zugeordnet ist. Dies ist nicht Ihr lokaler Hostname. Ein FQDN wird nicht nur in Ihrem LAN, sondern überall auf der Welt zu Ihrer IP aufgelöst, solange er Teil eines öffentlichen DNS-Eintrags ist und der Resolver diesen DNS-Server verwendet.
Die Flags sind dieselben, die Sie beim Generieren Ihres CA-Zertifikats verwendet haben. Hier fehlt mir das -x509
Da dies kein selbstsigniertes Zertifikat ist, wird Ihre Zertifizierungsstelle dieses signieren. Unterschreiben Sie deshalb,
openssl x509 -req -days 365 -in server.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -extfile <(echo "extendedKeyUsage = serverAuth") -out server-cert.pem
- x509 :Diese Option wird verwendet, um CSRs zu signieren.
- -req :Diese Option gibt es für
openssl
eine CSR zu erwarten. - -in :Übergibt die CSR-Datei.
- Die Optionen -CA , -CAkey nimmt das CA-Zertifikat bzw. den CA-Schlüssel als Argumente.
- -CAcreateserial :Mit dieser Option
openssl
erstellt eine CA-Seriennummerndatei, falls noch keine vorhanden ist. - -extfile :Übergibt die Datei mit den zu verwendenden Zertifikaterweiterungen. Hier habe ich die
extendedKeyUsage
verwendet Erweiterung.
Jetzt sollten Sie das CA-signierte Serverzertifikat server-cert.pem
haben und den privaten Schlüssel des Servers server-key.pem
.
Docker-Client
Jetzt müssen Sie Ihren Docker-Client einrichten. Der Prozess ist in etwa derselbe wie zuvor. Erstellen Sie einen privaten Schlüssel> generieren Sie eine CSR> signieren Sie diese CSR mit Ihrer Zertifizierungsstelle.
Der Übersichtlichkeit halber werde ich diese hier noch dokumentieren. Generieren Sie den privaten Schlüssel:
openssl genrsa -out client-key.pem 2048
Generieren Sie als Nächstes die CSR:
openssl req -new -key client-key.pem -subj '/CN=docker-client' -out client.csr
Geben Sie hier den Hostnamen Ihres Clients als CN-Wert ein. Unterschreiben Sie abschließend den CSR:
openssl x509 -req -days 365 -in client.csr -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -extfile <(echo "extendedKeyUsage = clientAuth") -out client-cert.pem
Hier ist der einzige Unterschied der Erweiterungswert „erweiterte Schlüsselverwendung“. Ich habe clientAuth
statt serverAuth
. Geben Sie Ihre Passphrase ein, wenn Sie dazu aufgefordert werden.
Umgebung einrichten
Sobald die Zertifikate und privaten Schlüssel fertig sind, müssen Sie sie Ihrer Docker-Engine und Ihrem Client mitteilen, die Engine-API einem öffentlichen TCP-Port zur Verfügung stellen und dem Client die Nutzung der Docker-Engine ermöglichen, die sich nicht auf dem lokalen Computer befindet.
Die folgenden Schritte gehen genau das durch.
Der Docker-Host
Kopieren Sie zunächst drei Dateien vom Computer des Administrators, das CA-Zertifikat (ca-cert.pem
), den privaten Schlüssel dieses Hosts (server-key.pem
) und CA-signiertes Zertifikat (server-cert.pem
). Erstellen Sie ein Verzeichnis /etc/docker/certs
um diese Dateien zu behalten.
sudo mkdir /etc/docker/certs
Öffnen Sie als Nächstes die Daemon-Konfigurationsdatei und fügen Sie Folgendes hinzu (Sie finden die Konfiguration in /etc/docker/daemon.json
):
{
"tlsverify": true,
"tlscacert": "/etc/docker/certs/ca-cert.pem",
"tlscert": "/etc/docker/certs/server-cert.pem",
"tlskey": "/etc/docker/certs/server-key.pem",
"host": "tcp://0.0.0.0:2376"
}
Die letzte Option weist den Daemon an, auf den TCP-Port 2376 zu lauschen. Speichern Sie die Datei und starten Sie Docker erneut.
sudo systemctl restart docker
Während das Team hinter docker
empfiehlt dafür Port 2376 zu verwenden, theoretisch kannst du jeden anderen ungenutzten/nicht reservierten Port verwenden.
Der Kunde
Die Client-Seite ist wohl einfacher einzurichten. Erstellen Sie ein Verzeichnis ~/.docker
:
mkdir ~/.docker
Platzieren Sie in diesem Verzeichnis drei Dateien mit den richtigen Namen, wie unten (Die Namen, die wir zuvor in diesem Artikel verwendet haben, stehen in diesen Klammern)
- ca.pem :Das CA-Zertifikat (
ca-cert.pem
). - key.pem :Privater Schlüssel des Clients (
client-key.pem
). - cert.pem :Client-Zertifikat (
client-cert.pem
).
Richten Sie als Nächstes zwei Umgebungsvariablen
ein- DOCKER_HOST Setzen Sie den Wert dieser Variablen auf
tcp://docker-host:2376
. Verwenden Sie den Hostnamen, den Sie in/etc/hosts
festgelegt haben Datei für den entsprechenden Host/IP. - DOCKER_TLS_VERIFY Setzen Sie diese auf 1.
Sie können ~/.bashrc
verwenden um diese automatisch zu konfigurieren. Verwenden Sie den Exportbefehl, um diese Variablen festzulegen:
export DOCKER_HOST=tcp://docker-host:2376
export DOCKER_TLS_VERIFY=1
Verwenden Sie für den Hostnamen erneut den entsprechenden Wert aus /etc/hosts
. Wenn Sie einen FQDN für diese IP haben, verwenden Sie stattdessen diesen.
Testen Sie die Einrichtung
Nachdem alles erledigt ist, können Sie es testen, indem Sie docker info
ausführen , oder führen Sie einen beliebigen Container aus, je nachdem, was Ihnen in den Sinn kommt. Sie können auch curl
verwenden um es zu testen (Erinnern Sie sich? Dies sind einfache HTTP-Anforderungen). Verwenden Sie Folgendes als Alternative zu docker info
curl https://docker-host:2376/info --cert ~/.docker/cert.pem --key ~/.docker/key.pem --cacert ~/.docker/ca.pem
Dadurch wird ein JSON-Objekt ausgegeben, das Sie mit etwas wie jq
parsen können . Sie können auch versuchen, einen Nginx-Server mit Docker auszuführen und zu sehen, auf welchem System er ausgeführt wird. Da es optisch so aussieht, als würde Docker auf Ihrem lokalen System ausgeführt, ist dies ein hervorragendes Beispiel/Test, den Sie durchführen können. Einfach ausführen
docker run -d --rm --name remote_nginx -p 8080:80 nginx:latest
Verwenden Sie jetzt curl
um sowohl localhost als auch die Remote-IP zu überprüfen. Erster lokaler Host,
curl http://localhost:8080
Sie sollten eine Ausgabe wie diese sehen
curl: (7) Failed to connect to localhost port 8080: Connection refused
Versuchen Sie nun dasselbe mit der Remote-IP,
curl http://docker-host:8080
Sie sollten dort die Vorlagenseite von nginx sehen. Sie können auch einfach einen Browser verwenden, um auf diesen Standorten, dem lokalen Host und dem Remote-Host zu surfen.
Welche Methode soll verwendet werden? TCP oder SSH?
Beide Methoden haben ihre eigenen Vorzüge. Die SSH-Methode ist einfacher, wenn Sie nicht viele Hürden durchlaufen möchten. Einige Anwendungen wie Portainer funktionieren jedoch nicht mit der SSH-Methode für den Remote-Daemon-Zugriff. Die Verwendung der TCP-Methode beseitigt standardmäßig auch die Probleme der „Verwendung oder Nichtverwendung der Docker-Gruppe“. Wählen Sie die Methode, die Ihren Zweck erfüllt.
Ich hoffe, dieses Tutorial war hilfreich und informativ. Wenn Sie Fragen haben, lassen Sie es mich in den Kommentaren unten wissen.