Você está na página 1de 37

Table of Contents

Microservicios de .NET: Arquitectura para aplicaciones .NET en contenedor


Introducción a los contenedores y Docker
¿Qué es Docker?
Terminología de Docker
Contenedores, imágenes y registros de Docker
Selección entre .NET Core y .NET Framework para contenedores de Docker
Orientación general
Cuándo elegir .NET Core para contenedores de Docker
Cuándo elegir .NET Framework para contenedores de Docker
Tabla de decisiones: versiones de .NET Framework para su uso con Docker
Selección del sistema operativo de destino con contenedores de .NET
Imágenes de Docker de .NET oficiales
Diseñar la arquitectura de aplicaciones basadas en contenedor y microservicio
Incluir en un contenedor aplicaciones monolíticas
Estado y datos en aplicaciones de Docker
Arquitectura orientada a servicios
Arquitectura de microservicios
Propiedad de los datos por microservicio
Arquitectura lógica frente a arquitectura física
Desafíos y soluciones de la administración de datos distribuidos
Identificar los límites del modelo de dominio para cada microservicio
Comunicación entre microservicios
Comunicación asincrónica basada en mensajes
Crear, desarrollar y controlar las versiones de los contratos y las API de microservicio
Direccionabilidad de microservicios y el Registro de servicios
Crear una interfaz de usuario compuesta en función de los microservicios, incluidos
la forma y el diseño visual de la interfaz de usuario generados por varios
microservicios
Resistencia y la alta disponibilidad en microservicios
Orquestar microservicios y aplicaciones de varios contenedores para una alta
escalabilidad y disponibilidad
Uso de Azure Service Fabric
Proceso de desarrollo de aplicaciones basadas en Docker
Flujo de trabajo de desarrollo para aplicaciones de Docker
Implementar aplicaciones web de .NET Core basadas en un solo contenedor en hosts
de Linux o Windows Nano Server
Migrar aplicaciones de .NET Framework monolíticas heredadas a contenedores de
Windows
Diseñar y desarrollar aplicaciones .NET basadas en varios contenedores y
microservicios
Diseñar una aplicación orientada a microservicios
Crear un microservicio CRUD sencillo controlado por datos
Definir una aplicación de varios contenedores con docker-compose.yml
Usar un servidor de bases de datos que se ejecuta como un contenedor
Implementar la comunicación basada en eventos entre microservicios (eventos de
integración)
Implementar un bus de eventos con RabbitMQ para el entorno de desarrollo o de
prueba
Suscribirse a eventos
Probar aplicaciones web y servicios ASP.NET Core
Abordar la complejidad empresarial en un microservicio con patrones DDD y CQRS
Aplicar los patrones CQRS y DDD simplificados en un microservicio
Aplicar enfoques CQRS y CQS en un microservicio DDD en eShopOnContainers
Implementar lecturas/consultas en un microservicio CQRS
Diseñar un microservicio orientado a DDD
Diseñar un modelo de dominio de microservicio
Implementar un modelo de dominio de microservicio con .NET Core
Seedwork (clases base e interfaces reutilizables para el modelo de dominio)
Implementar objetos de valor
Usar las clases de enumeración en lugar de tipos de enumeración
Diseñar las validaciones en el nivel de modelo de dominio
Validación del lado cliente (validación de los niveles de presentación)
Eventos de dominio: diseño e implementación
Diseñar el nivel de persistencia de infraestructura
Implementar el nivel de persistencia de infraestructura con Entity Framework Core
Usar bases de datos NoSQL como una infraestructura de persistencia
Diseñar el nivel de aplicación de microservicios y API web
Implementar el nivel de aplicación de microservicios mediante la API web
Implementar aplicaciones resistentes
Controlar errores parciales
Estrategias para controlar errores parciales
Implementar reintentos con retroceso exponencial
Implementar conexiones SQL resistentes de Entity Framework Core
Implementar reintentos de llamada HTTP personalizados con retroceso exponencial
Implementar reintentos de llamada HTTP con retroceso exponencial con Polly
Implementar el patrón de interruptor
Supervisión de matenimiento
Proteger microservicios y aplicaciones web de .NET
Acerca de la autorización en microservicios y aplicaciones web de .NET
Almacenar secretos de aplicación de forma segura durante el desarrollo
Usar Azure Key Vault para proteger secretos en tiempo de producción
Puntos clave
03/10/2017 • 6 min to read • Edit Online

Microservicios de .NET. Arquitectura para aplicaciones .NET


en contenedor
DESCARGA disponible en: https://aka.ms/microservicesebook
PUBLICADO POR
Equipos de producto de la División de desarrolladores de Microsoft, .NET y Visual Studio
División de Microsoft Corporation
One Microsoft Way
Redmond, Washington 98052-6399
Copyright © 2017 de Microsoft Corporation
Todos los derechos reservados. No se puede reproducir ni transmitir de ninguna forma ni por ningún medio
ninguna parte del contenido de este libro sin la autorización por escrito del publicador.
Este libro se proporciona “tal cual” y expresa las opiniones del autor. Las opiniones y la información expresados en
este libro, incluidas las direcciones URL y otras referencias a sitios web de Internet, pueden cambiar sin previo
aviso.
Algunos ejemplos descritos aquí se proporcionan únicamente con fines ilustrativos y son ficticios. No debe
deducirse ninguna asociación ni conexión reales.
Microsoft y las marcas comerciales indicadas en http://www.microsoft.com en la página web “Marcas comerciales”
pertenecen al grupo de empresas de Microsoft.
Mac y macOS son marcas comerciales de Apple Inc.
El logotipo de la ballena de Docker es una marca registrada de Docker, Inc. Se usa con permiso.
El resto de marcas y logotipos pertenece a sus respectivos propietarios.
Coautores:

Cesar de la Torre, administrador de programas sénior del equipo del producto de .NET, Microsoft Corp.
Bill Wagner, desarrollador de contenido sénior de C+E, Microsoft Corp.
Mike Rousos, ingeniero de software principal del equipo de CAT de la división de desarrollo, Microsoft

Editores:

Mike Pope
Steve Hoag

Participantes y revisores:

Jeffrey Ritcher, ingeniero de software asociado del equipo de Azure, Microsoft


Jimmy Bogard, arquitecto jefe de Headspring
Udi Dahan, fundador y director general de Particular Software
Jimmy Nilsson, cofundador y director general de Factor10
Glenn Condron, director de programas sénior del equipo de ASP.NET
Mark Fussell, responsable principal de administración de programas del equipo de Azure Service Fabric,
Microsoft
Diego Vega, responsable de administración de programas del equipo de Entity Framework, Microsoft
Barry Dorrans, administrador de programas de seguridad sénior
Rowan Miller, administrador de programas sénior, Microsoft
Ankit Asthana, director principal de administración de programas del equipo de .NET, Microsoft
Scott Hunter, director asociado de administración de programas del equipo de .NET, Microsoft
Dylan Reisenberger, arquitecto y responsable de desarrollo de Polly
Steve Smith, artesano e instructor de software de ASPSmith Ltd.
Cooper Ian, arquitecto de codificación de Brighter
Unai Zorrilla, arquitecto y responsable de desarrollo de Plain Concepts
Eduard Tomas, responsable de desarrollo de Plain Concepts
Ramon Tomas, desarrollador de Plain Concepts
David Sanz, desarrollador de Plain Concepts
Javier Valero, director de operaciones de Grupo Solutio
Pierre Millet, asesor sénior de Microsoft
Michael Friis, administrador de productos de Docker Inc.
Charles Lowell, ingeniero de software del equipo de CAT de VS, Microsoft

Introducción
Las empresas cada vez ahorran más costos, resuelven más problemas de implementación y mejoran más las
operaciones de DevOps y producción mediante el uso de contenedores. Microsoft ha lanzado recientemente
innovaciones en los contenedores de Windows y Linux con la creación de productos como Azure Container Service
y Azure Service Fabric, contando además con la colaboración de líderes del sector como Docker, Mesosphere y
Kubernetes. Estos productos ofrecen soluciones de contenedores que ayudan a las empresas a compilar e
implementar aplicaciones a velocidad y escala de nube, sea cual sea la plataforma o las herramientas que hayan
elegido.
Docker se está convirtiendo en el estándar de facto del sector de los contenedores, ya que es compatible con los
proveedores más importantes del ecosistema de Windows y Linux. (Microsoft es uno de los principales
proveedores de nube que admite Docker). En el futuro, Docker probablemente estará omnipresente en todos los
centros de datos en la nube o locales.
Además, la arquitectura de microservicios se está convirtiendo en un enfoque fundamental para las aplicaciones
críticas distribuidas. En una arquitectura basada en microservicios, la aplicación se basa en una colección de
servicios que se pueden desarrollar, probar, implementar y versionar por separado.

Acerca de esta guía


