Herramientas de usuario

Herramientas del sitio


informatica:sistemas_operativos:cursos:docker_a_fondo_introduccion_kubernetes:contextos_docker

Contextos en Docker

Contextos en Docker: Historia

Antes de introducir los conceptos creo que es interesante refrescar algunos conceptos sobre la arquitectura de Docker.

Docker es un sistema cliente-servidor, en el cual una herramienta de línea de comandos (CLI) llamada docker se comunica con un servidor (al que solemos llamar dockerd de docker daemon). Lo habitual es que la CLI y el daemon se ejecuten en la misma máquina. En estos casos la comunicación es usando un “socket de Unix” que es un mecanismo de comunicación entre procesos (ICP). Introdujimos ese “socket de Unix” en la introducción de docker: es el docker.sock. No es necesario que sepas mucho más de ello, simplemente que se trata del mecanismo mediante el cual el cliente y el daemon se comunican. En el caso de Windows la comunicación se realiza a través de un “named pipe” que es un mecanismo similar.

Usar un “socket de Unix”, no es el único mecanismo mediante el cual se puede acceder al daemon. Existe la posibilidad de abrir un puerto TCP y comunicarnos usando este puerto TCP. Esa aproximación tiene riesgos de seguridad y no está recomendada. Tienes más información en la documentación oficial.

Que la CLI y el daemon estén en la misma máquina puede ser lo habitual, pero no es una obligación: la arquitectura de Docker está pensada para que un cliente pueda comunicarse con daemons ejecutándose en otra máquina. De este modo tú controlas desde tu máquina los contenedores ejecutándose en otra.

De hecho esa es la base de Docker Desktop: en Docker Desktop el daemon se ejecuta en una MV (o WSL2) mientras que el cliente se ejecuta directamente en el Host. Por supuesto Docker Desktop se encarga de muchas más cosas (como convertir formatos de rutas o compartir el disco).

La variable de entorno DOCKER_HOST

Esa variable de entorno es el mecanismo más sencillo para controlar un daemon de Docker desde nuestra máquina.

En el primer comando lanzo un docker ps y eso se ejecuta contra el daemon de mi máquina local. Luego en el segundo comando establezco la variable DOCKER_HOST y me conecto al daemon de la máquina 192.168.122.1.

Docker abrirá una sesión SSH contra la máquina indicada y se conectará al daemon ejecutándose en esta máquina. Eso implica que la máquina debe aceptar conexiones SSH y obviamente debe tener Docker instalado. Otra opción para DOCKER_HOST es usar el protocolo TCP directamente, sin usar SSH, pero para ello el daemon de Docker debe estar configurado para usar el puerto TCP.

El uso de DOCKER_HOST con el protocolo TCP fue muy común hace algún tiempo en Windows. Cuando Docker Desktop no tenía soporte para WSL, había gente que se encontraba con la siguiente situación: Tenían Docker Desktop instalado, pero usaban generalmente WSL para desarrollar. Instalar el daemon de Docker en WSL no era una opción (por limitaciones que tenía WSL), así que la solución era instalar sólo la CLI en WSL y usar DOCKER_HOST para conectar la CLI contra el daemon de Docker Desktop. Era como un salto con triple tirabuzón, pero funcionaba.

Docker Machine

Docker Machine es un proyecto, ahora obsoleto, que facilitaba usar la CLI en una máquina con el daemon en otra. La gracia de Docker Machine era que era capaz de aprovisionar:

  • Máquinas externas: se conectaba por SSH e instalaba y configuraba Docker en ellas (en caso de que fuese necesario).
  • Máquinas virtuales: era capaz de crear y configurar MVs con varios sistemas de virtualización.
  • Máquinas en el cloud: era capaz de crear y configurar MVs en varios clouds.

Así Docker Machine se encargaba de todo: creaba (si era necesario) la máquina remota, la configuraba para que tuviese Docker instalado y nos daba la configuración a usar para que nuestra CLI se conectase a ellas.

Con el tiempo Docker se empezó a preguntar si era necesario declarar docker machine obsoleto, cosa que hizo finalmente.

Pero sin Docker Machine nos quedamos huérfanos de un escenario interesante: el poder controlar desde nuestra máquina contenedores ejecutándose en otros lugares. Y digo explícitamente “otros lugares” porque ya no es necesario que esos “otros lugares” sean máquinas virtuales: pueden ser motores de contenedores serverless de los cloud que ahora están tan en boga.

Para soportar estos escenarios Docker ideó el concepto de “contextos”.

Contextos en Docker

Los contextos en Docker son el mecanismo actual para podernos conectar a distintos daemons de Docker desde la CLI de nuestra máquina. Incluye soporte para daemons de Docker ejecutándose en otras máquinas, así como soporte para algunos servicios de cloud.

