12 sept 2020

Docker Introducción: Primeros pasos

 Hace tiempo que quería tener mi primer contacto con Docker. Sabía, conceptualmente y muy básicamente de que trata, es decir, que es una especie de virtualización: en la cual contamos con “imágenes” que tienen lo estrictamente necesario para que, por ejemplo, una aplicación web se ejecute independiente del sistema operativo y sus particulares condiciones. Con una una imagen creada ésta debería ejecutarse en un “contenedor” exactamente igual en mi máquina de desarrollador como en el ambiente de pruebas o en producción (en realidad en cualquier escenario), inclusive si estos ambientes están en la nube.

Entonces, aterrizando un poco más los conceptos: una imagen en Docker esta compuesta, por capas donde la primera capa seria una especie de sistema operativo mínimo (con lo mínimo requerido para lo que sea que vayamos a crear o utilizar se ejecute correcta y eficientemente), otras capas serian componentes esenciales para nuestro propósito (en el ejemplo de una aplicación web, es necesario un servidor web), configuraciones, variables de ambiente o entorno, y encima de estas capas estarían los archivos necesarios para que nuestra aplicación se ejecute. Algo muy importante a tomar en cuenta es que las imágenes son inmutables, o sea, una vez creadas, no cambian o se alteran.

Un contenedor de Docker, es la ejecución de una imagen, y éste si es modificable, sin embargo, una vez eliminado el contenedor todo lo que no sea parte de la imagen se perderá. Es decir, si tenemos una aplicación que guarda archivos dentro de su contenedor, cada vez que creemos un contenedor a partir de su imagen siempre se comportará de la misma manera, y podremos “subir” archivos, pero una vez eliminado el contenedor todos los archivos “subidos” se perderán.

Ahora bien ¿Qué necesitamos para comenzar a utilizar Docker en un ambiente de desarrollo basado en Windows? Necesitaríamos el Docker Desktop el cual lo podemos encontrar en este Link. Una vez instalado tendremos un icono como este (la imagen incluye la configuración por defecto al instalar el Docker Desktop).

Como se mencionó, en la imagen anterior vemos la configuración por defecto. El aspecto más importante aquí (según yo) es la que dice “Use the WSL 2 based engine” esto significa que Docker utilizará el motor basado en el “Windows Subsystem for Linux” siendo 2 la versión más reciente de este subsistema incluida dentro Windows 10. En teoría se podría usar Hyper-V, pero usar WSL es la manera más optima actualmente.

Ahora demos nuestros primeros pasos con Docker, nuestro objetivo es el siguiente: vamos a crear un mini sitio web a partir de cual crearemos una imagen Docker y luego la montaremos en un contenedor, todo utilizando VSCode.

Primero dentro de un folder (DockerTest en mi caso) creamos una carpeta llamada html y dentro de esta creamos un archivo llamado index.html con apenas código, quedando algo similar a lo siguiente: 


Usando la extensión VSCode “Live Server” podemos hacer clic en el ícono de la barra inferior que dice “Go Live” y podemos ver el resultado de la ejecución de esta pequeña página html. 


Obviamente esto se está ejecutando en un servidor de mi máquina, de momento no tiene nada que ver con Docker. Pero a eso vamos de inmediato. Primero necesitamos instalar la extensión de Docker para VSCode lo que nos dará intellisense para los archivos de configuración de Docker y alguna funcionalidad adicional. 


Con esta herramienta ya instalada vamos a crear un archivo fuera de la carpeta html, es decir en el directorio raíz llamado dockerfile (sin ninguna extensión). De manera que se vea así: 


En este dockerfile se va a definir como se crearán las imágenes que eventualmente se ejecutaran en contenedores para nuestro proyecto. Estos dockerfiles se componen de pasos. En este caso debemos definir los pasos para crear las diferentes capas que contendrá la imagen que eventualmente “servirá” la página html que acabamos de crear. ¿Cómo sabemos cómo crear un dockerfile para una necesidad en particular? Pues existe este sitio Explore Docker's Container Image Repository | Docker Hub por medio de cual podemos obtener los pasos requeridos para obtener los resultados deseados. Tiene una amplia colección por lo que deberíamos mantenerla a mano.

En mi caso deseo una imagen que me permita servir páginas html, por lo que elegiré httpd que permite crear una imagen de un servidor apache 