Esta guía es una introducción al desarrollo de aplicaciones basadas en microservicios y a su administración
mediante contenedores. En ella se trata el diseño de la arquitectura y los métodos de implementación con .NET
Core y contenedores de Docker. Para que sea más fácil empezar a trabajar con contenedores y microservicios, la
guía se centra en una aplicación de referencia en contenedor y basada en microservicios que puede explorar. Esta
misma aplicación de ejemplo está disponible en el repositorio de GitHub eShopOnContainers.
En esta guía se proporciona el desarrollo fundamental y una guía de arquitectura principalmente en el nivel del
entorno de desarrollo con especial hincapié en dos tecnologías: Docker y .NET Core. Nuestra intención es que lea
esta guía cuando reflexione sobre el diseño de las aplicaciones sin centrarse en la infraestructura (en la nube o
local) de su entorno de producción. Tomará decisiones sobre la infraestructura más adelante, cuando cree
aplicaciones listas para la producción. Por lo tanto, esta guía está diseñada para ser independiente de la
infraestructura y centrarse en el desarrollo y el entorno.
Una vez que haya estudiado esta guía, el siguiente paso que debería dar es obtener información sobre los
microservicios listos para la producción en Microsoft Azure.
Aspectos no tratados en esta guía
Esta guía no se centra en el ciclo de vida de la aplicación, DevOps, las canalizaciones CI/CD ni el trabajo de equipo.
La guía complementaria Containerized Docker Application Lifecycle with Microsoft Platform and Tools (Ciclo de
vida de aplicaciones de Docker en contenedor con la plataforma y herramientas de Microsoft) se centra en esas
cuestiones. La guía actual tampoco proporciona detalles de implementación de la infraestructura de Azure, como
información sobre orquestadores específicos.
Recursos adicionales
Containerized Docker Application Lifecycle with Microsoft Platform and Tools (Ciclo de vida de
aplicaciones de Docker en contenedor con la plataforma y herramientas de Microsoft) (libro electrónico
descargable) https://aka.ms/dockerlifecycleebook

Destinatarios de esta guía


Esta guía se ha escrito para desarrolladores y arquitectos de soluciones que no están familiarizados con el
desarrollo de aplicaciones basado en Docker y la arquitectura basada en microservicios. Esta guía será de su interés
si quiere obtener información sobre cómo crear arquitecturas, diseñar e implementar aplicaciones de prueba de
concepto con tecnologías de desarrollo de Microsoft (con un hincapié especial en .NET Core) y con contenedores de
Docker.
También le resultará útil si es el responsable de tomar decisiones técnicas (por ejemplo, un arquitecto empresarial)
y necesita una descripción de la arquitectura y la tecnología antes de decidir qué enfoque tomar para el diseño de
aplicaciones distribuidas tanto nuevas como modernas.
Cómo usar esta guía
La primera parte de esta guía presenta los contenedores de Docker, describe cómo elegir entre .NET Core y .NET
Framework como marco de desarrollo y proporciona una visión general de los microservicios. Este contenido está
destinado a arquitectos y responsables de la toma de decisiones técnicas que quieren obtener información general
pero que no necesitan centrarse en los detalles de la implementación de código.
La segunda parte de la guía comienza con la sección Proceso de desarrollo de aplicaciones basadas en Docker. Se
centra en los patrones de desarrollo y microservicios usados en la implementación de las aplicaciones que utilizan
.NET Core y Docker. Esta sección será de gran interés para los desarrolladores y los arquitectos que quieran
centrarse en el código, en los patrones y los detalles de implementación.

Aplicación de referencia relacionada de microservicios y basada en


contenedor: eShopOnContainers
La aplicación eShopOnContainers es una aplicación de referencia para .NET Core y microservicios que está
diseñada para implementarse mediante contenedores de Docker. La aplicación consta de varios subsistemas,
incluidos varios front-end de interfaz de usuario de almacén electrónico (una aplicación web y una aplicación móvil
nativa). También incluye microservicios y contenedores de back-end para todas las operaciones del lado servidor
necesarias.
El código fuente de la aplicación de microservicios basada en contenedor es código abierto y está disponible en el
repositorio de GitHub eShopOnContainers.

Envíenos sus comentarios.


Hemos creado esta guía para ayudarle a entender la arquitectura de aplicaciones y microservicios en contenedor
en .NET. La guía y la aplicación de referencia relacionada irán evolucionando, por lo que le agradecemos sus
comentarios. Si tiene comentarios sobre cómo se puede mejorar esta guía, envíelos a:
dotnet-architecture-ebooks-feedback@service.microsoft.com
S IG U IE N T E
Introducción a Containers y Docker
03/10/2017 • 1 min to read • Edit Online

La inclusión en contenedores es un enfoque de desarrollo de software en el que una aplicación o un servicio, sus
dependencias y su configuración (extraídos como archivos de manifiesto de implementación) se empaquetan
como una imagen de contenedor. La aplicación en contenedor puede probarse como una unidad e implementarse
como una instancia de imagen de contenedor en el sistema operativo (SO) host.
Del mismo modo que los contenedores de mercancías permiten su transporte por barco, tren o camión
independientemente de la carga de su interior, los contenedores de software actúan como una unidad estándar de
software que puede contener diferentes dependencias y código. De esta manera, la inclusión del software en
contenedor permite a los desarrolladores y los profesionales de TI implementarlo en entornos con pocas
modificaciones o ninguna en absoluto.
Los contenedores también aíslan las aplicaciones entre sí en un sistema operativo compartido. Las aplicaciones en
contenedor se ejecutan sobre un host de contenedor que a su vez se ejecuta en el sistema operativo (Linux o
Windows). Por lo tanto, los contenedores tienen una superficie significativamente menor que las imágenes de
máquina virtual (VM).
Cada contenedor puede ejecutar una aplicación web o un servicio al completo, como se muestra en la figura 2-1.
En este ejemplo, el host de Docker es un host de contenedor, y App 1, App 2, Svc 1 y Svc 2 son aplicaciones o
servicios en contenedor.

Figura 2-1. Varios contenedores ejecutándose en un host de contenedor.


Otra ventaja de la inclusión en contenedores es la escalabilidad. La creación de contenedores para tareas a corto
plazo permite escalar horizontalmente con gran rapidez. Desde el punto de vista de la aplicación, la creación de
instancias de una imagen (la creación de un contenedor) es similar a la creación de instancias de un proceso como
un servicio o una aplicación web. Pero con fines de confiabilidad, cuando ejecute varias instancias de la misma
imagen en varios servidores host, seguramente le interesará que cada contenedor (instancia de imagen) se ejecute
en un servidor host o máquina virtual diferente en dominios de error distintos.
En resumen, los contenedores ofrecen las ventajas del aislamiento, la portabilidad, la agilidad, la escalabilidad y el
control a lo largo de todo el flujo de trabajo del ciclo de vida de la aplicación. La ventaja más importante es el
aislamiento que se proporciona entre el desarrollo y las operaciones.
A N T E R IO R S IG U IE N T E
Selección entre .NET Core y .NET Framework para
contenedores de Docker
03/10/2017 • 1 min to read • Edit Online

Se admiten dos implementaciones para compilar aplicaciones de Docker en contenedor del lado del servidor con
.NET: .NET Framework y .NET Core. Ambas comparten muchos de los componentes de .NET Standard y es posible
compartir código entre ellas. Aun así, presentan diferencias fundamentales, y la elección de la implementación
dependerá de lo que quiera realizar. En esta sección se proporciona orientación sobre cuándo se debe elegir cada
implementación.

A N T E R IO R S IG U IE N T E
Diseñar la arquitectura de aplicaciones basadas en
contenedores y microservicios
03/10/2017 • 2 min to read • Edit Online

Los microservicios ofrecen grandes ventajas, pero también generan nuevos desafíos enormes. Los patrones de
arquitectura de microservicios son los pilares fundamentales a la hora de crear una aplicación basada en
microservicios.
Previamente en esta guía, ha aprendido los conceptos básicos sobre los contenedores y Docker. Con esa
información mínima, ya puede empezar a trabajar con contenedores. Aunque los contenedores son habilitadores y
se consideran una gran elección para microservicios, no son obligatorios para una arquitectura de microservicios, y
muchos conceptos arquitectónicos de esta sección sobre la arquitectura también se podrían aplicar sin
contenedores. A pesar de ello, esta guía se centra en la intersección de ambos debido a la importancia actual de los
contenedores.
Las aplicaciones empresariales pueden ser complejas y, a menudo, se componen de varios servicios en lugar de
una sola aplicación basada en servicios. En esos casos, debe comprender otros enfoques de arquitectura, como son
los microservicios y determinados patrones de diseño guiado por el dominio (DDD), además de conceptos de
orquestación de contenedores. Tenga en cuenta que en este capítulo no solo se describen los microservicios en
contenedor, sino cualquier aplicación en contenedor.

Principios de diseño de contenedores


En el modelo de contenedor, una instancia de imagen de contenedor representa un único proceso. Al definir una
imagen de contenedor como un límite de proceso, puede crear primitivas que se usen para escalar el proceso o
para procesarlo por lotes.
Cuando diseñe una imagen de contenedor, verá una definición ENTRYPOINT en el archivo Dockerfile. Esto define el
proceso cuya duración controla la duración del contenedor. Cuando se completa el proceso, finaliza el ciclo de vida
del contenedor. Los contenedores pueden representar procesos de ejecución prolongada como servidores web,
pero también pueden representar procesos de corta duración, como trabajos por lotes, que anteriormente se
implementarían como WebJobs de Azure.
Si se produce un error en el proceso, el contenedor finaliza y lo sustituye el orquestador. Si el orquestador está
configurado para mantener cinco instancias en ejecución y se produce un error en una de ellas, el orquestador
creará otra instancia del contenedor para reemplazar al proceso con error. En un trabajo por lotes, el proceso se
inicia con parámetros. Cuando el proceso finalice, el trabajo se habrá completado.
Es posible que en algún momento le interese que varios procesos se ejecuten en un solo contenedor. En ese caso,
dado que solo puede haber un punto de entrada por contenedor, puede ejecutar dentro del contenedor un script
que inicie todos los programas que sean necesarios. Por ejemplo, puede usar Supervisor o una herramienta similar
para que se encargue de iniciar varios procesos dentro de un único contenedor. Este método no es muy habitual,
aunque existan arquitecturas que contengan varios procesos por contenedor.

