Contenedores Docker en Azure (aci) desde Docker Desktop

Tiempo de lectura: 8 minutos
Imagen ornamental con el logo de Azure Container Instances (aci) para la entrada sobre como desplegar contenedores en Azure con Docker Desktop

Se van acercando las vacaciones de verano y ya están tan cerca que se pueden sentir. Con las vacaciones de verano llega el final de la temporada y un merecido descanso. Con esa idea en mente, pensaba cerrar la temporada con una entrada sobre Dapper que se iba a publicar en lugar de esta, pero el reciente anuncio de Microsoft sobre el soporte experimental para desplegar contenedores Docker directamente en Azure Container Instances (aci de aquí en adelante) desde Docker Desktop ha trastocado un poco los planes.

Si quieres saber como desplegar un agente de DevOps efímero sobre aci, no te pierdas la entrada ‘Azure DevOps Ephimeral Agents: Agentes de usar y tirar

¿Por qué es tan interesante poder desplegar aci directamente desde Docker Desktop?

Normalmente, trabajar con Docker en local es más que suficiente para poder hacer pruebas y desarrollos que antes o después acaben desplegados por ejemplo en Kubernetes. Aunque este suele ser el proceso habitual, también existen modelos de orquestación basados en docker-compose.

Imagina que necesitas que un equipo de testing haga pruebas sobre una web que estas desarrollando. Si bien es cierto que se podría desplegar la imagen sobre un App Service directamente, habría que gestionarlo a parte, actualizar sus imágenes,…

Gracias a este nuevo modelo, vamos a poder tener un funcionamiento mucho más sencillo, ya que va a ser directamente desde Docker Desktop donde vamos a gestionar los despliegues a contenedores en Azure Container Instances. Nuestro flujo de trabajo sería algo como esto:

La imagen muestra un diagrama de flujo hacia DockerHub/ACR y desde ahí hacia Azure Container Instances

Aunque ahora mismo está en una fase muy preliminar (se hizo público el 25 de junio de 2020), la idea detras de esto es conectar el aci con por ejemplo un Storage de Azure de modo que tengamos volúmenes persistentes o que podamos por ejemplo crear un despliegue complejo utilizando directamente docker-compose.

Esto se suma a que los recursos dejan de ser parte de nuestra máquina para empezar a ser parte de la infraestructura de Azure. De este modo, si nuestro entorno tiene un consumo que nuestra máquina no puede soportar bien, al estar alojado en Azure ese problema desaparece de raíz.

Configurando Docker Desktop para desplegar sobre ACI

Llegados a este punto, vamos a empezar a configurar Docker Desktop para poder desplegar sobre ACI. El primero de los requisitos es tener la versión 2.3.2.0 Edge (o superior). Esta versión se puede descargar desde le propia web de descargas de Docker Desktop:

La imagen señala el canal Edge de MacOS y de Windows en la sección de descargas de Docker Desktop

En caso de que todavía no este disponible la versión 2.3.2.0 en las descargas (a mí me ha pasado), puedes descargarlo utilizando uno de estos enlaces para Windows o para MacOS.

Una vez que hemos instalado la nueva versión, lo primero que vamos a necesitar es autenticarnos con nuestra cuenta de Azure. Para esto basta con ejecutar el comando:

docker login azure

Esto nos enviará a la web de Azure para que introduzcamos las credenciales. Una vez que nos autentiquemos, en la consola recibiremos un mensaje de confirmación de que todo ha ido bien:

PS C:\Users\jorge> docker login azure
login succeeded

Con esto, ya casi tenemos todo listo para desplegar contenedores en Azure (aci) desde Docker Desktop. Solo nos falta un paso más, crear un contexto de tipo aci en Docker Desktop. Para esto basta con ejecutar:

docker context create aci myacicontext

Este comando nos permite a día de hoy, definir ciertos parámetros adicionales para poder ajustar más la configuración. Estos parámetros son:

  • location: Permite definir la ubicación de los contenedores
  • resource-group: Permite indicar que los contenedores deben crearse en un grupo de recursos concreto (que debe existir previamente)
  • subscription-id: Permite indicar el Id de una suscripción en concreto de Azure, especialmente útil si tienes más de una suscripción en tu cuenta.

Por ejemplo, en caso de definir los 3 parámetros el comando sería algo así:

docker context create aci myacicontext --location westeurope --subscription-id xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --resource-group docker-aci

Con esto, ya tenemos disponible el contexto myacicontext listo para desplegar contenedores aci desde Docker Desktop. Esto podemos comprobarlo con el comando:

docker context ls

Como mínimo, este comando debería respondernos 2 contextos, el default de Docker Desktop y el que acabamos de crear.

PS C:\Users\jorge> docker context ls
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT                  KUBERNETES ENDPOINT   ORCHESTRATOR
default             moby                Current DOCKER_HOST based configuration   npipe:////./pipe/docker_engine                         swarm
myacicontext *      aci                 docker-aci@westeurope

De ahora en adelante, podemos especificar sobre que contexto queremos aplicar los comandos Docker con el argumento –context Contexto. También podemos especificar el contexto por defecto que debe utilizarse si no se informa específicamente con el comando:

docker context use contexto

Vamos a probarlo

Una vez que tenemos el contexto listo, basta con ejecutar un run normal para que se despliegue automáticamente. Por ejemplo, podemos utilizar el comando:

docker run -p 80:80 -d nginx

Esto mostrará por consola una salida un tanto diferente a la habitual cuando se usa el contexto local:

PS C:\Users\jorge> docker run -p 80:80 -d nginx
[+] Running 2/2
 - sleepy-cray             Created                                         4.5s
 - single--container--aci  Done                                           20.6s
sleepy-cray

Si ahora vamos a la suscripción de Azure en el grupo de recursos que le hemos indicado, podemos encontrarnos algo como esto:

La imagen muestra el grupo de recursos docker-aci de con un aci llamado sleepy-cray

En caso de que cuando creásemos el contexto no le indicásemos un grupo de recursos, se crearía uno automáticamente con un GUID como nombre.

Podemos gestionar el propio contenedor desde el mismo Docker. En este caso hemos desplegado una imagen de nginx y hemos mapeado el puerto 80, por tanto, si obtenemos la IP del contendor, deberíamos poder acceder desde cualquier navegador. Para obtener esa IP basta con que ejecutemos:

docker ps

Esto nos mostrará por consola la salida habitual del comando, indicándonos la IP del contenedor:

CONTAINER ID        IMAGE               COMMAND             STATUS              PORTS
sleepy-cray         nginx                                   Running             52.143.11.203:80->80/tcp

Basta con navegar a la dirección IP para ver que todo funciona correctamente:

La imagen muestra la página de bienvenida de nginx y señala la IP desde la que se ha accedido que es 52.143.11.203

Al igual que hacemos con cualquier otro contenedor, también podríamos obtener los logs desde el aci utilizando en Docker Desktop el comando:

docker logs id-del-contenedor

Por ejemplo, para nuestro nginx:

PS C:\Users\jorge> docker logs sleepy-cray
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
10.240.255.56 - - [28/Jun/2020:19:37:17 +0000] "GET / HTTP/1.1" 400 157 "-" "-" "-"
10.240.255.55 - - [28/Jun/2020:19:43:13 +0000] "GET / HTTP/1.1" 200 612 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.56" "-"
10.240.255.55 - - [28/Jun/2020:19:43:13 +0000] "GET /favicon.ico HTTP/1.1" 404 555 "http://52.143.11.203/" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36 Edg/83.0.478.56" "-"
2020/06/28 19:43:13 [error] 27#27: *154 open() "/usr/share/nginx/html/favicon.ico" failed (2: No such file or directory), client: 10.240.255.55, server: localhost, request: "GET /favicon.ico HTTP/1.1", host: "52.143.11.203", referrer: "http://52.143.11.203/"
PS C:\Users\jorge>

Por último, para borrar el contenedor basta con que ejecutemos el comando:

docker rm id-del-contenedor

Utilizando Docker Compose sobre aci

Hasta ahora hemos planteado el uso de docker para levantar contenedores individuales, pero no es la única posibilidad. Gracias a Docker Compose podemos orquestar diferentes configuraciones de contenedores de manera que podamos por ejemplo levantar una web y una base de datos. Como no podía ser de otra manera, esta es una característica soportada por esta versión preview (aunque con muchas limitaciones).

Para poder usar esta funcionalidad, basta con que creemos un fichero docker-compose.yml con un contenido como este:

version: '3.4'

services:
   db:
     image: mysql:5.7
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "80:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
       WORDPRESS_DB_NAME: wordpress

Una vez hecho el fichero, basta con ejecutar el comando:

docker compose -f .\docker-compose.yml up

OJO. El comando es docker compose y no docker-compose. Esto es porque se utiliza la docker cli en vez de docker-compose cli.

Tras la ejecución del comando, podremos obtener una salida como esta:

PS C:\Users\jorge\OneDrive\Escritorio\aci> docker compose -f .\docker-compose.yml up  
[+] Running 4/4
 - aci                Created                                  4.4s
 - db                 Done                                    66.7s
 - wordpress          Done                                    66.7s
 - aci--dns--sidecar  Done                                    66.7s

Esto va a levantar un aci con varios contenedores dentro para la base de datos, el propio wordpress y un contenedor adicional que sirve de dns entre ambos. Ahora mismo, podemos ir a la interfaz de Azure y ver que efectivamente se han creado:

La imagen muestra la interfaz de Azure donde se ve centro del aci que se han desplegado los contenedores db, wordpress y aci--dns--sidecar

Con esto deberíamos poder entrar en la IP que se ha asignado y usar nuestro wordpress, pero actualmente parece que o no está soportado el uso de variables o tiene algún bug por lo que nuestro escenario no es capaz de arrancar al no asignar las variables de entorno en el contenedor. Puedes seguir la información al respecto en esta incidencia.

Conclusión

Gracias a esta nueva vuelta de tuerca de la mano de Docker y Microsoft, se amplían mucho los posibles escenarios de desarrollo que podemos conseguir con Docker antes de llegar a desplegar en un Kubernetes. Es posible hacer despliegues de entornos de pruebas de manera muy sencilla y gestionarlo tal cual haríamos como si el entorno fuese local de nuestra máquina.

Hay que reconocer que la línea actual de desarrollo es muy interesante en cuanto a sus ambiciones, despliegue de aci desde Docker Desktop directamente, pudiendo utilizar cuentas de almacenamiento de Azure como volúmenes para los contenedores o pudiendo desplegar con docker-compose como sistema de orquestación.

Llegados a este punto, es también muy importante señalar que es un producto extremadamente reciente, que no está recomendado para su uso en producción y que su documentación actualmente brilla por su ausencia. Si bien es cierto que se detalla cómo crear un contenedor, no hay nada de información sobre cómo utilizar los volúmenes, o solución de errores.

Aun así y con todo, pienso que apunta muchas maneras para tener su hueco en el día a día del desarrollo con Docker una vez que madure un poco.

Deja un comentario