Publicando una aplicación .Net Framework en Azure con Docker y ServiceFrabric

Introducción


Docker es una de las herramientas más potentes con la que puedes llegar a hacer cosas alucinantes y que me enamoró desde el primer día que oí hablar de ella. Aunque su principal target son las arquitecturas de microservicios (principalmente en linux), las arquitecturas monolíticas también se pueden aprovechar mucho de la potencia de Docker, ya que Docker nos ofrece la posibilidad de tener nuestra aplicación dentro de un contenedor que nos permitirá distribuirla de forma sencilla sin la incertidumbre de las condiciones de cada entorno concreto. Es decir, se acabó el oír la típica frase de "en mi local funciona".

En el proyecto que me encuentro trabajando, aunque se hace uso de diferentes servicios, la parte web se compone de una arquitectura monolítica de N-capas con .Net Framework en el backend y Angular5 en el frontend. En un  plazo medio-corto uno de los objetivos es migrar esta arquitectura a Azure con SaaS y si se puede, aprovechado todas las ventajas que nos ofrece Docker.

Para esto he estado investigando cómo se puede realizar una migración de una arquitectura .Net Framework en Windows a Azure, haciendo uso de contenedores Docker. Para ejemplo voy a trabajar con una plantilla de aplicación MVC sencilla que me sirva como prueba de concepto.

Creando la aplicación web .net framework como un contenedor Docker


En primer lugar nos creamos una aplicación MVC con .net framework.

Capturavs1.JPG

Capturavs2.JPG

Una vez creada la aplicación podemos suponer que esta es nuestra aplicación inicial, con la que empezamos a trabajar. Ahora tenemos que poner docker en modo windows. Para esto, en el icono de la barra de tareas, hacemos clic derecho en el icono de docker y seleccionamos "Switch to Windows containers..."

Capturadocker1.JPG

Ahora al proyecto web, le añadimos soporte para docker. Para esto le hacemos clic derecho, Add, Docker Support.

Capturadocker2.JPG

Esto principalmente lo que hará será crearnos un proyecto docker-compose, que nos permitirá levantar varias aplicaciones con docker (si las hubiera) y en cada proyecto creará su Dockerfile, que el fichero que nos indica cómo se crea la imagen del proyecto.

Capturadocker3.JPG

Para nosotros, con el Dockerfile será suficiente. Si lo vemos, básicamente lo que hace es generar el site a partir de .net framework 4.7 y copiarlo a un dicrectorio publish. Además es muy importante añadir que lo exponga en el puerto 80 añadiendo la línea "EXPOSE 80" (esto no lo hace visual studio automáticamente). De no hacerlo, luego no veremos nuestra aplicación el Azure.

Capturadocker4.JPG

Una vez que tenemos esto, abrimos un PowerShell en directorio donde tengamos el Dockerfile y generamos nuestra imagen docker con el comando:
docker build -t prueba .

Captura2.JPG

Una vez creada la imagen la podemos ejecutar y probar a generar un contenedor con "docker run id_de_la_imagen". En nuestro caso, vamos a subirla a nuestro docker hub, para luego poder cargarla desde el service fabric. Para esto, tenemos que tener una cuenta docker y hacer login con "docker login". Una vez que introducimos las credenciales, podemos ponerle un tag a nuestra imagen y subirla a nuestro repositorio de docker con los siguientes comandos:
docker tag prueba acorrales/prueba
docker push acorrales/prueba

Captura3.JPG

Si todo fue bien, ya podemos ver la imagen en nuestro repositorio:

Capturadocker5.JPG

Con esto ya tenemos generada nuestra aplicación MVC windows en .net framework y subida a docker hub para poder ser distribuida. Ahora vamos a ver cómo desplegarla en Azure.

Creación de un cluster Service Frabric en Azure


Ahora toca publicar nuestra aplicación en Azure. Para esto tenemos diferentes alternativas y dos de las más conocidas son Kubernetes y Service Fabric. Ambas alternativas tienen algunas diferencias, pero nos permiten hacer cosas similares. Para nuestro ejemplo, basta con saber que nos permiten tener un cluster de aplicaciones o contenedores Docker. En otras palabras, que nuestra aplicación será publicada en varios nodos, que son gestionados por un cluster.