A N T E R IO R S IG U IE N T E
1 min to read •
Edit O nline
Proceso de desarrollo de aplicaciones basadas en
Docker
03/10/2017 • 2 min to read • Edit Online

Desarrolle aplicaciones .NET en contenedor de la forma que prefiera, ya sea centradas en el IDE con Visual Studio y
Visual Studio Tools para Docker o bien centradas en la CLI o el editor con la CLI de Docker y Visual Studio Code.

Entorno de desarrollo para aplicaciones de Docker


Opciones de herramientas de desarrollo: IDE o editor
Tanto si quiere un IDE eficaz y completo como si prefiere un editor ligero y ágil, Microsoft dispone de herramientas
que puede usar para desarrollar aplicaciones de Docker.
Visual Studio Tools para Docker. Si usa Visual Studio 2015, puede instalar el complemento Visual Studio Tools
para Docker. Si usa Visual Studio 2017, las herramientas para Docker ya están integradas. En cualquier caso, las
herramientas para Docker permiten desarrollar, ejecutar y validar las aplicaciones directamente en el entorno de
Docker de destino. Puede presionar F5 para ejecutar y depurar la aplicación (de un solo contenedor o de varios
contenedores) directamente en un host de Docker, o bien presionar CTRL+F5 para editar y actualizar la aplicación
sin tener que volver a compilar el contenedor. Esta es la opción más sencilla y más eficaz para los desarrolladores
de Windows que tienen como destino contenedores de Docker para Linux o Windows.
Visual Studio Code y la CLI de Docker. Si prefiere un editor ligero multiplataforma que admita todos los
lenguajes de programación, puede usar Microsoft Visual Studio Code (VS Code) y la CLI de Docker. Se trata de un
enfoque de desarrollo multiplataforma para Mac, Linux y Windows.
Estos productos proporcionan una experiencia sencilla pero sólida que agiliza el flujo de trabajo del desarrollador.
Mediante la instalación de las herramientas de Docker Community Edition (CE), puede usar una sola CLI de Docker
para compilar aplicaciones para Windows y Linux. Además, Visual Studio Code admite extensiones para Docker
como IntelliSense para Dockerfiles y tareas de acceso directo para ejecutar comandos de Docker desde el editor.
Recursos adicionales
Visual Studio Tools para Docker https://visualstudiogallery.msdn.microsoft.com/0f5b2caa-ea00-41c8-
b8a2-058c7da0b3e4
Visual Studio Code. Sitio oficial. https://code.visualstudio.com/download
Docker Community Edition (CE) para Mac y Windows https://www.docker.com/community-editions

Lenguajes y marcos de .NET para contenedores de Docker


Como se ha mencionado en secciones anteriores de esta guía, puede usar .NET Framework, .NET Core o el proyecto
Mono de código abierto para desarrollar aplicaciones .NET en contenedor de Docker. Puede desarrollar en C#, F# o
Visual Basic cuando tenga como destino contenedores de Windows o Linux, en función de qué versión de .NET
Framework esté en uso. Para obtener más información sobre lenguajes de .NET, vea la entrada de blog The .NET
Language Strategy (Estrategia de lenguaje de .NET).

A N T E R IO R S IG U IE N T E
Implementar aplicaciones web de .NET Core basadas
en un solo contenedor en hosts de Linux o Windows
Nano Server
03/10/2017 • 9 min to read • Edit Online

Puede usar contenedores de Docker para la implementación monolítica de aplicaciones web más sencillas. Esto
mejora la integración continua y las canalizaciones de implementación continua y ayuda a llevar a cabo
correctamente el proceso desde la implementación hasta la producción. Ya no se volverá a preguntar: "Funciona
en mi equipo, ¿por qué no funciona en producción?".
Una arquitectura basada en microservicios tiene muchas ventajas, pero a costa de una mayor complejidad. En
algunos casos, los costos superan a las ventajas y podría resultarle más útil una aplicación de implementación
monolítica que se ejecute en un solo contenedor o en unos pocos contenedores.
Es posible que una aplicación monolítica no se pueda descomponer fácilmente en microservicios bien separados.
Ya ha aprendido que estos se deben particionar por función: los microservicios deberían funcionar de manera
independiente para proporcionar una aplicación más resistente. Si no puede proporcionar sectores de
características de la aplicación, el hecho de separarla solo agrega complejidad.
Una aplicación podría no necesitar inicialmente el escalado de las características por separado. Supongamos que
en una fase temprana del ciclo de vida de la aplicación de referencia eShopOnContainers, el tráfico no justificaba
separar las características en diferentes microservicios. El tráfico era bastante reducido y el hecho de agregar
recursos a un servicio normalmente suponía agregar recursos a todos los servicios. El trabajo adicional que
suponía separar la aplicación en servicios diferenciados apenas proporcionaba beneficio.
Además, en las fases tempranas del desarrollo de una aplicación, es posible que no se tenga una idea clara de
dónde están los límites funcionales naturales. Mientras desarrolla un producto mínimamente viable, puede que
todavía no sea evidente la separación natural.
Algunas de estas condiciones pueden ser temporales. Podría empezar creando una aplicación monolítica y, más
adelante, separar algunas características para desarrollarlas e implementarlas como microservicios. Otras
condiciones podrían ser básicas para el espacio de problemas de la aplicación y, en consecuencia, tal vez no se
pueda dividir nunca en varios microservicios.
La separación de una aplicación en varios procesos diferenciados también introduce una sobrecarga. La separación
de funciones en procesos diferentes conlleva una mayor complejidad. Los protocolos de comunicación se vuelven
más complejos. En lugar de llamadas a métodos, debe usar comunicaciones asincrónicas entre servicios. Cuando
cambie a una arquitectura de microservicios, deberá agregar muchos de los bloques de creación que se
implementan en la versión de microservicios de la aplicación eShopOnContainers: control de bus de eventos,
reintentos y resistencia de mensajes, coherencia eventual y mucho más.
Una versión muy simplificada de eShopOnContainers (denominada eShopWeb e incluida en el mismo repositorio
de GitHub) se ejecuta como una aplicación de MVC monolítica y, tal como se ha indicado, esta opción de diseño
ofrece una serie de ventajas. Puede descargar de GitHub el código fuente para esta aplicación y ejecutarlo de forma
local. Incluso esta aplicación monolítica se beneficia de la implementación en un entorno de contenedor.
Ante todo, la implementación en contenedor implica que cada instancia de la aplicación se ejecuta en el mismo
entorno. Esto incluye el entorno de desarrollo donde tienen lugar las pruebas y el desarrollo iniciales. El equipo de
desarrollo puede ejecutar la aplicación en un entorno en contenedor que coincida con el entorno de producción.
Además, las aplicaciones en contenedor se escalan horizontalmente con un costo menor. Como ya ha visto, el
entorno en contenedor permite un mayor uso compartido de recursos que los entornos de máquina virtual
tradicionales.
Por último, el hecho de incluir la aplicación en un contenedor fuerza la separación entre la lógica de negocios y el
servidor de almacenamiento. Cuando la aplicación se escala horizontalmente, los diversos contenedores se basan
en un único medio de almacenamiento físico. Normalmente, se trata de un servidor de alta disponibilidad que
ejecuta una base de datos de SQL Server.

Paseo por la aplicación


La aplicación eShopWeb representa una parte de la aplicación eShopOnContainers que se ejecuta como una
aplicación monolítica (una aplicación basada en MVC de ASP.NET Core que se ejecuta en .NET Core). Básicamente,
proporciona las funciones de exploración del catálogo que se han descrito en secciones anteriores.
La aplicación usa una base de datos de SQL Server para el almacenamiento del catálogo. En las implementaciones
basadas en contenedor, esta aplicación monolítica puede tener acceso al mismo almacén de datos que la aplicación
basada en microservicios. La aplicación está configurada para ejecutar SQL Server en un contenedor junto con la
aplicación monolítica. En un entorno de producción, SQL Server se ejecutaría en una máquina con alta
disponibilidad, fuera del host de Docker. Para mayor comodidad en un entorno de desarrollo o de pruebas, se
recomienda ejecutar SQL Server en su propio contenedor.
El conjunto de características iniciales solo permite examinar el catálogo. Mediante las actualizaciones se habilitará
el conjunto completo de características de la aplicación en contenedor. En el libro electrónico ASP.NET Web
Application architecture practices (Prácticas de la arquitectura de aplicaciones web ASP.NET) y en la aplicación de
ejemplo eShopOnWeb relacionada se describe una arquitectura de aplicaciones web monolítica más avanzada,
aunque en este caso no se ejecuta en contenedores de Docker, ya que el escenario se centra en el desarrollo web
simple con ASP.NET Core.
Aun así, la versión simplificada disponible en eShopOnContainers (eShopWeb) se ejecuta en un contenedor de
Docker.

Compatibilidad con Docker