En la misma página más abajo (es importante leer toda la documentación) hace mención de la variante Alpine la cual se basa en la distribución de Linux Alpine la cual es muy pequeña. Por lo cual es la que vamos a usar. El contenido de nuestro dockerfile quedaría entonces de la siguiente manera:


Obviamente en un dockerfile se puede definir muchas cosas más, pueden ser bastante largos. Para nuestro pequeño experimento este par de líneas son suficientes. La primer línea define el tipo de imagen que queremos: un servidor apache basado en Linux Alpine y con la segunda línea copiamos nuestros archivos a la estructura donde el servidor apache de la imagen los va a necesitar.

Una vez con este dockerfile creado podemos empezar nuestra aventura con docker. Abrimos una terminal dentro de VS Code y podemos empezar a jugar con los comandos. Por ejemplo, “docker images” nos mostrará las imágenes que tenemos en nuestro Docker Engine, si lo ejecutamos nos indicará que ahora mismo no tenemos ninguna imagen creada 


Usando el siguiente comando creamos nuestra primera imagen “docker build -t docker-test:1.0.0 .”. Estamos usando el comando build con el parámetro -t para darle nombre a la imagen, en este ejemplo docker-test, lo que esta después de los dos puntos es un tag. Es importante notar que se debe colocar un punto al final antes del cual hay un espacio, ese espacio adicional es de olvido frecuente. Además, este comando se debe ejecutar en la carpeta donde se encuentra nuestro dockerfile.


Ahora, si de nuevo ejecutamos el comando “docker images” veremos la imagen recién creada 


Las primeras dos columnas corresponden con los parámetros del comando build. La columna Image Id, nos sirve como identificador único de la imagen. Por ejemplo, si quisiéramos saber como se conformó esta imagen podemos utilizar el comando “docker image history ed1” donde ed1 son los primeros tres caracteres de la image id (hay que usar suficientes caracteres para una única e inequívoca identificación) 


Podemos decir que esta lista corresponde a las diferentes capas de nuestra imagen donde la entrada más inferior (5.6 MB) corresponde al sistema operativo, la entrada de 49.2 MB corresponde al servidor web, y la entrada superior (181 B) corresponde a nuestra pagina html. Es muy importante notar la palabra “missing” en la columna Image, quiere decir que todos esos archivos están dentro de nuestro Docker Engine, es decir, se crean una única vez dentro del gestor, por lo que si se crea una segunda imagen estos paquetes ya existen y no es necesario bajarlos nuevamente; también significa que si creamos un contenedor este usará estos archivos y al crear un segundo contenedor éste re-usará los mismos archivos por lo que estaríamos ahorrando mucho espacio.

Bueno, ya tenemos nuestra imagen, ahora ¿Qué sigue? Pues bien, como se mencionó anteriormente las imágenes son “read only”, lo que sigue es ejecutar esta imagen a través de un contenedor. Para esto ejecutamos el siguiente comando “docker run --name contenedor01 -p 8080:80 docker-test:1.0.0”. Para explicar un poco el comando diré que luego del parámetro --name va el nombre que le daremos a nuestro contenedor (contenedor01), seguidamente, como en este caso estamos usando una imagen que tiene un servidor web, definimos el parámetro -p que es para mapear puertos entre el contenedor y el de la maquina host (mi maquina), a la izquierda de los dos puntos va el puerto local de mi maquina (8080) y a la derecha para el puerto al que corresponde dentro del contenedor (80) y finalmente se debe proporcionar el nombre y el tag de la imagen que vamos a ejecutar (docker-test:1.0.0) 


Si en este punto vamos a nuestro navegador y usamos la ruta localhost:8080 deberíamos ver que nuestro contenedor esta sirviendo la página html que habíamos creado 


¡Y aquí lo tenemos, nuestro primer contenedor Docker funcionando como se debe!

Podemos listar los contenedores que tenemos en nuestro gestor utilizando el comando “docker ps -all” (si usamos “docker ps” únicamente nos listará los contenedores que se estén ejecutando) 


Tal y como se aprecia en la imagen, tenemos un container id que nos sirve para referenciar el contenedor. De esta manera podemos usar el comando “docker stop b14” para detener la ejecución del contenedor, donde b14 corresponden a los primeros caracteres del container id. 


Si intentamos de nuevo la ruta locahost:8080, ésta ya no estará disponible porque el contenedor está detenido. 


Para volver a iniciar el contenedor podemos usar el comando “docker start b14” con lo que el contenedor volverá a iniciar su ejecución y la página de nuevo estará disponible.

