Ho scritto in dettaglio su come SSH in un contenitore docker. Questo tutorial porta lo stesso concetto a un altro livello abilitando l'accesso remoto a Docker.
Con l'accesso remoto Docker, ogni volta che esegui un comando Docker sul tuo host locale, gli effetti si verificano sul server remoto.
Lascia che lo spieghi in dettaglio.
Cos'è l'accesso remoto Docker?
Prima di immergerti nella configurazione, lasciami ricordare come funziona la finestra mobile.
Docker funziona in qualcosa chiamato architettura client-server. Il componente principale che gestisce tutti i tuoi container, volumi, reti, ecc. è il demone docker che viene eseguito in background.
La docker
il comando non è altro che l'applicazione client. Il client e il demone comunicano tramite l'API Docker su un socket Unix tradizionale che puoi trovare in /run/docker.sock
o /var/run/docker.sock
. Il client chiede al demone di fare qualcosa o di recuperare informazioni e il demone fa proprio questo.
Come ti interessa? Poiché il protocollo di comunicazione utilizzato tra il client Docker e il server è HTTP semplice, dovresti essere in grado di inviare richieste al server in remoto, se puoi fare in modo che il demone ascolti le richieste HTTP su una porta anziché su un socket UNIX locale.
A quanto pare, puoi farlo totalmente. Il demone può infatti ascoltare non solo il socket UNIX ma anche una porta TCP. Come se non bastasse, a partire dalla versione docker 18.09, puoi persino utilizzare SSH per il protocollo di comunicazione.
In questo tutorial, ti guiderò attraverso l'intero processo di configurazione del tuo host e di un server remoto, in modo da poter utilizzare docker
comandi da un host e farlo funzionare su un altro host, senza dover eseguire l'SSH nel server remoto.
Vantaggi dell'utilizzo dell'accesso remoto alla finestra mobile
Ti stai ancora chiedendo i vantaggi di questo approccio? Eccone alcuni:
- Non è necessario accedere a un server per avviare o interrompere un servizio. Tutto può essere fatto da remoto.
- Molti strumenti di monitoraggio, come Portainer, richiedono l'accesso all'endpoint dell'API Docker per monitorare dettagli come reti, contenitori in esecuzione, ecc. Normalmente per aggiungere un server all'elenco degli endpoint, dovresti distribuire un agente Portainer sul server prima e associa alcune porte dal container all'host. Invece, potresti semplicemente consentirgli di accedere direttamente al demone docker, questo farebbe risparmiare molte risorse.
- Potresti scrivere vari script di automazione direttamente nel tuo computer locale per controllare/gestire uno o più server docker remoti. Dal momento che non è necessario SSH nel server remoto, non è necessario mantenere una connessione stabile. Questa potrebbe essere una buona opzione se hai una connessione Internet instabile o lenta.
- Se il tuo sistema locale non è abbastanza potente per eseguire i container o se dici di non avere spazio di archiviazione sufficiente, puoi utilizzare un server remoto per il tuo host Docker e controllarlo in remoto tramite una porta TCP o SSH.
- Espandendo il punto precedente, i server sul cloud sono oggigiorno molto scalabili. Se stai bene con i costi, puoi ridimensionare l'host Docker quanto necessario senza doversi preoccupare di acquistare un nuovo SSD o HDD (se lo usi ancora).
I vantaggi stessi possono essere scalati verso l'alto o verso il basso, dipende dal fatto che la persona in questione ne abbia davvero bisogno o meno. Se non lo fai, va bene. Ma se lo fai sei nel posto giusto.
L'accesso remoto Docker è sicuro?
Gli amici di Docker l'hanno già considerato. Utilizzando SSH per il protocollo intermedio, è sicuro come lo sono le tue sessioni SSH. Maggiori informazioni su questo nella sezione successiva di questo tutorial.
Se non ti piace usare SSH, esporre l'API attraverso una porta pubblica, senza alcuna forma di autenticazione, non è esattamente l'idea migliore ora, vero?
Ecco perché abbiamo l'autenticazione TLS. A meno che qualcun altro non abbia un certificato firmato dalla tua CA (insieme al certificato della CA), non dovrebbe essere in grado di farti del male.
Il diagramma seguente spiega questo:
Per prima cosa parlerò di come configurare i server locali e remoti per questa configurazione, con SSH. È molto più semplice e ti consiglio di seguire questa strada se l'altro metodo ti sembra un po' complicato.
Di cosa hai bisogno per questa configurazione?
Prima di andare avanti, hai bisogno di un paio di cose, alcune obbligatorie, altre facoltative.
- Dato che questo è già abbastanza chiaro, avrai bisogno di un server sul cloud, personalmente raccomando Linode.
- Docker deve essere installato su questo server remoto. Puoi fare riferimento alla nostra guida sull'installazione di Docker su Ubuntu e CentOS.
- Facoltativamente, una certa conoscenza di
openssl
potrebbe essere utile se stai pianificando di utilizzare il metodo della porta TCP. - Accesso al server tramite autenticazione a chiave pubblica SSH.
Metodo 1:configurare l'accesso remoto Docker utilizzando SSH
Una delle cose migliori dell'utilizzo di SSH qui è che richiede molto meno lavoro rispetto all'altro metodo. Se hai già impostato le chiavi SSH, è letteralmente un processo in un unico passaggio.
Prima di andare avanti, voglio che tu abbia questa immagine mentale a posto, per capire come funziona questo metodo SSH e perché è configurato nel modo in cui è configurato.
Quando si utilizza il protocollo SSH per l'accesso remoto alla finestra mobile, ciò che accade è che il client Docker esegue effettivamente un comando ssh sull'host locale, con un comando Docker nascosto (dial-stdio del sistema Docker) sull'host remoto, che stabilisce una connessione al telecomando endpoint dockerd che è quasi sempre /var/run/docker.sock e inoltra la connessione ai comandi stdio.
Per confermare l'istruzione precedente, esegui qualsiasi docker
comando alla fine di questa sezione (durante il test) con il -l debug
bandiera. Questo stamperà il comando esatto in esecuzione sul tuo computer locale.
Prerequisiti
I prerequisiti per questa configurazione sono i seguenti:
È necessario che l'autenticazione con chiave pubblica SSH sia abilitata tra le macchine partecipanti. Ecco un breve riassunto di come puoi farlo,
- Usa il comando
ssh-keygen
per generare una coppia di chiavi pubblica e privata. - Usa
ssh-copy-id [email protected]
comando per copiare la chiave pubblica sul server remoto. - Assicurati
PubKeyAuthentication
è impostato suyes
nel file di configurazione SSHD remoto. Inoltre, ti consiglio di disattivare l'autenticazione della password (impostarePasswordAuthentication
ano
).
Dal momento che effettivamente stai accedendo come un utente e stai richiedendo la docker
server alcune informazioni o per fare qualcosa, l'utente remoto (con cui stai effettuando l'accesso) deve disporre di autorizzazioni sufficienti per inviare la richiesta tramite il "local DOCKER_HOST" del telecomando (che è come affermato in precedenza, principalmente /var/run/docker.sock
). Puoi avere tale autorizzazione aggiungendo quell'utente remoto alla docker
gruppo.
Per "DOCKER_HOST locale remoto" intendo il DOCKER_HOST locale del server remoto.
Questo può essere un ostacolo per molti come me, poiché personalmente non mi piace usare la docker
gruppo per un sudo
-meno esecuzione.
Puoi usare il comando usermod per aggiungere un utente esistente alla docker
gruppo.
sudo usermod -aG docker [username]
Modifiche alla configurazione sul tuo sistema locale
Ecco le cose che devi modificare sul tuo sistema personale locale da dove controllerai i server docker.
Che ci crediate o no, c'è solo una cosa da fare qui. Imposta la variabile d'ambiente DOCKER_HOST
alla corretta combinazione di nome utente remoto, IP del server e la porta su cui è in esecuzione sshd. In questo modo:
DOCKER_HOST=ssh://[email protected]:22
In alternativa, puoi anche usare il -H
flag come ho fatto qui con la docker
comando
docker -H ssh://[email protected] info
Puoi invece aggiungere un alias in Linux come questo:
alias docker="docker -H ssh://[email protected]:22"
Verifica la configurazione
Non importa quale metodo hai scelto (variabile d'ambiente o alias), testarlo è solo questione di eseguire un semplice comando docker come docker info
.
Prova anche a eseguire docker -l debug info
e nota l'esecuzione del comando.
Metodo 2:utilizzo di una porta TCP pubblica con autenticazione TLS
Questo metodo è più complicato del precedente, ma ha i suoi vantaggi come non dover usare la docker
gruppo affatto.
L'idea qui è semplice, creerai i tuoi certificati e le tue chiavi private, quindi utilizzerai una porta TCP per accedere alla docker
demone attraverso non un semplice HTTP, ma un canale HTTPS sicuro.
È analogo a un sito web. Nel caso di un sito Web, lo configuri con un server Web per utilizzare chiavi e certificati diversi, che vengono successivamente confermati dal browser che sono validi e sono verificati da un'organizzazione affidabile (come Let's Encrypt o DigiCert). Una volta eseguita la verifica, le richieste HTTP crittografate vengono inviate al server Web per ottenere i dati necessari.
Allo stesso modo, qui invece di un server web tradizionale, configurerai la docker
server del demone per utilizzare determinati certificati e chiavi private. Pertanto, ogni volta che qualcuno sta per inviare una richiesta al server demone, il primo passo è assicurarsi che i partecipanti siano attendibili, purché il client abbia lo stesso certificato CA e i certificati siano firmati da quella CA, verrà stabilita una connessione e il client sarà in grado di inviare richieste [crittografate] al server.
Preparazione di certificati e chiavi
Nei passaggi seguenti genererai certificati e chiavi private per il tuo server e client.
Autorità di certificazione
Per semplificare le transazioni, utilizzerò la mia macchina client per generare tutti i file. È possibile utilizzare una macchina separata per questo, se necessario. Un certificato CA non è altro che un certificato autofirmato.
Ma prima devi generare la chiave privata della tua CA. Usa il comando seguente per farlo
openssl genrsa -aes256 -out ca-key.pem 4096
Analizziamo il comando:
- genere :Questa opzione dice a
openssl
per generare una chiave privata basata sull'algoritmo RSA. - -aes256 :crittografa la chiave privata con una passphrase fornita dall'utente, utilizzando AES a 256 bit. AES è semplicemente una tecnica di crittografia (Advanced Encryption Standard).
- -fuori :specifica il nome del file di output.
- Infine, inserisco la lunghezza della chiave (in bit).
Fornire una passphrase per proteggere la chiave. Successivamente, creerai un certificato per la tua CA, che verrà firmato con la chiave che hai appena creato. Crealo usando il seguente comando:
openssl req -x509 -new -key ca-key.pem -days 365 -subj '/CN=CertificateAuthority' -out ca-cert.pem
Per molti, questo potrebbe sembrare un mistero, ad esempio cosa sta facendo esattamente? Bene, lascia che te lo spieghi:
- richiesto :questa opzione viene utilizzata principalmente per la creazione di CSR. Qui lo stiamo usando per creare un certificato autofirmato.
- -x509 :Questo dice a
openssl
per generare un certificato firmato invece di una CSR. - nuovo :Questo crea una nuova richiesta di certificato e chiede all'utente i valori dei campi rilevanti.
- -chiave :la chiave che verrà utilizzata.
- giorni :Validità del certificato in giorni.
- -soggetto :Invece di essere richiesti per ogni singolo dettaglio, assegniamo i valori dei campi rilevanti direttamente con questa opzione. Ho impostato il nome comune solo qui. Puoi omettere questo flag e ti verrà chiesto di ogni singolo dettaglio.
- -fuori :il nome del file di output.
Fornisci la passphrase per la chiave quando richiesto.
Server Docker
Successivamente, devi generare i certificati e le chiavi private del tuo server.
Per questo, creerai prima una CSR, una richiesta di firma del certificato, quindi verrà firmata dalla CA. Genera prima la chiave privata:
openssl genrsa -out server-key.pem 2048
La sintassi è la stessa usata in precedenza, con eccezioni. Uno, non crittografare la chiave questa volta. Poiché altri programmi dovranno leggere questo file incustodito, se crittografato, incontrerai alcuni errori. Due, la lunghezza della chiave è di 256 byte qui. Ho optato per una chiave più lunga per la CA. Puoi usare la stessa lunghezza anche per questo, questo per mostrarti le diverse opzioni disponibili a tua disposizione.
Quindi genera la CSR:
openssl req -new -key server-key.pem -subj '/CN=docker-host' -out server.csr
Modifica il /etc/hosts
e aggiungi l'IP dell'host Docker con un nome host costante. Dovrai aggiungerlo a tutti i tuoi clienti che desiderano accedere a questo host. Se questo host ha un FQDN assegnato al suo IP, puoi usarlo invece. Un FQDN, nome di dominio completo è un nome di dominio associato al tuo IP nei server DNS. Questo non è il tuo nome host locale. Un FQDN viene risolto nel tuo IP non solo nella tua LAN ma in qualsiasi parte del mondo, purché faccia parte di un record DNS pubblico e il risolutore utilizzi quel server DNS.
I flag sono gli stessi utilizzati durante la generazione del certificato CA. Qui non ho il -x509
flag, poiché questo non è un certificato autofirmato, la tua CA firmerà questo. Pertanto, firmalo,
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 :questa opzione viene utilizzata per firmare le CSR.
- -richiesto :Questa opzione è disponibile per
openssl
aspettarsi una CSR. - -in :Passa il file CSR.
- Le opzioni -CA , -CAkey prende rispettivamente il certificato CA e la chiave CA come argomenti.
- -CAcreateserie :Con questa opzione,
openssl
crea un file del numero di serie CA se non ne esiste già uno. - -fileext :Passa il file contenente le estensioni di certificato da utilizzare. Qui ho usato
extendedKeyUsage
estensione.
Ora dovresti avere il certificato del server firmato dalla CA server-cert.pem
e la chiave privata del server server-key.pem
.
Cliente Docker
Ora devi configurare il tuo client Docker. Il processo è in qualche modo lo stesso di prima. Crea una chiave privata> genera una CSR> firma quella CSR con la tua CA.
Per chiarezza, li documenterò ancora qui. Genera la chiave privata:
openssl genrsa -out client-key.pem 2048
Quindi, genera la CSR:
openssl req -new -key client-key.pem -subj '/CN=docker-client' -out client.csr
Qui, inserisci il nome host del tuo cliente per il valore di CN. Infine, firma la 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
Qui l'unica differenza è il valore dell'estensione "utilizzo chiave esteso". Ho clientAuth
invece di serverAuth
. Inserisci la tua passphrase quando richiesto.
Configurazione dell'ambiente
Una volta che i certificati e le chiavi private sono pronti, è necessario informarne il motore Docker e il client, oltre a esporre l'API del motore a una porta TCP pubblica e consentire al client di utilizzare il motore Docker che non si trova sulla macchina locale.
I seguenti passaggi seguono esattamente questo.
L'host della finestra mobile
Innanzitutto, copia tre file dalla macchina dell'amministratore, il certificato CA (ca-cert.pem
), la chiave privata di questo host (server-key.pem
) e certificato firmato CA (server-cert.pem
). Crea una directory /etc/docker/certs
per conservare questi file.
sudo mkdir /etc/docker/certs
Quindi, apri il file di configurazione del demone e aggiungi quanto segue (troverai la configurazione 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"
}
L'ultima opzione dice al demone di ascoltare la porta TCP 2376. Salva il file e riavvia la finestra mobile.
sudo systemctl restart docker
Mentre il team dietro docker
consiglia di utilizzare la porta 2376 per questo, in teoria puoi utilizzare qualsiasi altra porta non utilizzata/non riservata.
Il cliente
Il lato client è probabilmente più facile da configurare. Crea una directory ~/.docker
:
mkdir ~/.docker
All'interno di quella directory, posiziona tre file, con la denominazione corretta, come di seguito (I nomi che abbiamo usato in precedenza durante questo articolo sono inseriti tra quelle parentesi)
- ca.pem :Il certificato CA (
ca-cert.pem
). - key.pem :chiave privata del cliente (
client-key.pem
). - cert.pem :Certificato del cliente (
client-cert.pem
).
Quindi, imposta due variabili di ambiente
- DOCKER_HOST Imposta il valore di questa variabile su
tcp://docker-host:2376
. Usa il nome host che hai impostato in/etc/hosts
file per l'host/ip corrispondente. - DOCKER_TLS_VERIFY Impostalo su 1.
Puoi usare ~/.bashrc
per configurarli automaticamente. Usa il comando di esportazione per impostare queste variabili:
export DOCKER_HOST=tcp://docker-host:2376
export DOCKER_TLS_VERIFY=1
Di nuovo, per il nome host, usa il valore appropriato da /etc/hosts
. Se hai un FQDN per questo IP, usa quello.
Verifica la configurazione
Ora che tutto è fatto, puoi testarlo eseguendo docker info
o esegui qualsiasi contenitore casuale, a seconda di quello che ti viene in mente. Puoi anche usare curl
per testarlo (ricordate? Queste sono semplici richieste HTTP). Utilizza quanto segue come alternativa a docker info
curl https://docker-host:2376/info --cert ~/.docker/cert.pem --key ~/.docker/key.pem --cacert ~/.docker/ca.pem
Questo genererà un oggetto JSON che puoi analizzare usando qualcosa come jq
. Puoi anche provare a eseguire un server Nginx con docker e vedere quale sistema lo ha in esecuzione. Poiché visivamente sembra che la finestra mobile sia in esecuzione sul tuo sistema locale, questo è un ottimo esempio/test che puoi eseguire. Esegui semplicemente
docker run -d --rm --name remote_nginx -p 8080:80 nginx:latest
Ora usa curl
per controllare sia localhost che l'IP remoto. Primo host locale,
curl http://localhost:8080
Dovresti vedere un output come questo
curl: (7) Failed to connect to localhost port 8080: Connection refused
Ora prova lo stesso con l'IP remoto,
curl http://docker-host:8080
Dovresti vedere il sito del modello di nginx lì. Puoi anche semplicemente utilizzare un browser per navigare in quelle posizioni, localhost e host remoto.
Quale metodo usare? TCP o SSH?
Entrambi i metodi hanno i loro meriti. Il metodo SSH è più semplice se non vuoi passare attraverso molti cerchi. Ma alcune applicazioni come Portainer non funzioneranno con il metodo SSH per l'accesso remoto al demone. L'utilizzo del metodo TCP elimina anche i problemi di "utilizzo o meno del gruppo Docker" per impostazione predefinita. Scegli il metodo che soddisfa il tuo scopo.
Spero che questo tutorial sia stato utile e informativo. Se avete domande, fatemelo sapere nei commenti qui sotto.