El proyecto eShopOnWeb se ejecuta en .NET Core. Por lo tanto, se puede ejecutar en contenedores basados en
Linux o en Windows. Tenga en cuenta que, para la implementación de Docker, le interesa usar el mismo tipo de
host para SQL Server. Los contenedores basados en Linux permiten una superficie menor y son preferibles.
Visual Studio proporciona una plantilla de proyecto que agrega compatibilidad con Docker a una solución. Para
ello, haga clic con el botón derecho en el proyecto y haga clic en Agregar y en Compatibilidad con Docker. La
plantilla agrega un archivo Dockerfile al proyecto y un nuevo proyecto docker-compose que proporciona un
archivo de inicio docker-compose.yml. Este paso ya se ha llevado a cabo en el proyecto eShopOnWeb descargado
de GitHub. Verá que la solución contiene el proyecto eShopOnWeb y el proyecto docker-compose tal como se
muestra en la figura 6-1.

Figura 6-1. Proyecto docker-compose en una aplicación web de un solo contenedor.


Estos archivos son archivos estándar docker-compose, coherentes con cualquier proyecto de Docker. Puede usarlos
con Visual Studio o desde la línea de comandos. Esta aplicación se ejecuta en .NET Core y usa contenedores de
Linux, por lo que también puede codificar, compilar y ejecutar en un equipo Mac o en un equipo Linux.
El archivo docker-compose.yml contiene información sobre qué imágenes se van a compilar y qué contenedores se
van a iniciar. Las plantillas especifican cómo se compila la imagen eshopweb y cómo se inician los contenedores de
la aplicación. Debe agregar la dependencia en SQL Server. Para hacerlo, incluya una imagen para ella (por ejemplo,
mssql-server-linux) y un servicio para la imagen sql.data de modo que Docker compile e inicie ese contenedor. Esta
configuración se muestra en el ejemplo siguiente:

version: '2'

services:
eshopweb:
image: eshop/web
build:
context: ./eShopWeb
dockerfile: Dockerfile
depends_on:
- sql.data

sql.data:
image: microsoft/mssql-server-linux

La directiva depends_on le indica a Docker que la imagen eShopWeb depende de la imagen sql.data. Unas líneas
por debajo se encuentran las instrucciones para compilar una imagen etiquetada como sql.data mediante la
imagen microsoft/mssql-server-linux.
En el proyecto docker-compose se muestran los demás archivos docker-compose bajo el nodo principal docker-
compose.yml. Esto ayuda a señalar visualmente la relación entre estos archivos. El archivo docker-compose-
override.yml contiene los valores de configuración de ambos servicios, como las cadenas de conexión y otros
valores para las aplicaciones.
En el ejemplo siguiente se muestra el archivo docker-compose.vs.debug.yml, que contiene los valores usados para
la depuración en Visual Studio. En ese archivo, la imagen eshopweb tiene anexada la etiqueta de desarrollo. Esto
ayuda a separar las imágenes de depuración de las imágenes de lanzamiento, para que no se implemente
accidentalmente la información de depuración en un entorno de producción:

version: '2'

services:
eshopweb:
image: eshop/web:dev
build:
args:
source: ${DOCKER_BUILD_SOURCE}
environment:
- DOTNET_USE_POLLING_FILE_WATCHER=1
volumes:
- ./eShopWeb:/app
- ~/.nuget/packages:/root/.nuget/packages:ro
- ~/clrdbg:/clrdbg:ro
entrypoint: tail -f /dev/null
labels:
- "com.microsoft.visualstudio.targetoperatingsystem=linux"

El último archivo agregado es docker-compose.ci.build.yml, que se usaría desde la línea de comandos para
compilar el proyecto desde un servidor CI. Este archivo compuesto inicia un contenedor de Docker que compila las
imágenes necesarias para la aplicación. En el ejemplo siguiente se muestra el contenido del archivo docker-
compose.ci.build.yml.
version: '2'

services:
ci-build:
image: microsoft/aspnetcore-build:1.0-1.1
volumes:
- .:/src
working_dir: /src
command: /bin/bash -c "dotnet restore ./eShopWeb.sln && dotnet publish ./eShopWeb.sln -c Release -o
./obj/Docker/publish"

Tenga en cuenta que la imagen es una imagen de compilación de ASP.NET Core. Esta imagen incluye las
herramientas de compilación y el SDK para compilar la aplicación y crear las imágenes necesarias. Al ejecutar el
proyecto docker-compose con este archivo, se inicia el contenedor de compilación desde la imagen y se compila
la imagen de la aplicación en ese contenedor. Debe especificar ese archivo docker-compose como parte de la línea
de comandos para compilar la aplicación en un contenedor de Docker y, después, iniciarlo.
En Visual Studio, puede ejecutar la aplicación en contenedores de Docker. Para ello, seleccione el proyecto docker-
compose como proyecto de inicio y presione Ctrl+F5 (F5 para depurar), como haría con cualquier otra aplicación.
Cuando se inicia el proyecto docker-compose, Visual Studio ejecuta docker-compose mediante el archivo
docker-compose.yml, el archivo docker-compose.override.yml y uno de los archivos docker-compose.vs.*. Una vez
que se ha iniciado la aplicación, Visual Studio abre automáticamente el explorador.
Si inicia la aplicación en el depurador, Visual Studio se asociará a la aplicación en ejecución en Docker.

Solución de problemas
En esta sección se describen algunos de los problemas que pueden surgir cuando se ejecutan contenedores de
manera local y se sugieren diversas correcciones.
Detener contenedores de Docker
Después de iniciar la aplicación en contenedor, los contenedores siguen ejecutándose incluso después de que se
haya detenido la depuración. Puede ejecutar el comando docker ps desde la línea de comandos para ver qué
contenedores se están ejecutando. El comando docker stop detiene un contenedor en ejecución, tal como se
muestra en la figura 6-2.
Figura 6-2. Mostrar y detener contenedores con los comandos docker ps y docker stop de la CLI
Es posible que necesite detener procesos en ejecución cuando cambie entre diferentes configuraciones. En caso
contrario, el contenedor que ejecuta la aplicación web usará el puerto para la aplicación (5106 en este ejemplo).
Agregar Docker a los proyectos
El asistente que agrega compatibilidad con Docker se comunica con el proceso de Docker que se está ejecutando. El
asistente no se ejecutará correctamente si Docker no está funcionando cuando se inicie el asistente. Además, el
asistente examinará el contenedor que ha elegido actualmente para agregar la compatibilidad correcta con Docker.
Si quiere agregar compatibilidad con contenedores de Windows, debe ejecutar el asistente mientras Docker se
ejecuta con contenedores de Windows configurados. Si quiere agregar compatibilidad con contenedores de Linux,
ejecute el asistente mientras Docker se ejecuta con contenedores de Linux configurados.

A N T E R IO R S IG U IE N T E
Migrar aplicaciones de .NET Framework monolíticas
heredadas a contenedores de Windows
03/10/2017 • 13 min to read • Edit Online

Los contenedores de Windows pueden usarse como una manera para mejorar los entornos de desarrollo y
pruebas y para implementar aplicaciones que se basan en tecnologías de .NET Framework heredadas, como
formularios Web Forms. El uso de contenedores para aplicaciones heredadas de esta manera se conoce como
“migración mediante lift-and-shift”.
Las secciones anteriores de esta guía han abogado por el uso de una arquitectura de microservicios en la que las
aplicaciones empresariales se distribuyen entre diferentes contenedores, cada uno de los cuales ejecuta un
pequeño servicio especializado. Este objetivo tiene numerosas ventajas. En el desarrollo nuevo, se recomienda
encarecidamente este enfoque. Las aplicaciones fundamentales para la empresa también se verán lo bastante
beneficiadas como para justificar el costo que supone el cambio de arquitectura y la reimplementación.
Pero no todas las aplicaciones se beneficiarán lo suficiente como para justificar dicho costo. Esto no significa que
esas aplicaciones no se puedan usar en escenarios de contenedor.
En esta sección, exploraremos una aplicación para eShopOnContainers, mostrada en la figura 7-1. Los usuarios de
esta aplicación serían los miembros del equipo empresarial de eShopOnContainers, que la utilizarían para ver y
editar el catálogo de productos.

Figura 7-1. Aplicación de formularios Web Forms ASP.NET (tecnología heredada) en un contenedor de Windows.
Se trata de una aplicación de formularios Web Forms que se usa para examinar y modificar las entradas del
catálogo. La dependencia de formularios Web Forms significa que esta aplicación no se ejecutará en .NET Core, a
menos que se reescriba sin formularios Web Forms y use en su lugar MVC de ASP.NET Core. Verá cómo puede
ejecutar aplicaciones como estas en contenedores sin ningún cambio. También verá cómo puede realizar cambios
mínimos para trabajar en un modo híbrido en el que alguna función se ha movido a un microservicio
independiente, pero la mayoría de las funciones permanece en la aplicación monolítica.

Ventajas de incluir en un contenedor una aplicación monolítica