Ahora realicemos algunos ajustes y añadidos a nuestro sitio web. Primero ajustemos la palabra “imágenes” de manera que utilicemos el código html de la letra acentuada, además voy a añadir una segunda página que se puede llamar desde la primera y viceversa quedando más o menos así: 


Ahora, sin tocar nuestro dockerfile, hagamos una segunda imagen de esta nueva versión de nuestro mini sitio web, utilizando el siguiente comando imagen “docker build -t docker-test:1.0.1 .” 


Como podemos constatar, la única diferencia con respecto a la primera vez que ejecutamos este comando es que cambiamos el tag de 1.0.0 a 1.0.1. Si ejecutamos de nuevo el comando “docker images” corroboraremos que ahora tenemos dos imágenes: 


Ahora crearé un segundo contenedor basado en esta segunda imagen por medio del siguiente comando “docker run --name contenedor02 -p 8081:80 docker-test:1.0.1” de manera que en mi maquina se utilice el puerto 8081 para acceder a este segundo contenedor. 


Ahora con el comando “docker ps -a” podemos verificar el numero de contenedores que tenemos creados:  


Aquí podemos verificar que nuestro contenedor02 se está ejecutando pero el contenedor01 no, por lo procedemos a iniciarlo usando el comando “docker start b14” y seguidamente probamos ambas direcciones:

localhost:8080 


localhost:8081   



Cómo se ve, en la segunda versión se ajustó correctamente la letra acentuada y se añadió más funcionalidad, sin embargo, podemos ejecutar aun la primera versión, al mismo tiempo, inclusive, que la segunda y compararlas. Esto nos puede ayudar con varias tareas propias del desarrollo.

Finalmente, para terminar estos primeros pasos voy a limpiar todo. 

Para detener los contenedores utilizo el comando “docker stop b14” y “docker stop d57”  y para borrar ambos contenedores el comando “docker rm b14” y docker rmd57” y ejecutamos el comando “docker ps -a” para verificar que ya no contamos con ningún contenedor. (hay una forma más eficiente de realizar esta tarea que incluyo al final de la entrada)


Ahora si deseamos eliminar las imágenes utilizamos el comando “docker rmi 56e” y “docker rmi ed1” y ejecutamos el comando “docker images” para verificar que no queda ninguna imagen:  


Notas, recapitulación y recomendación 

Hasta aquí todo lo hemos hecho a punta de comandos en la terminal, pero es importante también saber que el Docker Desktop tiene una interfaz gráfica que nos ayuda a gestionar imágenes y contenedores. Por ejemplo, listar los contenedores que tenemos y desde aquí ejecutarlos, detenerlos o borrarlos 


Ver la interacción de un contenedor en ejecución  


O listar las imágenes y a partir de ellas crear el contenedor 


En esta ultima imagen un detalle importante a notar es la etiqueta Total size. A pesar de contar con dos imágenes ambas con 54.52 MB, nos indica que el tamaño total es de 54.52 MB, no el doble, esto es, como se mencionó anteriormente, porque ambas imágenes comparten la mayoría de capas.


Resumen de comandos básicos de Docker:

Uso

Comando

Comentario

Listar imágenes

docker images

 

Listar Contenedores

docker ps -a

Sin el parámetro -a (-all) se listan solo los contenedores en ejecución

Crear imagen

docker build -t <nombre:tag> .

Se debe estar en una carpeta que contenga el dockerfile a partir del cual se crea la imagen. No olvidar espacio y punto final

Historia de imagen

docker image history <imageID>

 

Crear contenedor

docker run --name <nombreContenedor> -p <puertoLocal:puertoContenedor> <nombreImagen:tag>

En este caso se usa el parámetro -p por ser una imagen de servidor web

Iniciar contenedor

docker start <containerID>

 

Detener contenedor

docker stop <containerID>

 

Eliminar contendor

docker rm <containerID>

Se pueden borrar varios con un solo comando separando los ids por un espacio.

Eliminar imagen

docker rmi <imageID>

Se pueden borrar varias con un solo comando separando los ids por un espacio. Se puede usar -f como parámetro adicional para forzar la eliminación

Recordar que no es necesario escribir todo el Image ID o Container ID basta con los primeros caracteres siempre que permitan una única e inequívoca identificación (de hecho, es posible solo usar el primer carácter si no tenemos muchos ítems en nuestros repositorios)