Para esta prueba de concepto he optado por service fabric, principalmente porque tienen un modo de prueba que viene muy bien para experimentar. Mediante este modo, te permiten tener un cluster de Service Fabric durante una hora para probar. Cuando se te a acabe la hora, te borran lo que tengas, pero puedes volver a solicitar otra hora de forma infinita.

Los pasos para obtener tu cluster durente una hora son:

  1. Accede a la siguiente url https://try.servicefabric.azure.com e inicia sesión con tu cuenta de facebook o github. Para nuestro ejemplo, selecciona "Join a Windows cluster".

  2. Ahora verás una pantalla como la siguiente. Ahora descarga el certificado pulsando en "PDX".clusterwebfree.JPG

  3. En la sección ReadMe, verás la siguiente información donde te indican cómo instalar el certificado. Captura.JPG

  4. En mi caso, he abierto un PowerShell en la ruta donde tenía el certificado y lo he instalado con la primera opción:Captura1.JPG

Desplegando el contenedor Docker en un Service Frabric


Ahora que ya tenemos nuestro cluster creado, nos vamos a visual studio y creamos un proyecto de Visual Studio, en el que tenemos que tener instalado el módulo de desarrollo en Azure. Seguimos estos pasos:

  1. Abrimos Visual Studio 2017 en modo administrador. Seleccionamos File > New > Project

  2. Seleccionamos Service Frabric application y lo llamamos "MyFirstContainer" y pulsamos OK.

  3. Elegimos la opción Container y en Image Name ponemos el nombre del contenedor que hemos usado en docker hub. En mi caso "acorrales/prueba".

Ahora tenemos una aplicación como la siguiente:

CapturaSF2.JPG

El servicio necesita configurar el endpoint para la comunicación. En este caso, nuestro contenedor escucha el puerto 80, por lo que cambiamos el fichero MyFirstContainer/ApplicationPackageRoot/MyContainerServicePkg/ServiceManifest.xml.
<Resources> 
   <Endpoints> 
      <Endpoint Name="MyContainerServiceTypeEndpoint" UriScheme="http" Port="80" Protocol="http"/> 
   </Endpoints> 
</Resources>

Ahora mapeamos el puerto 80 del contenedor, al puerto 80 del servicio. Para esto vamos a MyFirstContainer/ApplicationPackageRoot/ApplicationManifest.xml y añadimos:
<ServiceManifestImport>
...
  <ConfigOverrides />
    <Policies>
      <ContainerHostPolicies CodePackageRef="Code">
    <PortBinding ContainerPort="80" EndpointRef="MyContainerServiceTypeEndpoint"/>
  </ContainerHostPolicies>
 </Policies>
</ServiceManifestImport>

Una vez configurado el servicio, vamos a publicar el contenedor en nuestro cluster. Para esto hacemos clic derecho sobre el proyecto y le damos a "Publish". Veremos una pantalla como la siguiente, en la que tenemos que poner la url del endpoint de nuestro cluster. En mi caso es el:
win242opmikvth.westus.cloudapp.azure.com:19000

CapturaSF1.JPG

Una vez que el despliegue termina correctamente, podemos ir a la url del explorador del cluster en la url que nos dieron
https://win242opmikvth.westus.cloudapp.azure.com:19080/Explorer/index.html

y podremos ver una pantalla como la siguiente:

clusteradmin.JPG

En esta pantalla podemos ver el estado de nuestro cluster. En mi caso podemos ver que tengo tres nodos y que la aplicación que he desplegado ya está corriendo.

Por último, si hemos hecho todo bien, podemos ir a la url del servicio y podremos ver nuestra aplicación .net framework funcionando en la web:
http://win242opmikvth.westus.cloudapp.azure.com/

Hasta que nuestra web sea visible, puede tardar un buen rato, en función de las dependencias que tenga nuestro contenedor docker, y en el caso de los contenedores de windows suelen ser bastante pesados, por lo que suele tardar un buen rato.

clusterservicio.JPG

Para profundizar más en los conceptos expuestos, recomiendo la lectura del libro Modernizing .Net Apps.

31475227-74e43246-aeb4-11e7-8dba-44da5fc3874b[1]

Otros enlaces de interés:

Happy coding ;-)

Comments

Popular posts from this blog

Azure DevOps: Deploy your SPA on AWS S3 bucket

Why you should migrate your old csproj to SDK format

Writing unit tests faster