La aplicación Catalog.WebForms está disponible en el repositorio de GitHub eShopOnContainers
(https://github.com/dotnet/eShopOnContainers). Se trata de una aplicación web independiente que tiene acceso a
un almacén de datos de alta disponibilidad. Aun así, resulta beneficioso ejecutar la aplicación en un contenedor.
Cree una imagen de la aplicación. A partir de ese momento, todas las implementaciones se ejecutarán en el mismo
entorno. Cada contenedor usa la misma versión de sistema operativo, tiene instalada la misma versión de
dependencias, usa el mismo marco de trabajo y se compila con el mismo proceso. En la figura 7-2 verá la
aplicación cargada en Visual Studio 2017.

Figura 7-2. Aplicación de formularios Web Forms de administración de catálogos en Visual Studio de 2017.
Además, todos los desarrolladores pueden ejecutar la aplicación en este entorno coherente. Los problemas que
solo se manifiestan con determinadas versiones aparecerán de inmediato para los desarrolladores, en lugar de
surgir en un entorno de ensayo o de producción. Las diferencias entre los entornos de desarrollo dejan de ser tan
importantes para el equipo de desarrollo una vez que las aplicaciones se ejecutan en contenedores.
Por último, las aplicaciones en contenedor tienen una curva de escalado horizontal más plana. Ya ha aprendido que
las aplicaciones en contenedor permiten la existencia de más contenedores en una máquina virtual o más
contenedores en una máquina física. Esto supone una mayor densidad y requiere menos recursos.
Por todas estas razones, considere la posibilidad de ejecutar aplicaciones monolíticas heredadas en un contenedor
de Docker mediante una operación de “migración mediante lift-and-shift”. La expresión “lift-and-shift” describe el
ámbito de la tarea: extrae (lift) toda la aplicación de una máquina física o virtual y la traslada (shift) a un
contenedor. En situaciones ideales, no es necesario realizar ningún cambio en el código de la aplicación para que
se ejecute en un contenedor.

Posibles procedimientos de migración


La aplicación monolítica Catalog.Webforms es una aplicación web que contiene todo el código, incluidas las
bibliotecas de acceso a datos. La base de datos se ejecuta en un equipo independiente de alta disponibilidad. Esta
configuración se simula en el código de ejemplo mediante el uso de un servicio de catálogo ficticio. Esto significa
que puede ejecutar la aplicación Catalog.WebForms con esos datos falsos para simular un escenario puro de
migración mediante lift-and-shift. Esto muestra el procedimiento de migración más sencillo, según el cual se
mueven los activos existentes para ejecutarlos en un contenedor sin realizar ningún cambio en el código. Este
procedimiento es adecuado para las aplicaciones que están completas y que tienen una interacción mínima con las
funciones que se van a mover a microservicios.
Pero el sitio web de eShopOnContainers ya tiene acceso al almacenamiento de datos mediante microservicios para
diferentes escenarios. Se pueden realizar algunos pequeños cambios adicionales en el editor del catálogo para
aprovechar el microservicio de catálogo, en lugar de tener acceso directamente al almacenamiento de datos del
catálogo.
Estos cambios muestran el continuo de sus propias aplicaciones. Puede hacer de todo, desde mover a
contenedores una aplicación existente sin cambiarla en absoluto, hasta realizar pequeños cambios que permiten
que las aplicaciones existentes tengan acceso a algunos de los nuevos microservicios, pasando por reescribir
completamente una aplicación para participar de lleno en una nueva arquitectura basada en microservicios. El
procedimiento que elija dependerá del costo y de las ventajas de la migración.

Paseo por la aplicación


Puede cargar la solución Catalog.WebForms y ejecutar la aplicación como una aplicación independiente. En esta
configuración, en lugar de una base de datos de almacenamiento persistente, la aplicación usa un servicio falso
para devolver los datos. La aplicación usa Autofac (https://autofac.org/) como contenedor de inversión de control
(IOC). Mediante la inserción de dependencias (DI), puede configurar la aplicación para que use los datos falsos o el
servicio de datos de catálogo activo. (Más adelante explicaremos con más detalle la inserción de dependencias). El
código de inicio lee un valor useFake en los archivos web.config y configura el contenedor Autofac para insertar el
servicio de datos falsos o el servicio de catálogo activo. Si ejecuta la aplicación con useFake establecido en false en
el archivo web.config, verá que la aplicación de formularios Web Forms muestra los datos del catálogo.
La mayoría de las técnicas usadas en esta aplicación le resultarán conocidas a cualquier persona que haya usado
formularios Web Forms. Aun así, el microservicio de catálogo introduce dos técnicas con las que probablemente
no esté familiarizado: la inserción de dependencias (DI) mencionada anteriormente y el trabajo con almacenes de
datos asincrónicos en formularios Web Forms.
DI invierte la estrategia típica orientada a objetos consistente en escribir clases que asignan todos los recursos
necesarios. En su lugar, las clases solicitan sus dependencias a un contenedor de servicios. La ventaja de DI es que
puede reemplazar a los servicios externos por emulaciones (objetos ficticios) para admitir entornos de pruebas o
de otro tipo.
El contenedor de DI usa la configuración appSettings de web.config para controlar si se van a usar los datos falsos
del catálogo o los datos activos del servicio en ejecución. La aplicación registra un objeto HttpModule que crea el
contenedor y registra un controlador de solicitud previa para insertar las dependencias. Puede ver ese código en el
archivo Modules/AutoFacHttpModule.cs, que es similar al ejemplo siguiente:
private static IContainer CreateContainer()
{
// Configure AutoFac:
// Register Containers:

var settings = WebConfigurationManager.AppSettings;


var useFake = settings["usefake"];
bool fake = useFake == "true";
var builder = new ContainerBuilder();

if (fake)
{
builder.RegisterType<CatalogMockService>()
.As<ICatalogService>();
}
else
{
builder.RegisterType<CatalogService>()
.As<ICatalogService>();
builder.RegisterType<RequestProvider>()
.As<IRequestProvider>();
}

var container = builder.Build();


return container;
}

private void InjectDependencies()


{
if (HttpContext.Current.CurrentHandler is Page page)
{
// Get the code-behind class that we may have written
var pageType = page.GetType().BaseType;

// Determine if there is a constructor to inject, and grab it


var ctor = (from c in pageType.GetConstructors()
where c.GetParameters().Length > 0
select c).FirstOrDefault();

if (ctor != null)
{
// Resolve the parameters for the constructor
var args = (from parm in ctor.GetParameters()
select Container.Resolve(parm.ParameterType))
.ToArray();

// Execute the constructor method with the arguments resolved


ctor.Invoke(page, args);
}

// Use the Autofac method to inject any


// properties that can be filled by Autofac
Container.InjectProperties(page);
}
}

Las páginas de la aplicación (Default.aspx.cs y EditPage.aspx.cs) definen constructores que toman estas
dependencias. Observe que el constructor predeterminado sigue estando presente y es accesible. La
infraestructura necesita el código siguiente.

protected _Default() { }

public _Default(ICatalogService catalog) => this.catalog = catalog;


Todas las API de catálogo son métodos asincrónicos. Los formularios Web Forms ahora las admiten para todos los
controles de datos. La aplicación Catalog.WebForms usa el enlace de modelos para las páginas de lista y edición;
los controles de las páginas definen las propiedades SelectMethod, UpdateMethod, InsertMethod y DeleteMethod
que especifican las operaciones asincrónicas de devolución de tarea. Los controles de los formularios Web Forms
entienden cuándo son asincrónicos los métodos enlazados a un control. La única restricción con la que se
encontrará al usar determinados métodos asincrónicos es que no se admite la paginación. La firma de paginación
requiere un parámetro out y los métodos asincrónicos no pueden tener parámetros out. Esta misma técnica se usa
en otras páginas que requieren datos del servicio de catálogo.
La configuración predeterminada de la aplicación de catálogo de formularios Web Forms usa una implementación
ficticia del servicio catalog.api. Dicha implementación ficticia usa un conjunto de datos codificados de forma rígida
para sus datos, lo que simplifica algunas tareas al quitar la dependencia del servicio catalog.api en entornos de
desarrollo.

Migración mediante lift-and-shift


Visual Studio proporciona una excelente compatibilidad para incluir una aplicación en un contenedor. Haga clic con
el botón derecho en el nodo del proyecto y seleccione Agregar y Compatibilidad con Docker. La plantilla de
proyecto de Docker agrega un nuevo proyecto a la solución denominado docker-compose. El proyecto contiene
los activos de Docker que componen (o compilan) las imágenes que necesita y empieza a ejecutar los
contenedores necesarios, tal como se muestra en la figura 7-3.
En los escenarios más simples de migración mediante lift-and-shift, la aplicación será el único servicio que usará
para la aplicación de formularios Web Forms. La plantilla también cambia el proyecto de inicio para que apunte al
proyecto docker-compose. Ahora, al presionar CTRL+F5 o F5, creará la imagen de Docker e iniciará el contenedor
de Docker.

Figura 7-3. El proyecto docker-compose en la solución de formularios Web Forms.


Antes de ejecutar la solución, debe asegurarse de que ha configurado Docker para usar contenedores de Windows.
Para ello, haga clic con el botón derecho en el icono de la barra de tareas de Docker en Windows y seleccione
Switch to Windows Containers (Cambiar a contenedores de Windows), como se muestra en la figura 7-4.
Figura 7-4. Cambiar a contenedores de Windows desde el icono de la barra de tareas de Docker en Windows.
Si el elemento de menú indica Switch to Linux containers (Cambiar a contenedores de Linux), ya está ejecutando
Docker con contenedores de Windows.
Al ejecutar la solución, se reinicia el host de Docker. Al compilar, la aplicación y la imagen de Docker se compilan
para el proyecto de formularios Web Forms. La primera vez que lo haga, tardará bastante. Esto se debe a que el
proceso de compilación extrae la imagen base de Windows Server y la imagen adicional para ASP.NET. Los ciclos
posteriores de compilación y ejecución serán mucho más rápidos.
Examinemos con detalle los archivos que ha agregado la plantilla de proyecto de Docker. Ha creado varios archivos
que Visual Studio usa para crear la imagen de Docker e iniciar un contenedor. Puede usar los mismos archivos
desde la CLI para ejecutar comandos de Docker manualmente.
En el siguiente ejemplo de Dockerfile se muestra la configuración básica para compilar una imagen de Docker
basada en la imagen de ASP.NET de Windows que ejecuta un sitio de ASP.NET.

FROM microsoft/aspnet

ARG source

WORKDIR /inetpub/wwwroot

COPY ${source:-obj/Docker/publish} .

Este archivo Dockerfile tendrá un aspecto muy similar a los creados para ejecutar una aplicación de ASP.NET Core
en contenedores de Linux. Aun así, hay algunas diferencias importantes. La más importante es que la imagen base
es microsoft/aspnet, que es la imagen actual de Windows Server que incluye .NET Framework. Otra diferencia es
que los directorios copiados del directorio de origen son diferentes.
Los demás archivos del proyecto docker-compose son los activos de Docker necesarios para compilar y
configurar los contenedores. Visual Studio coloca los diversos archivos docker-compose.yml en un nodo para
resaltar cómo se usan. El archivo base docker-compose contiene las directivas que son comunes a todas las
configuraciones. El archivo docker-compose.override.yml contiene variables de entorno y los reemplazos
relacionados para una configuración de desarrollador. Las variantes con .vs.debug y .vs.release proporcionan una
configuración de entorno que permite a Visual Studio adjuntar elementos al contenedor en ejecución y
administrarlo.
Aunque la integración de Visual Studio forma parte de la compatibilidad con la adición de Docker a la solución,
también puede compilar y ejecutar desde la línea de comandos mediante el comando docker-compose up, como
ha visto en secciones anteriores.

Obtener datos del microservicio de catálogo existente de .NET Core


Puede configurar la aplicación de formularios Web Forms para usar el microservicio de catálogo
eShopOnContainers para obtener datos en lugar de usar datos falsos. Para ello, edite el archivo web.config y
establezca el valor de la clave useFake en false. El contenedor de inserción de dependencias usará la clase que tiene
acceso al microservicio de catálogo activo en lugar de la clase que devuelve los datos codificados de forma rígida.
No se necesita ningún otro cambio de código.
Para obtener acceso al servicio de catálogo activo tiene que actualizar el proyecto docker-compose para compilar
la imagen del servicio de catálogo e iniciar el contenedor de servicio de catálogo. Docker CE para Windows es
compatible con contenedores de Linux y con contenedores de Windows, pero no al mismo tiempo. Para ejecutar el
microservicio de catálogo, debe compilar una imagen que ejecute el microservicio de catálogo sobre un
contenedor de Windows. Este enfoque requiere para el proyecto de microservicios un archivo Dockerfile diferente
del que ha visto en secciones anteriores. El archivo Dockerfile.windows contiene los valores de configuración
necesarios para compilar la imagen de contenedor de la API de catálogo de modo que se ejecute en un contenedor
de Windows, por ejemplo, para usar una imagen de Docker de Windows Nano.
El catálogo de microservicio se fundamenta en la base de datos de SQL Server. Por lo tanto, debe usar también una
imagen de Docker de SQL Server basada en Windows.
Después de estos cambios, el proyecto docker-compose lleva a cabo más acciones para iniciar la aplicación. El
proyecto inicia ahora SQL Server con la imagen de SQL Server basada en Windows, inicia el microservicio de
catálogo en un contenedor de Windows e inicia el contenedor del editor de catálogo de formularios Web Forms,
también en un contenedor de Windows. Si es necesario compilar alguna de las imágenes, se crean en primer lugar.

Entornos de desarrollo y producción


Hay un par de diferencias entre la configuración de desarrollo y la configuración de producción. En el entorno de
desarrollo, puede ejecutar la aplicación de formularios Web Forms, el microservicio de catálogo y SQL Server en
contenedores de Windows, como parte del mismo host de Docker. En las secciones anteriores, hemos mencionado
imágenes de SQL Server implementadas en el mismo host de Docker que los demás servicios basados en .NET
Core en un host de Docker basado en Linux. La ventaja de ejecutar los diversos microservicios en el mismo host de
Docker (o clúster) es que hay menos comunicación de red y la comunicación entre los contenedores tiene una
latencia inferior.
En el entorno de desarrollo, debe ejecutar todos los contenedores en el mismo sistema operativo. Docker CE para
Windows no admite la ejecución simultánea de contenedores basados en Windows y en Linux. En producción,
puede decidir si quiere ejecutar el microservicio de catálogo en un contenedor de Windows en un solo host de
Docker (o clúster), o bien si prefiere que la aplicación de formularios Web Forms se comunique con una instancia
del microservicio de catálogo que se ejecuta en un contenedor de Linux en un host de Docker diferente. Depende
de cómo quiera optimizar la latencia de red. En la mayoría de los casos, le interesará que los microservicios de los
que dependen sus aplicaciones se ejecuten en el mismo host de Docker (o conjunto) para facilitar la
implementación y para que la latencia de comunicación sea inferior. En estas configuraciones, la única
comunicación costosa es la que se establece entre las instancias de microservicios y los servidores de alta
disponibilidad para el almacenamiento de datos persistentes.

A N T E R IO R S IG U IE N T E
Diseñar y desarrollar aplicaciones .NET basadas en
varios contenedores y microservicios
03/10/2017 • 1 min to read • Edit Online

Si desarrolla aplicaciones de microservicios en contenedor significa que está compilando aplicaciones de varios
contenedores. Pero una aplicación de varios contenedores también podría ser más sencilla (por ejemplo, una
aplicación de tres niveles) y podría no compilarse con una arquitectura de microservicios.
Previamente planteamos la pregunta “¿Se necesita Docker para compilar una arquitectura de microservicios?”. La
respuesta es un no rotundo. Docker es un habilitador y puede proporcionar grandes ventajas, pero los
contenedores y Docker no son un requisito imprescindible para los microservicios. Por ejemplo, podría crear una
aplicación basada en microservicios con o sin Docker al usar Azure Service Fabric, que es compatible con los
microservicios que se ejecutan como procesos simples o como contenedores de Docker.
Pero si sabe cómo diseñar y desarrollar una aplicación basada en microservicios que también se base en
contenedores de Docker, podrá diseñar y desarrollar cualquier modelo de aplicación más sencillo. Por ejemplo,
podría diseñar una aplicación de tres niveles que también requiera un enfoque de varios contenedores. Debido a
eso, y dado que las arquitecturas de microservicios son una tendencia importante en el mundo de los
contenedores, esta sección se centra en la implementación de una arquitectura de microservicios con contenedores
de Docker.

A N T E R IO R S IG U IE N T E
Abordar la complejidad empresarial en un
microservicio con patrones DDD y CQRS
03/10/2017 • 2 min to read • Edit Online

Diseñe un modelo de dominio para cada microservicio o contexto limitado que refleje un conocimiento del ámbito
empresarial.
Esta sección se centra en microservicios más avanzados que se implementan cuando se deben abordar
subsistemas complejos y en microservicios derivados de los conocimientos de expertos en el dominio con reglas
de negocios cambiantes. Los patrones de arquitectura que se usan en esta sección se basan en enfoques de diseño
guiado por el dominio (DDD) y separación de la responsabilidad de comandos y consultas (CQRS), como se
muestra en la figura 9-1.

Figura 9-1. Arquitectura de microservicios externa frente a patrones de arquitectura interna para cada
microservicio.
Pero la mayoría de las técnicas para microservicios controlados por datos (por ejemplo, cómo implementar un
servicio ASP.NET Core Web API o cómo exponer metadatos de Swagger con Swashbuckle) también son aplicables a
los microservicios más avanzados que se implementan internamente con patrones DDD. Esta sección es una
ampliación de las secciones anteriores, ya que la mayoría de las prácticas explicadas anteriormente también se
aplican aquí o a cualquier tipo de microservicio.
Esta sección proporciona en primer lugar detalles sobre los patrones CQRS simplificados que se usan en la
aplicación de referencia eShopOnContainers. Más adelante, obtendrá información general sobre las técnicas DDD
que le permiten encontrar patrones comunes que puede volver a usar en sus aplicaciones.
DDD es un tema amplio con numerosos recursos para obtener más información. Puede empezar con libros como
Domain-Driven Design (Diseño guiado por el dominio), de Eric Evans, y materiales adicionales de Vaughn Vernon,
Jimmy Nilsson, Greg Young, Udi Dahan, Jimmy Bogard y muchos otros expertos en DDD y CQRS. Pero, sobre todo,
para aprender a aplicar técnicas DDD, debe recurrir a conversaciones, pizarras interactivas y sesiones de modelado
de dominio con expertos de su ámbito empresarial específico.
Recursos adicionales
D D D (d i se ñ o g u i a d o p o r e l d o m i n i o )

Eric Evans. Sitio web Domain Language http://domainlanguage.com/


Martin Fowler. Artículos con la etiqueta "domain-driven design" (diseño guiado por el dominio)
http://martinfowler.com/tags/domain%20driven%20design.html
Jimmy Bogard. Strengthening your domain: a primer (Manual sobre cómo fortalecer el dominio)
https://lostechies.com/jimmybogard/2010/02/04/strengthening-your-domain-a-primer/
L i b r o s so b r e D D D

Eric Evans. Domain-Driven Design: Tackling Complexity in the Heart of Software


https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/
Eric Evans. Domain-Driven Design Reference: Definitions and Pattern Summaries
https://www.amazon.com/Domain-Driven-Design-Reference-Definitions-2014-09-22/dp/B01N8YB4ZO/
Vaughn Vernon. Implementing Domain-Driven Design https://www.amazon.com/Implementing-
Domain-Driven-Design-Vaughn-Vernon/dp/0321834577/
Vaughn Vernon. Domain-Driven Design Distilled https://www.amazon.com/Domain-Driven-Design-
Distilled-Vaughn-Vernon/dp/0134434420/
Jimmy Nilsson. Applying Domain-Driven Design and Patterns https://www.amazon.com/Applying-
Domain-Driven-Design-Patterns-Examples/dp/0321268202/
Cesar de la Torre. N-Layered Domain-Oriented Architecture Guide with .NET
https://www.amazon.com/N-Layered-Domain-Oriented-Architecture-Guide-NET/dp/8493903612/
Abel Avram y Floyd Marinescu. Domain-Driven Design Quickly https://www.amazon.com/Domain-
Driven-Design-Quickly-Abel-Avram/dp/1411609255/
Aprendizaje de DDD
Julie Lerman y Steve Smith. Curso "Domain-Driven Design Fundamentals" (Conceptos fundamentales
sobre el diseño guiado por el dominio) http://bit.ly/PS-DDD

A N T E R IO R S IG U IE N T E
Implementar aplicaciones resistentes
03/10/2017 • 1 min to read • Edit Online

Sus aplicaciones basadas en microservicios y en la nube deben estar preparadas para los errores parciales que
seguramente se acabarán produciendo en algún momento. Debe diseñar su aplicación de modo que sea resistente
a estos errores parciales.
La resistencia es la capacidad de recuperarse de errores y seguir funcionando. No se trata de evitar los errores, sino
de aceptar el hecho de que se producirán errores y responder a ellos de forma que se evite el tiempo de inactividad
o la pérdida de datos. El objetivo de la resistencia consiste en que la aplicación vuelva a un estado totalmente
operativo después de un error.
Es todo un desafío diseñar e implementar una aplicación basada en microservicios. Pero también necesita
mantener la aplicación en ejecución en un entorno en el que con seguridad se producirá algún tipo de error. Por lo
tanto, la aplicación debe ser resistente. Debe estar diseñada para hacer frente a errores parciales, como las
interrupciones de red o el bloqueo de nodos o máquinas virtuales en la nube. Incluso los microservicios
(contenedores) que se mueven a otro nodo dentro de un clúster pueden causar breves errores intermitentes dentro
de la aplicación.
Los numerosos componentes individuales de la aplicación también deberían incorporar características de
seguimiento de estado. Mediante las directrices descritas en este capítulo, podrá crear una aplicación que funcione
sin problemas aunque se produzcan tiempos de inactividad transitorios o las interrupciones típicas de las
implementaciones complejas y basadas en la nube.

A N T E R IO R S IG U IE N T E
Proteger microservicios y aplicaciones web de .NET
03/10/2017 • 11 min to read • Edit Online

A menudo es necesario que los recursos y las API expuestas por un servicio se limiten a determinados usuarios o
clientes de confianza. El primer paso para tomar este tipo de decisiones de confianza en el nivel de API es la
autenticación. La autenticación es el proceso de determinar de forma fiable la identidad de un usuario.
En escenarios de microservicios, la autenticación suele controlarse de manera centralizada. Si usa una puerta de
enlace de API, dicha puerta es un buen lugar para realizar la autenticación, como se muestra en la figura 11-1. Si
emplea este método, asegúrese de que no es posible ponerse en contacto directamente con los microservicios
individuales (sin la puerta de enlace de API), a menos que haya aplicado seguridad adicional para autenticar si los
mensajes provienen de la puerta de enlace.

Figura 11-1. Autenticación centralizada con una puerta de enlace de API.


Si se puede tener acceso directamente a los servicios, entonces para la autenticación de los usuarios se puede usar
un servicio de autenticación como Azure Active Directory o un microservicio de autenticación dedicado que actúe
como un servicio de token de seguridad (STS). Las decisiones de confianza se comparten entre los servicios con
tokens de seguridad o cookies. (Si es necesario, estos se pueden compartir entre aplicaciones en ASP.NET Core con
servicios de protección de datos). Este patrón se ilustra en la figura 11-2.

Figura 11-2. Autenticación realizada por un microservicio de identidad; la confianza se comparte mediante un
token de autorización.

Autenticación mediante ASP.NET Core Identity


El principal mecanismo de ASP.NET Core para identificar a los usuarios de una aplicación es el sistema de
pertenencia ASP.NET Core Identity. ASP.NET Core Identity almacena la información del usuario (incluida la
información de inicio de sesión, los roles y las notificaciones) en un almacén de datos configurado por el
desarrollador. Normalmente, el almacén de datos de ASP.NET Core Identity es un almacén de Entity Framework
incluido en el paquete Microsoft.AspNetCore.Identity.EntityFrameworkCore. Aun así, se pueden usar almacenes
personalizados u otros paquetes de terceros para almacenar información de identidad en Table Storage de Azure,
DocumentDB u otras ubicaciones.
El código siguiente procede de la plantilla de proyecto de aplicación web de ASP.NET Core con la autenticación de
cuentas de usuario individuales seleccionada. Muestra cómo configurar ASP.NET Core Identity mediante
EntityFramework.Core en el método Startup.ConfigureServices.

services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

Una vez configurado ASP.NET Core Identity, debe habilitarlo. Para ello, llame a app.UseIdentity en el método
Startup.Configure del servicio.
El uso de ASP.NET Core Identity permite varios escenarios:
Crear información de usuario con el tipo UserManager (userManager.CreateAsync).
Autenticar a los usuarios con el tipo SignInManager. Puede usar signInManager.SignInAsync para iniciar
sesión directamente, o bien signInManager.PasswordSignInAsync para confirmar que la contraseña del
usuario es correcta y, después, iniciar sesión.
Identificar a un usuario en función de la información almacenada en una cookie (que se lee mediante el
software intermedio de ASP.NET Core Identity), de modo que las solicitudes posteriores desde un explorador
incluyan la identidad y las notificaciones del usuario que ha iniciado sesión.
ASP.NET Core Identity también es compatible con la autenticación en dos fases.
ASP.NET Core Identity es una solución recomendada para los escenarios de autenticación que usan un almacén de
datos de usuario local y que conservan la identidad entre las solicitudes mediante el uso de cookies (como es
habitual en las aplicaciones web MVC).

Autenticar mediante proveedores externos


ASP.NET Core también admite el uso de proveedores de autenticación externos para permitir que los usuarios
inicien sesión a través de flujos OAuth 2.0. Esto significa que los usuarios pueden iniciar sesión mediante los
procesos de autenticación existentes de proveedores como Microsoft, Google, Facebook o Twitter y asociar las
identidades con una identidad de ASP.NET Core en la aplicación.
Para usar la autenticación externa, incluya el software intermedio de autenticación adecuado en la canalización de
procesamiento de solicitudes HTTP de la aplicación. Este software intermedio es responsable de controlar las
solicitudes para devolver las rutas URI desde el proveedor de autenticación, capturar información de identidad y
hacer que esté disponible mediante el método SignInManager.GetExternalLoginInfo.
A continuación se muestran proveedores de autenticación externos populares y sus paquetes NuGet asociados.
Microsoft: Microsoft.AspNetCore.Authentication.MicrosoftAccount
Google: Microsoft.AspNetCore.Authentication.Google
Facebook: Microsoft.AspNetCore.Authentication.Facebook
Twitter: Microsoft.AspNetCore.Authentication.Twitter
En todos los casos, el software intermedio se registra con una llamada a un método de registro similar a
app.Use{ExternalProvider}Authentication en Startup.Configure. Estos métodos de registro toman un objeto de
opciones que contiene un identificador de aplicación e información secreta (una contraseña, por ejemplo), según
requiera el proveedor. Los proveedores de autenticación externos requieren que la aplicación se registre (como se
explica en la documentación de ASP.NET Core) para que puedan informar al usuario sobre qué aplicación solicita
acceso a su identidad.
Una vez que se haya registrado el software intermedio en Startup.Configure, podrá pedirles a los usuarios que
inicien sesión desde cualquier acción de controlador. Para ello, cree un objeto AuthenticationProperties que incluya
el nombre del proveedor de autenticación y una dirección URL de redireccionamiento. Después, devuelva una
respuesta Challenge que pase el objeto AuthenticationProperties. El código siguiente muestra un ejemplo de esto.

var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider,


redirectUrl);
return Challenge(properties, provider);

El parámetro redirectUrl incluye la dirección URL a la que el proveedor externo debe redirigir una vez que se ha
autenticado el usuario. La dirección URL debe representar una acción que iniciará la sesión del usuario en función
de información de identidad externa, como en el siguiente ejemplo simplificado:

// Sign in the user with this external login provider if the user
// already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent:
false);