Una última recomendación

Todos los comandos que se utilizaron en este post se introdujeron en una terminal tipo bash, pero se puede usar una terminal powershell que puede ser preferible dada la flexibilidad de uso. Por ejemplo, podríamos tener lo siguiente 


Son dos imágenes y dos contenedores ejecutándose y queremos detener y eliminar todos los contenedores e imágenes. Como ya vimos, para hacerlo tradicionalmente necesitamos los containers id e images id, sin embargo, con powershell podríamos usar el siguiente comando para detener todos los contenedores en ejecución “docker stop $(docker ps -q)” (docker ps -q devuelve solo los containers id de los contenedores en ejecución). Seguidamente podemos usar “docker rm $(docker ps -a -q)” (como habrán intuido docker ps -a -q devuelve los containers id de todos contenedores aun cuando no se estén ejecutando) y finalmente para borrar todas las imágenes ejecutaríamos el siguiente comando “docker rmi $(docker images -q)” (efectivamente, docker images -q devuelve los images id de todas las imágenes) 


El uso de pawershell nos podría hacer la vida más sencilla cuando utilizamos Docker.

El mundo de Docker es muy amplio, esta entrada es apenas una mínima introducción a partir de la cual podemos seguir explorando qué otras cosas podemos hacer, qué otros beneficios podemos obtener del uso de Docker en nuestros desarrollos.


3 ago 2020

Azure Functions 2 – Publicando en Azure

En la anterior entrada del blog realizamos un ejercicio sencillo en el que desarrollamos una simple azure function “disparada” ´por llamada http en la que utilizamos inyección de dependencias. En esta nueva entrada realizaremos la publicación de este ejercicio en Azure

Como pre-requisito necesitamos contar con una suscripción a Azure y, preferiblemente, ya creado un resource group. Para obtener una cuenta en Azure podemos optar por crea una en este link con hasta por 12 meses de ciertos servicios de forma gratuita. 

Con la cuenta ya creada podemos realizar la publicación por medio de Visual Studio, para esto hacemos clic derecho sobre el proyecto que tiene nuestra función y seleccionamos la opción “Publish”. 


Si no hemos realizado previamente ninguna publicación esto nos abrirá un “wizard” en el que crearemos, en primera instancia, nuestro perfil de publicación. En el primer paso seleccionaremos donde vamos a publicar:

 


En este caso dejaremos la opción seleccionada por defecto es decir publicaremos directamente en la “Azure” cloud, y haremos clic en el botón “Next”. 


En el segundo paso se nos solicitará que seleccionamos el tipo de servicio que alojara nuestras funciones. Es importante notar que “Azure function app” se refiere al servicio o recurso dentro de azure capaz de alojar azure functions, podemos pensar en el cómo el espacio que contendrá nuestras funciones. Este servicio puede ejecutarse (tras bambalinas) en Windows, Linux o como una imagen de Docker, o como cuarta opción podemos desplegar directamente en otro servicio, el Azure container Registry (contenedor de imágenes Docker). En este sencillo ejemplo dejaremos seleccionada la opción por defecto, es decir publicaremos en un Azure Function App que se ejecutará en un entorno Windows y hacemos clic en el botón “Next”. 


Si estuviéramos utilizando Visual Studio con credenciales ya asociadas a una cuenta de Azure este tercer paso sería diferente, pero asumamos que vamos a configurar la conexión a Azure por primera vez por lo que hacemos clic en el link “Sign in” (si aún no hemos creado la cuenta podríamos utilizar el link Create your free Azure Account pero en lo personal prefiero llegar aquí ya con la cuenta creada). Se nos mostrara una ventana emergente en la que debemos ingresar las mismas credenciales utilizadas al crear la cuenta en Azure (estas pueden ser diferentes a las credenciales con las que estamos utilizando visual Studio)

 


Una vez ingresadas las credenciales y realizada una correcta conexión con Azure se nos mostrará una pantalla similar a la siguiente: 


En esta se muestra el nombre de nuestra subscripción (o subscripciones en el caso de que tuviésemos varias). Para continuar debemos hacer clic el símbolo “+” cerca de la etiqueta Function Apps, lo cual nos abrirá la ventana en la que configuramos una nueva app. 


