He escrito en detalle sobre cómo usar SSH en un contenedor docker. Este tutorial lleva el mismo concepto a otro nivel al habilitar el acceso remoto a Docker.
Con el acceso remoto docker, cada vez que ejecuta un comando docker en su host local, los efectos tienen lugar en el servidor remoto.
Déjame explicarte eso en detalle.
¿Qué es el acceso remoto Docker?
Antes de sumergirse en la configuración, permítanme recordar cómo funciona la ventana acoplable.
Docker funciona en algo llamado arquitectura cliente-servidor. El componente principal que maneja todos sus contenedores, volúmenes, redes, etc. es el demonio docker que se ejecuta en segundo plano.
El docker
El comando no es más que la aplicación cliente. El cliente y el daemon se comunican a través de la API de docker sobre un socket tradicional de Unix que puede encontrar en /run/docker.sock
o /var/run/docker.sock
. El cliente le pide al daemon que haga algo o recupere información, y el daemon hace exactamente eso.
¿Cómo te interesa esto? Dado que el protocolo de comunicación utilizado entre el cliente de Docker y el servidor es HTTP simple, debería poder enviar solicitudes al servidor de forma remota, si puede hacer que el daemon escuche las solicitudes HTTP en un puerto en lugar de un socket UNIX local.
Resulta que puedes hacer eso totalmente. De hecho, el daemon puede escuchar no solo en el socket UNIX sino también en un puerto TCP. Como si eso no fuera suficiente, a partir de la versión 18.09 de docker, incluso puede usar SSH para el protocolo de comunicación.
En este tutorial, lo guiaré a través de todo el proceso de cómo puede configurar su host y un servidor remoto, para que pueda usar docker
comandos desde un host y hacer que se ejecute en otro host, sin tener que conectarse mediante SSH al servidor remoto.
Beneficios de usar acceso remoto a docker
¿Todavía te preguntas acerca de los beneficios de este enfoque? Estos son algunos de ellos:
- No es necesario iniciar sesión en un servidor para iniciar o detener un servicio. Todo se puede hacer de forma remota.
- Muchas herramientas de monitoreo, como Portainer, necesitan acceso al punto final de la API de Docker para monitorear detalles como redes, contenedores en ejecución, etc. Normalmente, para agregar un servidor a la lista de puntos finales, debe implementar un agente Portainer en el servidor. primero y vincule algún puerto del contenedor al host. En su lugar, podría dejar que acceda directamente al demonio docker, esto le ahorraría muchos recursos.
- Puede escribir varios scripts de automatización directamente en su computadora local para controlar/administrar uno o más servidores docker remotos. Dado que no es necesario conectarse mediante SSH al servidor remoto, no es necesario mantener una conexión estable. Esta podría ser una buena opción si tiene una conexión a Internet lenta o inestable.
- Si su sistema local no es lo suficientemente potente para ejecutar contenedores, o dice que no tiene suficiente almacenamiento, puede usar un servidor remoto para su docker host y controlarlo de forma remota a través de un puerto TCP o SSH.
- Ampliando el punto anterior, los servidores en la nube son hoy en día muy escalables. Siempre que esté de acuerdo con los costos, puede escalar el host de la ventana acoplable tanto como sea necesario sin tener que preocuparse por comprar un SSD o HDD más nuevo (si todavía lo usa).
Las ventajas en sí mismas se pueden aumentar o reducir, dependiendo de si la persona en cuestión realmente lo necesita o no. Si no lo hace, está bien. Pero si lo haces, estás en el lugar correcto.
¿Es seguro el acceso remoto a Docker?
Los amigos de Docker ya lo han considerado. Usar SSH para el protocolo intermedio es tan seguro como sus sesiones SSH. Más sobre esto en una sección posterior de este tutorial.
Si no está interesado en usar SSH, exponer la API a través de un puerto público, sin ningún tipo de autenticación, no es exactamente la mejor idea ahora, ¿verdad?
Por eso tenemos autenticación TLS. A menos que otra persona tenga un certificado firmado por su CA (junto con el certificado de CA), no debería poder hacerle ningún daño.
El siguiente diagrama explica esto:
Primero voy a hablar sobre cómo puede configurar sus servidores locales y remotos para esta configuración, con SSH. Es mucho más fácil y te recomiendo que sigas esta ruta si el otro método te parece un poco complicado.
¿Qué necesita para esta configuración?
Antes de seguir adelante, necesita un par de cosas, algunas obligatorias y otras opcionales.
- Como esto ya está bastante claro, necesitará un servidor en la nube, personalmente recomiendo Linode.
- Docker debe estar instalado en este servidor remoto. Puede consultar nuestra guía sobre cómo instalar Docker en Ubuntu y CentOS.
- Opcionalmente, algún conocimiento de
openssl
puede ser beneficioso si planea usar el método de puerto TCP. - Acceso al servidor mediante autenticación de clave pública SSH.
Método 1:configurar el acceso remoto a Docker mediante SSH
Una de las mejores cosas de usar SSH aquí es que requiere mucho menos trabajo que el otro método. Si ya tiene claves SSH configuradas, es literalmente un proceso de un solo paso.
Antes de continuar, quiero que tenga esta imagen mental en su lugar, para comprender cómo funciona este método SSH y por qué está configurado de la manera en que está configurado.
Cuando se usa el protocolo SSH para el acceso remoto a la ventana acoplable, lo que sucede es que el cliente de la ventana acoplable en realidad ejecuta un comando ssh en el host local, con un comando oculto de la ventana acoplable (docker system dial-stdio) en el host remoto, que establece una conexión con el control remoto. dockerd endpoint, que casi siempre es /var/run/docker.sock, y reenvía la conexión a los comandos stdio.
Para confirmar la declaración anterior, ejecute cualquier docker
comando al final de esta sección (durante la prueba) con -l debug
bandera. Esto imprimirá el comando exacto que se está ejecutando en su máquina local.
Requisitos
Los requisitos previos para esta configuración son los siguientes:
Debe tener habilitada la autenticación de clave pública SSH entre las máquinas participantes. Aquí hay un resumen rápido de cómo puede hacerlo,
- Use el comando
ssh-keygen
para generar un par de claves pública y privada. - Utilice
ssh-copy-id [email protected]
Comando para copiar la clave pública al servidor remoto. - Asegúrese de
PubKeyAuthentication
está establecido enyes
en el archivo de configuración de SSHD remoto. Además, recomiendo desactivar la autenticación de contraseña (establecerPasswordAuthentication
ano
).
Ya que efectivamente estás iniciando sesión como un usuario y solicitando el docker
servidor alguna información o para hacer algo, el usuario remoto (con el que está iniciando sesión) debe tener suficientes permisos para enviar la solicitud a través del "DOCKER_HOST local" del control remoto (que es como se indicó anteriormente, en su mayoría /var/run/docker.sock
). Puede tener ese permiso agregando ese usuario remoto a la docker
grupo.
Por "DOCKER_HOST local remoto" me refiero al DOCKER_HOST local del servidor remoto.
Esto puede ser un desvío para muchos como yo, ya que personalmente no me gusta usar el docker
grupo para un sudo
-menos ejecución.
Puede usar el comando usermod para agregar un usuario existente a la docker
grupo.
sudo usermod -aG docker [username]
Cambios de configuración en su sistema local
Estas son las cosas que necesita modificar en su sistema personal local desde donde controlará los servidores acoplables.
Lo creas o no, solo hay una cosa que hacer aquí. Establecer la variable de entorno DOCKER_HOST
a la combinación correcta de nombre de usuario remoto, IP del servidor y el puerto en el que se ejecuta sshd. Así:
DOCKER_HOST=ssh://[email protected]:22
Alternativamente, también puede usar el -H
marca como lo he hecho aquí con el docker
comando
docker -H ssh://[email protected] info
Puede agregar un alias en Linux como este en su lugar:
alias docker="docker -H ssh://[email protected]:22"
Probar la configuración
No importa qué método haya elegido (variable de entorno o alias), probar esto es solo cuestión de ejecutar un simple comando de ventana acoplable como docker info
.
También intente ejecutar docker -l debug info
y observe que se está ejecutando el comando.
Método 2:Usar un puerto TCP público con autenticación TLS
Este método es más complicado que el anterior, pero tiene sus ventajas como no tener que usar el docker
grupo en absoluto.
La idea aquí es simple, va a crear sus propios certificados y claves privadas, y luego usará un puerto TCP para acceder al docker
daemon no a través de HTTP simple, sino de un canal HTTPS seguro.
Es análogo a un sitio web. En el caso de un sitio web, lo configura con un servidor web para usar diferentes claves y certificados, que luego el navegador confirma que son válidos y son verificados por alguna organización confiable (como Let's Encrypt o DigiCert). Una vez que se realiza la verificación, las solicitudes HTTP encriptadas se envían al servidor web para obtener los datos necesarios.
Del mismo modo, aquí, en lugar de un servidor web tradicional, configurará el docker
servidor de daemon para usar ciertos certificados y claves privadas. Por lo tanto, siempre que alguien esté a punto de enviar una solicitud al servidor daemon, el primer paso es asegurarse de que los participantes sean de confianza, siempre que el cliente tenga el mismo certificado de CA y los certificados estén firmados por esa CA, se establecerá una conexión. y el cliente podrá enviar solicitudes [cifradas] al servidor.
Preparando los certificados y claves
En los siguientes pasos, generará certificados y claves privadas para su servidor y cliente.
Autoridad de certificación
Para simplificar las transacciones, usaré mi máquina cliente para generar todos los archivos. Puede usar una máquina separada para eso si es necesario. Un certificado de CA no es más que un certificado autofirmado.
Pero primero, debe generar la clave privada de su CA. Use el siguiente comando para hacerlo
openssl genrsa -aes256 -out ca-key.pem 4096
Analicemos el comando:
- genera :Esta opción le dice a
openssl
para generar una clave privada basada en el algoritmo RSA. - -aes256 :Esto encripta la clave privada con una frase de contraseña proporcionada por el usuario, utilizando AES de 256 bits. AES es simplemente una técnica de cifrado (Estándar de cifrado avanzado).
- -fuera :especifica el nombre del archivo de salida.
- Finalmente, pongo la longitud de la clave (en bits).
Proporcione una frase de contraseña para proteger la clave. A continuación, creará un certificado para su CA, que se firmará con la clave que acaba de crear. Créalo usando el siguiente comando:
openssl req -x509 -new -key ca-key.pem -days 365 -subj '/CN=CertificateAuthority' -out ca-cert.pem
Para muchos, esto puede parecer un misterio, ¿qué está haciendo exactamente? Bueno, déjame desglosarlo por ti:
- requisito :esta opción se utiliza principalmente para crear CSR. Aquí lo estamos usando para crear un certificado autofirmado.
- -x509 :Esto le dice a
openssl
para generar un certificado firmado en lugar de una CSR. - nuevo :Esto crea una nueva solicitud de certificado y le pide al usuario los valores de campo relevantes.
- -clave :La clave que se va a utilizar.
- -días :Vigencia del certificado en días.
- -sujeto :En lugar de solicitar cada detalle, asignamos los valores de campo relevantes directamente con esta opción. He configurado el nombre común aquí solamente. Puede omitir esta marca y se le solicitará cada detalle.
- -fuera :El nombre del archivo de salida.
Proporcione la frase de contraseña para la clave cuando se le solicite.
Servidor Docker
A continuación, debe generar los certificados y las claves privadas de su servidor.
Para esto, primero creará una CSR, una solicitud de firma de certificado, y luego la firmará la CA. Primero genera la clave privada:
openssl genrsa -out server-key.pem 2048
La sintaxis es la misma que usó anteriormente, con excepciones. Uno, no cifrar la clave esta vez. Debido a que otros programas necesitarán leer este archivo sin supervisión, si está encriptado, se enfrentará a algunos errores. Dos, la longitud de la clave es de 256 bytes aquí. Opté por una clave más larga para la CA. También puede usar la misma longitud para este, esto es para mostrarle las diferentes opciones disponibles a su disposición.
A continuación, genere la CSR:
openssl req -new -key server-key.pem -subj '/CN=docker-host' -out server.csr
Editar /etc/hosts
y agregue la IP del host Docker con un nombre de host constante. Deberá agregar esto a todos sus clientes que deseen acceder a este host. Si este host tiene un FQDN asignado a su IP, puede usarlo en su lugar. Un FQDN, nombre de dominio completo, es un nombre de dominio que está asociado con su IP en los servidores DNS. Este no es su nombre de host local. Un FQDN se resuelve en su IP no solo en su LAN, sino en cualquier parte del mundo, siempre que sea parte de un registro DNS público y el resolutor esté usando ese servidor DNS.
Las banderas son las mismas que usó al generar su certificado de CA. Aquí no tengo el -x509
marca, ya que este no es un certificado autofirmado, su CA firmará este. Por lo tanto, fírmelo,
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 :esta opción se utiliza para firmar CSR.
- -requerido :Esta opción está ahí para
openssl
esperar una CSR. - -en :pasa el archivo CSR.
- Las opciones -CA , -CAclave toma el certificado de CA y la clave de CA como argumentos respectivamente.
- -CAcreateserial :Con esta opción,
openssl
crea un archivo de número de serie de CA si aún no existe uno. - -extfile :Pasa el archivo que contiene las extensiones de certificado a utilizar. Aquí he usado el
extendedKeyUsage
extensión.
Ahora debería tener el certificado de servidor firmado por CA server-cert.pem
y la clave privada del servidor server-key.pem
.
Cliente Docker
Ahora necesita configurar su cliente docker. El proceso es un poco el mismo que antes. Cree una clave privada> genere una CSR> firme esa CSR con su CA.
Para mayor claridad, todavía los documentaré aquí. Genere la clave privada:
openssl genrsa -out client-key.pem 2048
A continuación, genere la CSR:
openssl req -new -key client-key.pem -subj '/CN=docker-client' -out client.csr
Aquí, ingrese el nombre de host de su cliente para el valor de CN. Finalmente, firme el 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
Aquí la única diferencia es el valor de extensión de "uso extendido de clave". Tengo clientAuth
en lugar de serverAuth
. Introduzca su frase de contraseña cuando se le solicite.
Configurando el entorno
Una vez que los certificados y las claves privadas están listos, debe informar a su motor acoplable y al cliente sobre ellos, además de exponer la API del motor a un puerto TCP público y permitir que el cliente use el motor acoplable que no está ubicado en la máquina local.
Los siguientes pasos pasan exactamente por eso.
El host docker
Primero, copie tres archivos de la máquina del administrador, el certificado CA (ca-cert.pem
), la clave privada de este host (server-key.pem
) y certificado firmado por CA (server-cert.pem
). Cree un directorio /etc/docker/certs
para guardar estos archivos.
sudo mkdir /etc/docker/certs
A continuación, abra el archivo de configuración del daemon y agregue lo siguiente (encontrará la configuración en /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"
}
La última opción le dice al demonio que escuche el puerto TCP 2376. Guarde el archivo y reinicie la ventana acoplable.
sudo systemctl restart docker
Mientras el equipo detrás de docker
recomienda usar el puerto 2376 para esto, teóricamente puede usar cualquier otro puerto no utilizado/no reservado.
El cliente
Podría decirse que el lado del cliente es más fácil de configurar. Crea un directorio ~/.docker
:
mkdir ~/.docker
Dentro de ese directorio, coloque tres archivos, con el nombre correcto, como se muestra a continuación (los nombres que usamos anteriormente durante este artículo se colocan dentro de esos corchetes)
- ca.pem :El certificado CA (
ca-cert.pem
). - clave.pem :Clave privada del cliente (
client-key.pem
). - cert.pem :Certificado del cliente (
client-cert.pem
).
A continuación, configure dos variables de entorno
- DOCKER_HOST Establezca el valor de esta variable en
tcp://docker-host:2376
. Use el nombre de host que configuró en/etc/hosts
archivo para el host/ip correspondiente. - DOCKER_TLS_VERIFY Establézcalo en 1.
Puede usar ~/.bashrc
para configurarlos automáticamente. Utilice el comando de exportación para establecer estas variables:
export DOCKER_HOST=tcp://docker-host:2376
export DOCKER_TLS_VERIFY=1
Nuevamente, para el nombre de host, use el valor apropiado de /etc/hosts
. Si tiene un FQDN para esta IP, utilícelo en su lugar.
Probar la configuración
Ahora que todo está listo, puede probarlo ejecutando docker info
, o ejecute cualquier contenedor aleatorio, lo que le venga a la mente. También puedes usar curl
para probarlo (¿Recuerdas? Estas son simples solicitudes HTTP). Use lo siguiente como alternativa a docker info
curl https://docker-host:2376/info --cert ~/.docker/cert.pem --key ~/.docker/key.pem --cacert ~/.docker/ca.pem
Esto generará un objeto JSON que puede analizar usando algo como jq
. También puede probar y ejecutar un servidor Nginx con docker y ver qué sistema lo tiene en ejecución. Debido a que visualmente parece que Docker se está ejecutando en su sistema local, este es un excelente ejemplo/prueba que puede realizar. Simplemente ejecuta
docker run -d --rm --name remote_nginx -p 8080:80 nginx:latest
Ahora, usa curl
para verificar tanto localhost como la IP remota. Primer anfitrión local,
curl http://localhost:8080
Deberías ver una salida como esta
curl: (7) Failed to connect to localhost port 8080: Connection refused
Ahora intente lo mismo con la IP remota,
curl http://docker-host:8080
Debería ver el sitio de plantillas de nginx allí. También puede simplemente usar un navegador para navegar por esas ubicaciones, localhost y host remoto.
¿Qué método usar? ¿TCP o SSH?
Ambos métodos tienen sus propios méritos. El método SSH es más fácil si no quiere pasar por muchos obstáculos. Pero algunas aplicaciones como Portainer no funcionarán con el método SSH para el acceso remoto al demonio. El uso del método TCP también elimina los problemas de "usar o no usar el grupo docker" de forma predeterminada. Elija el método que satisfaga su propósito.
Espero que este tutorial haya sido útil e informativo. Si tiene alguna pregunta, hágamelo saber en los comentarios a continuación.