if (result.Succeeded)
{
return RedirectToLocal(returnUrl);
}
else
{
ApplicationUser newUser = new ApplicationUser
{
// The user object can be constructed with claims from the
// external authentication provider, combined with information
// supplied by the user after they have authenticated with
// the external provider.
UserName = info.Principal.FindFirstValue(ClaimTypes.Name),
Email = info.Principal.FindFirstValue(ClaimTypes.Email)
};
var identityResult = await _userManager.CreateAsync(newUser);
if (identityResult.Succeeded)
{
identityResult = await _userManager.AddLoginAsync(newUser, info);
if (identityResult.Succeeded)
{
await _signInManager.SignInAsync(newUser, isPersistent: false);
}
return RedirectToLocal(returnUrl);
}
}

Si elige la opción de autenticación Individual User Account (Cuenta de usuario individual) al crear el proyecto de
aplicación web de ASP.NET Core en Visual Studio, todo el código necesario para iniciar sesión con un proveedor
externo ya está en el proyecto, como se muestra en la figura 11-3.
Figura 11-3. Proceso de selección de una opción para usar la autenticación externa al crear un proyecto de
aplicación web.
Además de los proveedores de autenticación externa mencionados anteriormente, hay disponibles paquetes de
terceros que proporcionan software intermedio para el uso de muchos otros proveedores de autenticación
externos. Para obtener una lista, vea el repositorio AspNet.Security.OAuth.Providers en GitHub.
Por supuesto, también puede crear su propio software intermedio de autenticación externo.