Aquí ingresamos el nombre de nuestra Function App (Que no es el nombre de la función en sí, si no del recurso o servicio que la va a contener); seleccionamos la subscripción en la que va se va crear este servicio; seleccionamos o creamos un Resourse Group (Que es un contenedor de recursos, que sirve para organizar de mejor manera recursos afines o que interactúan entre sí); seleccionamos el Plan Type (que tiene que ver con ciertas características y modelos de precio. El Consumption, por ejemplo, es el verdaderamente serveless y el más cómodo en cuenta a precio al menos para pruebas, pero también hay un plan Premuim y un plan Service App estos últimos no son verdaderamente serveless pero permite por ejemplo configurar una VNet para la Azure Function App cosa que no lo permite el plan Consumption) en nuestro ejercicio dejamos el plan Consumption seleccionado. Seguidamente seleccionamos la Location (corresponde a la región geográfica donde se desplegará la Function App, tiene mucha importancia pues la idea es que se encuentre cerca de nuestros usuarios o cerca de otros recursos que podríamos utilizar lo que a su vez podría reducir latencia y costos) y, finalmente, seleccionamos o creamos un Azure Storage donde se almacenara el código de la función que se va a ejecutar, hacemos clic en el botón “Create” lo que creará los recursos en Azure y nos devolverá a la pantalla anterior. 


En esta dejamos seleccionado el checkbox “Run from package file (recommended)” y hacemos clic en el botón “Finish”. Ya hemos creado los recursos necesarios y hemos creado un “perfil” de publicación que recordara nuestras selecciones, pero aún no hemos realizado la publicación. Para esto debemos hacer clic en el botón “Publish” de la siguiente pantalla: 


Por ahora ignoraremos los iconos de “warnning” y efectivamente haremos clic en el botón “Publish” con lo Visual Studio procederá a realizar la publicación de nuestra Azure Function.

Al final de la publicación podemos ir al portal de Azure con el fin de verificar que efectivamente nuestra publicación se realizó. Podemos ubicar nuestro Resource Group y dentro de esta nuestra recién creada Function App 


Al seleccionarla se mostrara una menú a la derecha donde tenemos la opción “Functions“ 


Al seleccionar la opción “Functions” se nos listará todas las funciones contenidas dentro del Azure Function App, en nuestro caso únicamente aparecerá Function1 que es el nombre con el quedó decorado nuestro método run de la azure function. 

Al seleccionar la función se nos mostrará un menú en la parte superior de la sección donde podemos obtener la dirección de nuestra función. 

Hay que notar que el link tiene en su querystring un código incorporado, este se generó automáticamente debido a que seleccionamos el authorization level en “Function”.

Con este url podemos probar nuestra función ahora alojada en la nube de Azure

 

Con esta entrada terminamos este pequeño tutorial de publicación en Azure de una azure function.


27 jul 2020

Azure Functions 1 – Dependency injection

Últimamente gracias a proyectos dentro de la compañía he tenido oportunidad de tener contacto con tecnologías en la “nube”, cloud computing como lo llaman los entendidos. Entre estas tecnologías están las azure functions que son parte de la oferta serverless de Microsoft. 

Estas funciones consisten en porciones de código que se ejecutan producto de algún trigger o evento. Estos triggers puede ser llamadas http, timers, archivos subidos a un blob storage, entre muchos otros tipos. Estas funciones en la versión 2 de las azure functions se pueden escribir utilizando .net core 3.1 (también se puede usar javascript) por lo que se pueden usar técnicas afines, por ejemplo, al web api o los sitios MVC tales como la inyección de dependencias.

Realicemos un ejercicio sencillo. Empecemos por crear nuestra azure function desde visual studio 2019:


Seleccionamos el template de las azure función y hacemos clic en “Next”


Le damos un nombre a nuestro proyecto, seleccionamos una ubicación y hacemos clic en “Create”. A continuación, se nos presentará la pantalla donde podemos seleccionar el trigger que desencadenará la ejecución de nuestra función.


Para nuestro ejercicio seleccionaremos el “HTTP trigger”. En el panel de la derecha si tuviéramos una cuenta en azure podríamos seleccionar el storage account al cual se subiría la azure función, también podemos dejarlo tal cual en el storage emulator como lo haremos en este caso. Adicionalmente podemos seleccionar el nivel de autorización (Authorization level) los cuales pueden ser:

Anonymous: no hay ningún mecanismo que restrinja el acceso.

Function: va a requerir un código o key para acceder a la función particular, este código se pude proporcionar por medio un campo llamado code en el querystring del llamado o bien en un header llamado x-functions-key.