También incluye la posibilidad de guardar información de acceso a un clúster de Kubernetes, pero eso no significa que podamos desplegar aplicaciones en Kubernetes usando la CLI de Docker. El soporte para Kubernetes lo que te permite es mantener la configuración de Kubernetes usando la CLI de Docker y transferirla entre máquinas. Al final eso ayuda a la interoperabilidad entre las distintas herramientas. No vamos a ver este punto en concreto de los contextos, si te interesa puedes echar un vistazo a la documentación oficial.

Vamos a ver lo fundamental de los contextos: cómo usarlos y crearlos.

Listar los contextos actuales

El comando docker context ls te permite listar los contextos actuales.

El contexto “actual” (es decir el contexto que usarán todos los comandos de la CLI), se muestra con un asterisco.

En este caso, la imagen muestra dos contextos:

  • default: es el contexto que se instala “por defecto”, al instalar Docker Engine
  • desktop-linux: es el contexto que instala, en este caso, Docker Desktop for Linux.

Recuerda que, en Linux, cuando instalas Docker Desktop, el daemon se ejecuta también en una MV. Si instalas Docker Desktop en un Linux donde ya tienes instalado Docker (como en mi caso), terminas con dos “entornos” de Docker: Los contenedores que levantes desde uno, no los vas a poder manejar con el otro. A nivel de la CLI eso se traduce en dos contextos (lo que es perfecto, porque así se evitan interferencias entre ambos entornos de Docker). Si no deseas tener esos dos entornos y usar sólo Docker for Desktop en Linux entonces debes parar el daemon local.

Como cada contexto es un entorno de Docker (un daemon), los contenedores dependen de cada entorno:

La imagen anterior es interesante porque puedes observar como:

  • Estoy situado en el contexto default
  • Pongo en marcha un contenedor de nginx.
    • El comando docker ps lo muestra
  • Cambio a otro contexto (docker context use).
    • El comando docker ps no muestra ahora ningún contenedor
  • Cambio de nuevo al contexto default
    • El comando docker ps muestra el contenedor de nginx

Si usas Docker Desktop en Windows verás los mismos dos contextos, pero en este caso observarás que sí se comparten contenedores e imágenes. Eso es debido a que, a diferencia de Linux, ambos contextos son realmente el mismo, ya que no existe Docker Engine en Windows.

Este es el uso general de los contextos: vamos cambiando entre ellos usando docker context use y todas las acciones de la CLI afectarán siempre al contexto contra el que estemos conectados.

El comando docker context use te permite especificar el nuevo contexto. A partir de ese momento todos los comandos de la CLI irán contra ese nuevo contexto. Puedes sobrescribir el contexto actual usando el modificador --context para usar un comando en concreto contra otro contexto.

Crear un contexto nuevo

Puedes crear un contexto adicional usando el comando docker context create

docker context create shared-vm --docker host=tcp:///shared-vm:2735

Este comando crea un contexto de Docker que apunta a TCP://shared-vm:2375. Por supuesto eso significa que en el servidor shared-vm debe estar el daemon de Docker configurado para escuchar por el puerto 2375.

Docker incluye soporte para usar ACI (Azure Container Instances) y AWS ECS (Elastic Container Services). Eso permite desplegar en esos servicios cloud usando la CLI de Docker. Para más información consulta cómo usar Docker con ACI o usar Docker con ECS.

Exportar e importar contextos

Si tienes más de una máquina con Docker instalado puedes exportar los contextos de una máquina e importarlos en la otra. Al final es un mecanismo sencillo para compartir configuraciones de Docker (y posibles credenciales asociadas), de forma que se simplifica mucho la configuración de máquinas.

El comando es docker import <nombre-contexto>. Este comando genera un fichero <nombre-contexto>.dockercontext que puedes importar usando el comando:

docker context import <nombre-contexto> <nombre-fichero>

Este comando te importará el contexto en la nueva máquina y ¡ya lo podrás usar con docker context use!

Contextos de Docker y Docker buildx

Esta sección hace referencia a aspectos relacionados con docker buildx, que se presentó en el módulo dedicado a la creación de imágenes. Si en aquel momento optaste por saltarte ese apartado, puedes saltarte esta sección y retomarla cuando te decidas a estudiar esas lecciones.

Cada contexto de docker que tengas definido en la máquina es a su vez un builder de docker buildx. Eso significa que, si tienes N contextos de Docker, vas a tener de forma automática N builders de docker buildx. Cada uno de esos builders será con el driver docker (recuerda que no puedes crear builders con ese driver):

En la imagen anterior se puede ver como hay dos contextos de Docker (default y desktop-linux) y por lo tanto dos builders de docker buildx con los mismos nombres.

informatica/sistemas_operativos/cursos/docker_a_fondo_introduccion_kubernetes/contextos_docker.txt · Última modificación: por tempwin