Autenticar mediante tokens de portador


La autenticación con ASP.NET Core Identity (o con Identity y proveedores de autenticación externos) funciona bien
en muchos escenarios de aplicación web en los que es adecuado almacenar información de usuario en una cookie.
En cambio, en otros escenarios las cookies no son una manera natural de conservar y transmitir datos.
Por ejemplo, en una Web API de ASP.NET Core que expone puntos de conexión RESTful a los que podrían tener
acceso aplicaciones de una sola página (SPA), clientes nativos o incluso otras Web API, normalmente le interesa
usar la autenticación mediante token de portador. Estos tipos de aplicaciones no funcionan con cookies, pero
pueden recuperar fácilmente un token de portador e incluirlo en el encabezado de autorización de las solicitudes
posteriores. Con objeto de habilitar la autenticación mediante token, ASP.NET Core admite varias opciones para el
uso de OAuth 2.0 y OpenID Connect.

Autenticar con un proveedor de identidad OpenID Connect u OAuth


2.0
Si la información de usuario se almacena en Azure Active Directory u otra solución de identidad compatible con
OpenID Connect u OAuth 2.0, puede usar el paquete Microsoft.AspNetCore.Authentication.OpenIdConnect para
autenticarse con el flujo de trabajo de OpenID Connect. Por ejemplo, para autenticarse con Azure Active Directory,
una aplicación web de ASP.NET Core puede usar el software intermedio de ese paquete tal como se muestra en el
ejemplo siguiente:

// Configure the OWIN pipeline to use OpenID Connect auth


app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
ClientId = Configuration["AzureAD:ClientId"],
Authority = String.Format(Configuration["AzureAd:AadInstance"],
Configuration["AzureAd:Tenant"]),
ResponseType = OpenIdConnectResponseType.IdToken,
PostLogoutRedirectUri = Configuration["AzureAd:PostLogoutRedirectUri"]
});

Los valores de configuración son los valores de Azure Active Directory que se crean cuando la aplicación se registra
como cliente de Azure AD. Es posible compartir un identificador de cliente único entre varios microservicios de una
aplicación si todos necesitan autenticar a usuarios autenticados mediante Azure Active Directory.
Tenga en cuenta que, cuando se usa este flujo de trabajo, el software intermedio de ASP.NET Core Identity no es
necesario, porque Azure Active Directory controla el almacenamiento y la autenticación de la información del
usuario.

Emitir tokens de seguridad desde un servicio de ASP.NET Core


Si prefiere emitir tokens de seguridad para los usuarios locales de ASP.NET Core Identity en lugar de usar un
proveedor de identidades externo, puede aprovechar algunas buenas bibliotecas de terceros.
IdentityServer4 y OpenIddict son proveedores de OpenID Connect que se integran fácilmente con ASP.NET Core
Identity y le permiten emitir tokens de seguridad desde un servicio de ASP.NET Core. En la documentación de
IdentityServer4 encontrará instrucciones detalladas para usar la biblioteca, pero los pasos básicos para emitir
tokens con IdentityServer4 son los que se indican a continuación.
1. Llame a app.UseIdentityServer en el método Startup.Configure para agregar IdentityServer4 a la
canalización de procesamiento de solicitudes HTTP de la aplicación. Esto permite a la biblioteca atender las
solicitudes a los puntos de conexión de OpenID Connect y OAuth2 como /connect/token.
2. Configure IdentityServer4 en Startup.ConfigureServices mediante una llamada a services.AddIdentityServer.
3. Para configurar el servidor de identidades, proporcione los datos siguientes:
Las credenciales que se van a usar para la firma.
Los recursos de identidad y de API a los que los usuarios podrían solicitar acceso:
Los recursos de API representan funciones o datos protegidos a los que los usuarios pueden tener acceso
con un token de acceso. Un ejemplo de un recurso de API sería una API web (o un conjunto de API) que
requiere autorización.
Los recursos de identidad representan información (notificaciones) que se entregan a un cliente para
identificar a un usuario. Las notificaciones pueden incluir el nombre de usuario, la dirección de correo
electrónico, etc.
Los clientes que se conectarán para solicitar tokens.
El mecanismo de almacenamiento de la información de usuario, como ASP.NET Core Identity u otra
alternativa.
Al especificar los clientes y los recursos que usará IdentityServer4, puede pasar una colección IEnumerable<T> del
tipo adecuado a los métodos que toman almacenes de recursos o cliente en memoria. En escenarios más
complejos, puede proporcionar tipos de proveedor de recursos o cliente mediante la inserción de dependencias.
En el ejemplo siguiente se muestra el aspecto que podría tener una configuración para que IdentityServer4 use
clientes y recursos en memoria proporcionados por un tipo IClientStore personalizado:

// Add IdentityServer services


services.AddSingleton<IClientStore, CustomClientStore>();
services.AddIdentityServer()
.AddSigningCredential("CN=sts")
.AddInMemoryApiResources(MyApiResourceProvider.GetAllResources())
.AddAspNetIdentity<ApplicationUser>();

Consumir tokens de seguridad


La autenticación con un punto de conexión de OpenID Connect o mediante la emisión de tokens de seguridad
propios se aplica a diversos escenarios. Pero ¿qué sucede si un servicio solo necesita limitar el acceso a los usuarios
que tienen tokens de seguridad válidos proporcionados por otro servicio?
Para este escenario, en el paquete Microsoft.AspNetCore.Authentication.JwtBearer está disponible el software
intermedio de autenticación que controla los tokens JWT. JWT es el acrónimo de "JSON Web Token" y es un
formato común de token de seguridad (definido en RFC 7519) para la comunicación de notificaciones de
seguridad. Un ejemplo sencillo de cómo emplear el software intermedio para usar esos tokens tendría un aspecto
similar al siguiente. Este código debe preceder a las llamadas al software intermedio MVC de ASP.NET Core
(app.UseMvc).

app.UseJwtBearerAuthentication(new JwtBearerOptions()
{
Audience = "http://localhost:5001/",
Authority = "http://localhost:5000/",
AutomaticAuthenticate = true
});

Los parámetros de este uso son los siguientes:


Audience representa el receptor del token entrante o el recurso al que el token concede acceso. Si el valor
especificado en este parámetro no coincide con el parámetro aud del token, se rechazará el token.
Authority es la dirección del servidor de autenticación de emisión de tokens. El software intermedio de
autenticación del portador de JWT usa este URI para obtener la clave pública que puede usarse para validar
la firma del token. El software intermedio también confirma que el parámetro iss del token coincide con este
URI.
AutomaticAuthenticate es un valor booleano que indica si la sesión del usuario definido por el token debe
iniciarse automáticamente.
En este ejemplo no se usa el parámetro RequireHttpsMetadata. Resulta útil para la realización de pruebas;
establézcalo en false para efectuar pruebas en los entornos en los que no tiene certificados. En implementaciones
reales, los tokens de portador de JWT siempre se deben pasar a través de HTTPS exclusivamente.
Con este software intermedio, los tokens JWT se extraen automáticamente de los encabezados de autorización.
Después, se deserializan, se validan (mediante los valores de los parámetros Audience y Authority) y se almacenan
como información del usuario a la que se hará referencia más adelante a través de acciones de MVC o filtros de
autorización.
El software intermedio de autenticación del portador de JWT también puede admitir escenarios más avanzados,
como el uso de un certificado local para validar un token si la entidad no está disponible. En este escenario, puede
especificar un objeto TokenValidationParameters en el objeto JwtBearerOptions.
Recursos adicionales
Sharing cookies between applications (Compartir cookies entre aplicaciones)
https://docs.microsoft.com/aspnet/core/security/data-protection/compatibility/cookie-sharing#sharing-
authentication-cookies-between-applications
Introduction to Identity (Introducción a la identidad)
https://docs.microsoft.com/aspnet/core/security/authentication/identity
Rick Anderson. Two-factor authentication with SMS (Autenticación en dos fases con SMS)
https://docs.microsoft.com/aspnet/core/security/authentication/2fa
Enabling authentication using Facebook, Google and other external providers (Habilitar la
autenticación con Facebook, Google y otros proveedores externos)
https://docs.microsoft.com/aspnet/core/security/authentication/social/
Michell Anicas. An Introduction to OAuth 2 (Introducción a OAuth 2)
https://www.digitalocean.com/community/tutorials/an-introduction-to-oauth-2
AspNet.Security.OAuth.Providers (repositorio de GitHub para proveedores de OAuth de ASP.NET).
https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers/tree/dev/src
Danny Strockis. Integrating Azure AD into an ASP.NET Core web app (Integración de Azure AD en una
aplicación web de ASP.NET Core) https://azure.microsoft.com/resources/samples/active-directory-dotnet-
webapp-openidconnect-aspnetcore/
IdentityServer4. Documentación oficial https://identityserver4.readthedocs.io/en/release/

A N T E R IO R S IG U IE N T E

Você também pode gostar