Admin: al igual que el nivel de función el acceso es por medio de un código o key, solo que en este caso se conocen como “host key” y se define una sola llave para todas las funciones dentro de una app función mientras que en Funcion se debe definir un code para cada función.

En nuestro caso dejaremos el nivel del acceso por defecto, es decir Function.
Este template de Visual Studio nos proporciona una azure function totalmente funcional


Esta función espera un parámetro name ya sea en el querystring o bien como parte de un json en el body del llamado. Visual Studio proporciona una manera de probar nuestra función de manera local, sin necesidad de subirla a la nube de Azure. Simplemente ejecutamos nuestra función con lo cual se nos mostrará una ventana de consola como esta:


Como podemos notar en la sección Functions se nos listan las funciones que tenemos codificadas (en este caso solo tenemos una, pero podríamos tener “n”) al tiempo que nos indica, en el caso de las funciones activadas por http trigger, su endpoint. Podemos utilizar insomnia (o postman) por ejemplo para probar nuestra función


Bien, ya tenemos nuestra primera azure function, ahora hagamos esto un poco mas divertido. Añadimos un proyecto de lógica de negocios, en el cual tendremos una clase que vamos a utilizar en nuestra azure función por medio de la inyección de dependencias. Quedamos con algo similar a lo siguiente:


Ahora tenemos un proyecto BLL, donde tenemos nuestra clase RequestProcessor y su respectiva interfaz. 

IRequestProcessor: 

namespace BLL
{
    public interface IRequestProcessor
    {
        string ProcessName(string name);
    }
}

RequestProcessor: 

namespace BLL
{
    public class RequestProcessor : IRequestProcessor
    {
        public string ProcessName(string name)
        {
            return $"Hello {name} from Azure function!";
        }
    }
}


Ahora queremos utilizarla en nuestra función. Probablemente el código de nuestra función termine quedando algo más o menos así (Recordemos añadimos a nuestro proyecto AzureFuncionDI la referencia al proyecto BLL haciendo clic derecho sobre el primero y Add > Project Reference…): 

using BLL;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.IO;
using System.Threading.Tasks;

namespace AzureFunctionDI
{
    public class Function1
    {
        private readonly IRequestProcessor Processor;

        public Function1(IRequestProcessor Processor)
        {
            this.Processor = Processor;
        }

        [FunctionName("Function1")]
        public async Task <IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string name = req.Query["name"];

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            name = name ?? data?.name;

            string responseMessage = Processor.ProcessName(name);

            return new OkObjectResult(responseMessage);
        }
    }
}
¿Qué hicimos? Pues añadimos una variable del tipo interfaz y un constructor a nuestra clase para poder inyectar la clase que implementa esta interfaz y para esto debimos quitar el modificador static tanto de la clase como del método run. Esto compila, sin embargo, no se ejecuta correctamente; al realizar el llamado nos muestra algo como esto y nos devuelve un código 500 Internal Server Error:


Esto pasa porque nos hace falta una pieza muy importante que es donde realizamos la inversión del control, es decir, donde decimos que al solicitar un tipo de esa interfaz se debe insertar cierta clase en concreto. En las aplicaciones MVC esto se realiza en el Startup.cs pero aquí no tenemos este archivo, entonces, vamos a crearlo dentro del proyecto que contiene la azure function:

El código del archivo Startup sería el siguiente:

using BLL;
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;

[assembly: FunctionsStartup(typeof(AzureFunctionDI.Startup))]

namespace AzureFunctionDI
{
    public class Startup : FunctionsStartup
    {
        public override void Configure(IFunctionsHostBuilder builder)
        {
            builder.Services.AddScoped<IRequestProcessor, RequestProcessor>();
        }
    }
}
Como se mencionó al inicio, si ya hemos trabajado con el mecanismo de inyección de dependencias de .Net Core esto no parecerá muy familiar. Para que el código de arriba nos funcione debimos instalar el paquete Microsoft.Azure.Functions.Extensions ya que estamos heredando de functionStartup. En este código indicamos que al solicitar un tipo de interfaz IRequestProcessor se inyecte un objeto RequestProcessor el cual implementa dicha interfaz. Con esto ya en su lugar procedemos a ejecutar nuevamente la función.

Y he aquí que nuestra azure function con inyección de dependencias está funcionando.

En otra entrada explicare como realiza la publicación de la función puesto que esta entrada del blog ya se alargó bastante.