NET Microservices Architecture for Containerized .NET Applications PDF v7.0

Document Details

UnforgettableOakland

Uploaded by UnforgettableOakland

2023

Cesar de la Torre, Bill Wagner, Mike Rousos, Mike Pope, Steve Hoag, Jeffrey Richter, Jimmy Bogard, Udi Dahan, Jimmy Nilsson, Glenn Condron, Mark Fussell, Diego Vega, Barry Dorrans, Rowan Miller, Ankit

Tags

.NET programming microservices architecture containerization with Docker application development

Summary

This guide provides an introduction to developing microservices-based applications using containers, specifically focusing on .NET and Docker. It covers architectural design and implementation approaches, with a reference application (eShopOnContainers) for easier understanding. The guide emphasizes the development environment and is infrastructure-agnostic. It discusses choosing between .NET and .NET Framework for Docker containers, and provides details on the Docker technology.

Full Transcript

EDITION v7.0 - Updated to ASP.NET Core 7.0 Refer changelog for the book updates and community contributions. This guide is an introduction to developing microservices-based applications and managing them using containers. It discusses architectural design and implementation approaches using.NET a...

EDITION v7.0 - Updated to ASP.NET Core 7.0 Refer changelog for the book updates and community contributions. This guide is an introduction to developing microservices-based applications and managing them using containers. It discusses architectural design and implementation approaches using.NET and Docker containers. To make it easier to get started, the guide focuses on a reference containerized and microservice- based application that you can explore. The reference application is available at the eShopOnContainers GitHub repo. Action links This e-book is also available in a PDF format (English version only) Download Clone/Fork the reference application eShopOnContainers on GitHub Watch the introductory video Get to know the Microservices Architecture right away Introduction Enterprises are increasingly realizing cost savings, solving deployment problems, and improving DevOps and production operations by using containers. Microsoft has been releasing container innovations for Windows and Linux by creating products like Azure Kubernetes Service and Azure Service Fabric, and by partnering with industry leaders like Docker, Mesosphere, and Kubernetes. These products deliver container solutions that help companies build and deploy applications at cloud speed and scale, whatever their choice of platform or tools. Docker is becoming the de facto standard in the container industry, supported by the most significant vendors in the Windows and Linux ecosystems. (Microsoft is one of the main cloud vendors supporting Docker). In the future, Docker will probably be ubiquitous in any datacenter in the cloud or on-premises. In addition, the microservices architecture is emerging as an important approach for distributed mission-critical applications. In a microservice-based architecture, the application is built on a collection of services that can be developed, tested, deployed, and versioned independently. About this guide This guide is an introduction to developing microservices-based applications and managing them using containers. It discusses architectural design and implementation approaches using.NET and Docker containers. To make it easier to get started with containers and microservices, the guide focuses on a reference containerized and microservice-based application that you can explore. The sample application is available at the eShopOnContainers GitHub repo. This guide provides foundational development and architectural guidance primarily at a development environment level with a focus on two technologies: Docker and.NET. Our intention is that you read this guide when thinking about your application design without focusing on the infrastructure (cloud or on-premises) of your production environment. You will make decisions about your infrastructure later, when you create your production-ready applications. Therefore, this guide is intended to be infrastructure agnostic and more development-environment-centric. After you have studied this guide, your next step would be to learn about production-ready microservices on Microsoft Azure. Version This guide has been revised to cover.NET 7 version along with many additional updates related to the same “wave” of technologies (that is, Azure and additional third-party technologies) coinciding in time with the.NET 7 release. That’s why the book version has also been updated to version 7.0. What this guide does not cover This guide does not focus on the application lifecycle, DevOps, CI/CD pipelines, or team work. The complementary guide Containerized Docker Application Lifecycle with Microsoft Platform and Tools focuses on that subject. The current guide also does not provide implementation details on Azure infrastructure, such as information on specific orchestrators. Additional resources Containerized Docker Application Lifecycle with Microsoft Platform and Tools (downloadable e-book) https://aka.ms/dockerlifecycleebook Who should use this guide We wrote this guide for developers and solution architects who are new to Docker-based application development and to microservices-based architecture. This guide is for you if you want to learn how to architect, design, and implement proof-of-concept applications with Microsoft development technologies (with special focus on.NET) and with Docker containers. You will also find this guide useful if you are a technical decision maker, such as an enterprise architect, who wants an architecture and technology overview before you decide on what approach to select for new and modern distributed applications. How to use this guide The first part of this guide introduces Docker containers, discusses how to choose between.NET 7 and the.NET Framework as a development framework, and provides an overview of microservices. This content is for architects and technical decision makers who want an overview but don’t need to focus on code implementation details. The second part of the guide starts with the Development process for Docker based applications section. It focuses on the development and microservice patterns for implementing applications using.NET and Docker. This section will be of most interest to developers and architects who want to focus on code and on patterns and implementation details. Related microservice and container-based reference application: eShopOnContainers The eShopOnContainers application is an open-source reference app for.NET and microservices that is designed to be deployed using Docker containers. The application consists of multiple subsystems, including several e-store UI front-ends (a Web MVC app, a Web SPA, and a native mobile app). It also includes the back-end microservices and containers for all required server-side operations. The purpose of the application is to showcase architectural patterns. IT IS NOT A PRODUCTION- READY TEMPLATE to start real-world applications. In fact, the application is in a permanent beta state, as it’s also used to test new potentially interesting technologies as they show up. Credits Co-Authors: Cesar de la Torre, Sr. PM,.NET product team, Microsoft Corp. Bill Wagner, Sr. Content Developer, C+E, Microsoft Corp. Mike Rousos, Principal Software Engineer, DevDiv CAT team, Microsoft Editors: Mike Pope Steve Hoag Participants and reviewers: Jeffrey Richter, Partner Software Eng, Azure team, Microsoft Jimmy Bogard, Chief Architect at Headspring Udi Dahan, Founder & CEO, Particular Software Jimmy Nilsson, Co-founder and CEO of Factor10 Glenn Condron, Sr. Program Manager, ASP.NET team Mark Fussell, Principal PM Lead, Azure Service Fabric team, Microsoft Diego Vega, PM Lead, Entity Framework team, Microsoft Barry Dorrans, Sr. Security Program Manager Rowan Miller, Sr. Program Manager, Microsoft Ankit Asthana, Principal PM Manager,.NET team, Microsoft Scott Hunter, Partner Director PM,.NET team, Microsoft Nish Anil, Sr. Program Manager,.NET team, Microsoft Dylan Reisenberger, Architect and Dev Lead at Polly Steve “ardalis” Smith - Software Architect and Trainer - Ardalis.com Ian Cooper, Coding Architect at Brighter Unai Zorrilla, Architect and Dev Lead at Plain Concepts Eduard Tomas, Dev Lead at Plain Concepts Ramon Tomas, Developer at Plain Concepts David Sanz, Developer at Plain Concepts Javier Valero, Chief Operating Officer at Grupo Solutio Pierre Millet, Sr. Consultant, Microsoft Michael Friis, Product Manager, Docker Inc Charles Lowell, Software Engineer, VS CAT team, Microsoft Miguel Veloso, Software Development Engineer at Plain Concepts Sumit Ghosh, Principal Consultant at Neudesic Copyright PUBLISHED BY Microsoft Developer Division,.NET and Visual Studio product teams A division of Microsoft Corporation One Microsoft Way Redmond, Washington 98052-6399 Copyright © 2023 by Microsoft Corporation All rights reserved. No part of the contents of this book may be reproduced or transmitted in any form or by any means without the written permission of the publisher. This book is provided “as-is” and expresses the author’s views and opinions. The views, opinions and information expressed in this book, including URL and other Internet website references, may change without notice. Some examples depicted herein are provided for illustration only and are fictitious. No real association or connection is intended or should be inferred. Microsoft and the trademarks listed at https://www.microsoft.com on the “Trademarks” webpage are trademarks of the Microsoft group of companies. Mac and macOS are trademarks of Apple Inc. The Docker whale logo is a registered trademark of Docker, Inc. Used by permission. All other marks and logos are property of their respective owners. Contents Introduction to Containers and Docker................................................................................ 1 What is Docker?........................................................................................................................................................................ 2 Comparing Docker containers with virtual machines........................................................................................... 3 A simple analogy................................................................................................................................................................. 4 Docker terminology................................................................................................................................................................ 5 Docker containers, images, and registries..................................................................................................................... 7 Choosing Between.NET and.NET Framework for Docker Containers.............................. 9 General guidance..................................................................................................................................................................... 9 When to choose.NET for Docker containers............................................................................................................. 10 Developing and deploying cross platform............................................................................................................ 10 Using containers for new (“green-field”) projects............................................................................................... 11 Create and deploy microservices on containers.................................................................................................. 11 Deploying high density in scalable systems.......................................................................................................... 11 When to choose.NET Framework for Docker containers..................................................................................... 12 Migrating existing applications directly to a Windows Server container.................................................. 12 Using third-party.NET libraries or NuGet packages not available for.NET 7......................................... 12 Using.NET technologies not available for.NET 7............................................................................................... 12 Using a platform or API that doesn’t support.NET 7........................................................................................ 13 Porting existing ASP.NET application to.NET 7................................................................................................... 13 Decision table:.NET implementations to use for Docker..................................................................................... 13 What OS to target with.NET containers...................................................................................................................... 14 Official.NET Docker images............................................................................................................................................. 16.NET and Docker image optimizations for development versus production........................................... 16 Architecting container and microservice-based applications.......................................... 18 Container design principles.............................................................................................................................................. 18 Containerizing monolithic applications....................................................................................................................... 19 Deploying a monolithic application as a container............................................................................................ 21 Publishing a single-container-based application to Azure App Service.................................................... 21 i Contents Manage state and data in Docker applications........................................................................................................ 22 Service-oriented architecture........................................................................................................................................... 25 Microservices architecture................................................................................................................................................. 25 Additional resources....................................................................................................................................................... 27 Data sovereignty per microservice................................................................................................................................ 27 The relationship between microservices and the Bounded Context pattern........................................... 29 Logical architecture versus physical architecture..................................................................................................... 30 Challenges and solutions for distributed data management.............................................................................. 31 Challenge #1: How to define the boundaries of each microservice............................................................ 31 Challenge #2: How to create queries that retrieve data from several microservices............................ 32 Challenge #3: How to achieve consistency across multiple microservices............................................... 33 Challenge #4: How to design communication across microservice boundaries.................................... 35 Additional resources....................................................................................................................................................... 36 Identify domain-model boundaries for each microservice.................................................................................. 36 The API gateway pattern versus the Direct client-to-microservice communication.................................. 40 Direct client-to-microservice communication...................................................................................................... 40 Why consider API Gateways instead of direct client-to-microservice communication....................... 41 What is the API Gateway pattern?............................................................................................................................. 42 Main features in the API Gateway pattern............................................................................................................. 44 Using products with API Gateway features............................................................................................................ 45 Drawbacks of the API Gateway pattern................................................................................................................... 47 Additional resources....................................................................................................................................................... 48 Communication in a microservice architecture........................................................................................................ 48 Communication types.................................................................................................................................................... 49 Asynchronous microservice integration enforces microservice’s autonomy........................................... 50 Communication styles.................................................................................................................................................... 52 Asynchronous message-based communication....................................................................................................... 54 Single-receiver message-based communication................................................................................................ 55 Multiple-receivers message-based communication.......................................................................................... 56 Asynchronous event-driven communication........................................................................................................ 56 A note about messaging technologies for production systems................................................................... 57 Resiliently publishing to the event bus................................................................................................................... 58 ii Contents Additional resources....................................................................................................................................................... 58 Creating, evolving, and versioning microservice APIs and contracts............................................................... 59 Additional resources....................................................................................................................................................... 59 Microservices addressability and the service registry............................................................................................ 60 Additional resources....................................................................................................................................................... 60 Creating composite UI based on microservices....................................................................................................... 60 Additional resources....................................................................................................................................................... 62 Resiliency and high availability in microservices...................................................................................................... 63 Health management and diagnostics in microservices.................................................................................... 63 Additional resources....................................................................................................................................................... 65 Orchestrate microservices and multi-container applications for high scalability and availability....... 66 Software platforms for container clustering, orchestration, and scheduling........................................... 68 Using container-based orchestrators in Microsoft Azure................................................................................ 68 Using Azure Kubernetes Service................................................................................................................................ 69 Development environment for Kubernetes........................................................................................................... 70 Getting started with Azure Kubernetes Service (AKS)....................................................................................... 70 Deploy with Helm charts into Kubernetes clusters............................................................................................. 71 Additional resources....................................................................................................................................................... 71 Development process for Docker-based applications....................................................... 72 Development environment for Docker apps............................................................................................................. 72 Development tool choices: IDE or editor................................................................................................................ 72 Additional resources....................................................................................................................................................... 73.NET languages and frameworks for Docker containers....................................................................................... 73 Development workflow for Docker apps..................................................................................................................... 73 Workflow for developing Docker container-based applications.................................................................. 73 Step 1. Start coding and create your initial application or service baseline............................................. 75 Step 2. Create a Dockerfile related to an existing.NET base image............................................................ 76 Step 3. Create your custom Docker images and embed your application or service in them.......... 83 Step 4. Define your services in docker-compose.yml when building a multi-container Docker application.......................................................................................................................................................................... 84 Step 5. Build and run your Docker application.................................................................................................... 87 Step 6. Test your Docker application using your local Docker host............................................................ 89 iii Contents Simplified workflow when developing containers with Visual Studio........................................................ 90 Using PowerShell commands in a Dockerfile to set up Windows Containers......................................... 91 Designing and Developing Multi-Container and Microservice-Based.NET Applications................................................................................................................................................. 93 Design a microservice-oriented application.............................................................................................................. 93 Application specifications............................................................................................................................................. 93 Development team context......................................................................................................................................... 94 Choosing an architecture.............................................................................................................................................. 94 Benefits of a microservice-based solution............................................................................................................. 97 Downsides of a microservice-based solution....................................................................................................... 98 External versus internal architecture and design patterns............................................................................... 99 The new world: multiple architectural patterns and polyglot microservices.......................................... 100 Creating a simple data-driven CRUD microservice............................................................................................... 102 Designing a simple CRUD microservice................................................................................................................ 102 Implementing a simple CRUD microservice with ASP.NET Core................................................................. 103 The DB connection string and environment variables used by Docker containers............................. 109 Generating Swagger description metadata from your ASP.NET Core Web API................................... 111 Defining your multi-container application with docker-compose.yml......................................................... 116 Use a database server running as a container........................................................................................................ 127 SQL Server running as a container with a microservice-related database.............................................. 128 Seeding with test data on Web application startup......................................................................................... 129 EF Core InMemory database versus SQL Server running as a container................................................. 132 Using a Redis cache service running in a container......................................................................................... 132 Implementing event-based communication between microservices (integration events)................... 133 Using message brokers and service buses for production systems.......................................................... 134 Integration events.......................................................................................................................................................... 135 The event bus.................................................................................................................................................................. 136 Additional resources..................................................................................................................................................... 138 Implementing an event bus with RabbitMQ for the development or test environment....................... 138 Implementing a simple publish method with RabbitMQ............................................................................... 139 Implementing the subscription code with the RabbitMQ API..................................................................... 140 Additional resources..................................................................................................................................................... 141 iv Contents Subscribing to events........................................................................................................................................................ 141 Publishing events through the event bus............................................................................................................. 142 Idempotency in update message events.............................................................................................................. 149 Deduplicating integration event messages......................................................................................................... 150 Testing ASP.NET Core services and web apps........................................................................................................ 152 Testing in eShopOnContainers................................................................................................................................. 155 Implement background tasks in microservices with IHostedService and the BackgroundService class.................................................................................................................................................................................................... 157 Registering hosted services in your WebHost or Host................................................................................... 159 The IHostedService interface..................................................................................................................................... 159 Implementing IHostedService with a custom hosted service class deriving from the BackgroundService base class................................................................................................................................... 160 Additional resources..................................................................................................................................................... 163 Implement API Gateways with Ocelot........................................................................................................................ 163 Architect and design your API Gateways.............................................................................................................. 163 Implementing your API Gateways with Ocelot.................................................................................................. 168 Using Kubernetes Ingress plus Ocelot API Gateways...................................................................................... 180 Additional cross-cutting features in an Ocelot API Gateway....................................................................... 181 Tackle Business Complexity in a Microservice with DDD and CQRS Patterns.............. 182 Apply simplified CQRS and DDD patterns in a microservice............................................................................. 184 Additional resources..................................................................................................................................................... 186 Apply CQRS and CQS approaches in a DDD microservice in eShopOnContainers................................. 186 CQRS and DDD patterns are not top-level architectures............................................................................... 187 Implement reads/queries in a CQRS microservice................................................................................................ 188 Use ViewModels specifically made for client apps, independent from domain model constraints............................................................................................................................................................................................... 189 Use Dapper as a micro ORM to perform queries.............................................................................................. 189 Dynamic versus static ViewModels......................................................................................................................... 190 Additional resources..................................................................................................................................................... 193 Design a DDD-oriented microservice......................................................................................................................... 194 Keep the microservice context boundaries relatively small.......................................................................... 194 Layers in DDD microservices..................................................................................................................................... 195 v Contents Design a microservice domain model........................................................................................................................ 199 The Domain Entity pattern......................................................................................................................................... 199 Implement a microservice domain model with.NET............................................................................................ 204 Domain model structure in a custom.NET Standard Library....................................................................... 204 Structure aggregates in a custom.NET Standard library............................................................................... 205 Implement domain entities as POCO classes..................................................................................................... 206 Encapsulate data in the Domain Entities.............................................................................................................. 207 Seedwork (reusable base classes and interfaces for your domain model).................................................. 210 The custom Entity base class..................................................................................................................................... 211 Repository contracts (interfaces) in the domain model layer...................................................................... 212 Additional resources..................................................................................................................................................... 213 Implement value objects.................................................................................................................................................. 213 Important characteristics of value objects........................................................................................................... 214 Value object implementation in C#........................................................................................................................ 215 How to persist value objects in the database with EF Core 2.0 and later................................................ 217 Persist value objects as owned entity types in EF Core 2.0 and later........................................................ 218 Additional resources..................................................................................................................................................... 221 Use enumeration classes instead of enum types................................................................................................... 221 Implement an Enumeration base class.................................................................................................................. 222 Additional resources..................................................................................................................................................... 223 Design validations in the domain model layer....................................................................................................... 223 Implement validations in the domain model layer........................................................................................... 224 Additional resources..................................................................................................................................................... 225 Client-side validation (validation in the presentation layers)............................................................................ 226 Additional resources..................................................................................................................................................... 227 Domain events: Design and implementation.......................................................................................................... 227 What is a domain event?............................................................................................................................................. 228 Domain events versus integration events............................................................................................................ 228 Domain events as a preferred way to trigger side effects across multiple aggregates within the same domain................................................................................................................................................................... 229 Implement domain events.......................................................................................................................................... 231 Conclusions on domain events................................................................................................................................. 237 vi Contents Additional resources..................................................................................................................................................... 238 Design the infrastructure persistence layer.............................................................................................................. 238 The Repository pattern................................................................................................................................................ 238 Additional resources..................................................................................................................................................... 243 Implement the infrastructure persistence layer with Entity Framework Core............................................ 243 Introduction to Entity Framework Core................................................................................................................. 244 Infrastructure in Entity Framework Core from a DDD perspective............................................................. 244 Implement custom repositories with Entity Framework Core...................................................................... 246 EF DbContext and IUnitOfWork instance lifetime in your IoC container................................................. 248 The repository instance lifetime in your IoC container................................................................................... 249 Table mapping................................................................................................................................................................ 250 Implement the Query Specification pattern........................................................................................................ 253 Use NoSQL databases as a persistence infrastructure......................................................................................... 255 Introduction to Azure Cosmos DB and the native Cosmos DB API........................................................... 256 Implement.NET code targeting MongoDB and Azure Cosmos DB.......................................................... 258 Design the microservice application layer and Web API.................................................................................... 266 Use SOLID principles and Dependency Injection.............................................................................................. 266 Implement the microservice application layer using the Web API................................................................. 267 Use Dependency Injection to inject infrastructure objects into your application layer..................... 267 Implement the Command and Command Handler patterns....................................................................... 271 The Command process pipeline: how to trigger a command handler..................................................... 278 Implement the command process pipeline with a mediator pattern (MediatR).................................. 281 Apply cross-cutting concerns when processing commands with the Behaviors in MediatR.......... 287 Implement resilient applications....................................................................................... 291 Handle partial failure......................................................................................................................................................... 292 Strategies to handle partial failure............................................................................................................................... 294 Additional resources..................................................................................................................................................... 295 Implement retries with exponential backoff............................................................................................................ 295 Implement resilient Entity Framework Core SQL connections.......................................................................... 295 Execution strategies and explicit transactions using BeginTransaction and multiple DbContexts296 Additional resources..................................................................................................................................................... 298 Use IHttpClientFactory to implement resilient HTTP requests......................................................................... 298 vii Contents Issues with the original HttpClient class available in.NET............................................................................. 298 Benefits of using IHttpClientFactory....................................................................................................................... 299 Multiple ways to use IHttpClientFactory............................................................................................................... 300 How to use Typed Clients with IHttpClientFactory........................................................................................... 300 Additional resources..................................................................................................................................................... 304 Implement HTTP call retries with exponential backoff with IHttpClientFactory and Polly policies... 304 Add a jitter strategy to the retry policy................................................................................................................. 305 Additional resources..................................................................................................................................................... 306 Implement the Circuit Breaker pattern....................................................................................................................... 306 Implement Circuit Breaker pattern with IHttpClientFactory and Polly..................................................... 307 Test Http retries and circuit breakers in eShopOnContainers...................................................................... 308 Additional resources..................................................................................................................................................... 310 Health monitoring.............................................................................................................................................................. 310 Implement health checks in ASP.NET Core services........................................................................................ 311 Use watchdogs................................................................................................................................................................ 315 Health checks when using orchestrators.............................................................................................................. 317 Advanced monitoring: visualization, analysis, and alerts............................................................................... 317 Additional resources..................................................................................................................................................... 318 Make secure.NET Microservices and Web Applications................................................. 319 Implement authentication in.NET microservices and web applications...................................................... 319 Authenticate with ASP.NET Core Identity............................................................................................................. 320 Authenticate with external providers..................................................................................................................... 321 Authenticate with bearer tokens.............................................................................................................................. 323 Authenticate with an OpenID Connect or OAuth 2.0 Identity provider................................................... 324 Issue security tokens from an ASP.NET Core service....................................................................................... 325 Consume security tokens............................................................................................................................................ 326 Additional resources.......................................................................................................................................................... 327 About authorization in.NET microservices and web applications.................................................................. 327 Implement role-based authorization..................................................................................................................... 328 Implement policy-based authorization................................................................................................................. 329 Authorization and minimal apis............................................................................................................................... 330 Additional resources..................................................................................................................................................... 330 viii Contents Store application secrets safely during development.......................................................................................... 330 Store secrets in environment variables................................................................................................................. 331 Store secrets with the ASP.NET Core Secret Manager.................................................................................... 331 Use Azure Key Vault to protect secrets at production time.............................................................................. 332 Additional resources..................................................................................................................................................... 333.NET Microservices Architecture key takeaways.............................................................. 334 ix Contents CHAPTER 1 Introduction to Containers and Docker Containerization is an approach to software development in which an application or service, its dependencies, and its configuration (abstracted as deployment manifest files) are packaged together as a container image. The containerized application can be tested as a unit and deployed as a container image instance to the host operating system (OS). Just as shipping containers allow goods to be transported by ship, train, or truck regardless of the cargo inside, software containers act as a standard unit of software deployment that can contain different code and dependencies. Containerizing software this way enables developers and IT professionals to deploy them across environments with little or no modification. Containers also isolate applications from each other on a shared OS. Containerized applications run on top of a container host that in turn runs on the OS (Linux or Windows). Containers therefore have a significantly smaller footprint than virtual machine (VM) images. Each container can run a whole web application or a service, as shown in Figure 2-1. In this example, Docker host is a container host, and App1, App2, Svc 1, and Svc 2 are containerized applications or services. Figure 2-1. Multiple containers running on a container host 1 CHAPTER 1 | Introduction to Containers and Docker Another benefit of containerization is scalability. You can scale out quickly by creating new containers for short-term tasks. From an application point of view, instantiating an image (creating a container) is similar to instantiating a process like a service or a web app. For reliability, however, when you run multiple instances of the same image across multiple host servers, you typically want each container (image instance) to run in a different host server or VM in different fault domains. In short, containers offer the benefits of isolation, portability, agility, scalability, and control across the whole application lifecycle workflow. The most important benefit is the environment’s isolation provided between Dev and Ops. What is Docker? Docker is an open-source project for automating the deployment of applications as portable, self- sufficient containers that can run on the cloud or on-premises. Docker is also a company that promotes and evolves this technology, working in collaboration with cloud, Linux, and Windows vendors, including Microsoft. Figure 2-2. Docker deploys containers at all layers of the hybrid cloud. Docker containers can run anywhere, on-premises in the customer datacenter, in an external service provider or in the cloud, on Azure. Docker image containers can run natively on Linux and Windows. However, Windows images can run only on Windows hosts and Linux images can run on Linux hosts and Windows hosts (using a Hyper-V Linux VM, so far), where host means a server or a VM. Developers can use development environments on Windows, Linux, or macOS. On the development computer, the developer runs a Docker host where Docker images are deployed, including the app and its dependencies. Developers who work on Linux or on macOS use a Docker host that is Linux based, and they can create images only for Linux containers. (Developers working on macOS can edit code or run the Docker CLI from macOS, but as of the time of this writing, containers don’t run 2 CHAPTER 1 | Introduction to Containers and Docker directly on macOS.) Developers who work on Windows can create images for either Linux or Windows Containers. To host containers in development environments and provide additional developer tools, Docker ships Docker Desktop for Windows or for macOS. These products install the necessary VM (the Docker host) to host the containers. To run Windows Containers, there are two types of runtimes: Windows Server Containers provide application isolation through process and namespace isolation technology. A Windows Server Container shares a kernel with the container host and with all containers running on the host. Hyper-V Containers expand on the isolation provided by Windows Server Containers by running each container in a highly optimized virtual machine. In this configuration, the kernel of the container host isn’t shared with the Hyper-V Containers, providing better isolation. The images for these containers are created the same way and function the same. The difference is in how the container is created from the image running a Hyper-V Container requires an extra parameter. For details, see Hyper-V Containers. Comparing Docker containers with virtual machines Figure 2-3 shows a comparison between VMs and Docker containers. Virtual Machines Docker Containers 3 CHAPTER 1 | Introduction to Containers and Docker Virtual Machines Docker Containers Virtual machines include the application, the Containers include the application and all its required libraries or binaries, and a full guest dependencies. However, they share the OS kernel operating system. Full virtualization requires with other containers, running as isolated more resources than containerization. processes in user space on the host operating system. (Except in Hyper-V containers, where each container runs inside of a special virtual machine per container.) Figure 2-3. Comparison of traditional virtual machines to Docker containers For VMs, there are three base layers in the host server, from the bottom-up: infrastructure, Host Operating System and a Hypervisor and on top of all that each VM has its own OS and all necessary libraries. For Docker, the host server only has the infrastructure and the OS and on top of that, the container engine, that keeps container isolated but sharing the base OS services. Because containers require far fewer resources (for example, they don’t need a full OS), they’re easy to deploy and they start fast. This allows you to have higher density, meaning that it allows you to run more services on the same hardware unit, thereby reducing costs. As a side effect of running on the same kernel, you get less isolation than VMs. The main goal of an image is that it makes the environment (dependencies) the same across different deployments. This means that you can debug it on your machine and then deploy it to another machine with the same environment guaranteed. A container image is a way to package an app or service and deploy it in a reliable and reproducible way. You could say that Docker isn’t only a technology but also a philosophy and a process. When using Docker, you won’t hear developers say, “It works on my machine, why not in production?” They can simply say, “It runs on Docker”, because the packaged Docker application can be executed on any supported Docker environment, and it runs the way it was intended to on all deployment targets (such as Dev, QA, staging, and production). A simple analogy Perhaps a simple analogy can help getting the grasp of the core concept of Docker. Let’s go back in time to the 1950s for a moment. There were no word processors, and the photocopiers were used everywhere (kind of). Imagine you’re responsible for quickly issuing batches of letters as required, to mail them to customers, using real paper and envelopes, to be delivered physically to each customer’s address (there was no email back then). At some point, you realize the letters are just a composition of a large set of paragraphs, which are picked and arranged as needed, according to the purpose of the letter, so you devise a system to issue letters quickly, expecting to get a hefty raise. The system is simple: 1. You begin with a deck of transparent sheets containing one paragraph each. 4 CHAPTER 1 | Introduction to Containers and Docker 2. To issue a set of letters, you pick the sheets with the paragraphs you need, then you stack and align them so they look and read fine. 3. Finally, you place the set in the photocopier and press start to produce as many letters as required. So, simplifying, that’s the core idea of Docker. In Docker, each layer is the resulting set of changes that happen to the filesystem after executing a command, such as, installing a program. So, when you “look” at the filesystem after the layer has been copied, you see all the files, included in the layer when the program was installed. You can think of an image as an auxiliary read-only hard disk ready to be installed in a “computer” where the operating system is already installed. Similarly, you can think of a container as the “computer” with the image hard disk installed. The container, just like a computer, can be powered on or off. Docker terminology This section lists terms and definitions you should be familiar with before getting deeper into Docker. For further definitions, see the extensive glossary provided by Docker. Container image: A package with all the dependencies and information needed to create a container. An image includes all the dependencies (such as frameworks) plus deployment and execution configuration to be used by a container runtime. Usually, an image derives from multiple base images that are layers stacked on top of each other to form the container’s filesystem. An image is immutable once it has been created. Dockerfile: A text file that contains instructions for building a Docker image. It’s like a batch script, the first line states the base image to begin with and then follow the instructions to install required programs, copy files, and so on, until you get the working environment you need. Build: The action of building a container image based on the information and context provided by its Dockerfile, plus additional files in the folder where the image is built. You can build images with the following Docker command: docker build Container: An instance of a Docker image. A container represents the execution of a single application, process, or service. It consists of the contents of a Docker image, an execution environment, and a standard set of instructions. When scaling a service, you create multiple instances of a container from the same image. Or a batch job can create multiple containers from the same image, passing different parameters to each instance. Volumes: Offer a writable filesystem that the container can use. Since images are read-only but most programs need to write to the filesystem, volumes add a writable layer, on top of the container image, so the programs have access to a writable filesystem. The program doesn’t know it’s accessing a 5 CHAPTER 1 | Introduction to Containers and Docker layered filesystem, it’s just the filesystem as usual. Volumes live in the host system and are managed by Docker. Tag: A mark or label you can apply to images so that different images or versions of the same image (depending on the version number or the target environment) can be identified. Multi-stage Build: Is a feature, since Docker 17.05 or higher, that helps to reduce the size of the final images. For example, a large base image, containing the SDK can be used for compiling and publishing and then a small runtime-only base image can be used to host the application. Repository (repo): A collection of related Docker images, labeled with a tag that indicates the image version. Some repos contain multiple variants of a specific image, such as an image containing SDKs (heavier), an image containing only runtimes (lighter), etc. Those variants can be marked with tags. A single repo can contain platform variants, such as a Linux image and a Windows image. Registry: A service that provides access to repositories. The default registry for most public images is Docker Hub (owned by Docker as an organization). A registry usually contains repositories from multiple teams. Companies often have private registries to store and manage images they’ve created. Azure Container Registry is another example. Multi-arch image: For multi-architecture (or multi-platform), it’s a Docker feature that simplifies the selection of the appropriate image, according to the platform where Docker is running. For example, when a Dockerfile requests a base image FROM mcr.microsoft.com/dotnet/sdk:7.0 from the registry, it actually gets 7.0-nanoserver-ltsc2022, 7.0-nanoserver-1809 or 7.0-bullseye-slim, depending on the operating system and version where Docker is running. Docker Hub: A public registry to upload images and work with them. Docker Hub provides Docker image hosting, public or private registries, build triggers and web hooks, and integration with GitHub and Bitbucket. Azure Container Registry: A public resource for working with Docker images and its components in Azure. This provides a registry that’s close to your deployments in Azure and that gives you control over access, making it possible to use your Azure Active Directory groups and permissions. Docker Trusted Registry (DTR): A Docker registry service (from Docker) that can be installed on- premises so it lives within the organization’s datacenter and network. It’s convenient for private images that should be managed within the enterprise. Docker Trusted Registry is included as part of the Docker Datacenter product. Docker Desktop: Development tools for Windows and macOS for building, running, and testing containers locally. Docker Desktop for Windows provides development environments for both Linux and Windows Containers. The Linux Docker host on Windows is based on a Hyper-V virtual machine. The host for Windows Containers is directly based on Windows. Docker Desktop for Mac is based on the Apple Hypervisor framework and the xhyve hypervisor, which provides a Linux Docker host virtual machine on macOS. Docker Desktop for Windows and for Mac replaces Docker Toolbox, which was based on Oracle VirtualBox. Compose: A command-line tool and YAML file format with metadata for defining and running multi- container applications. You define a single application based on multiple images with one or more.yml files that can override values depending on the environment. After you’ve created the definitions, 6 CHAPTER 1 | Introduction to Containers and Docker you can deploy the whole multi-container application with a single command (docker-compose up) that creates a container per image on the Docker host. Cluster: A collection of Docker hosts exposed as if it were a single virtual Docker host, so that the application can scale to multiple instances of the services spread across multiple hosts within the cluster. Docker clusters can be created with Kubernetes, Azure Service Fabric, Docker Swarm and Mesosphere DC/OS. Orchestrator: A tool that simplifies the management of clusters and Docker hosts. Orchestrators enable you to manage their images, containers, and hosts through a command-line interface (CLI) or a graphical UI. You can manage container networking, configurations, load balancing, service discovery, high availability, Docker host configuration, and more. An orchestrator is responsible for running, distributing, scaling, and healing workloads across a collection of nodes. Typically, orchestrator products are the same products that provide cluster infrastructure, like Kubernetes and Azure Service Fabric, among other offerings in the market. Docker containers, images, and registries When using Docker, a developer creates an app or service and packages it and its dependencies into a container image. An image is a static representation of the app or service and its configuration and dependencies. To run the app or service, the app’s image is instantiated to create a container, which will be running on the Docker host. Containers are initially tested in a development environment or PC. Developers should store images in a registry, which acts as a library of images and is needed when deploying to production orchestrators. Docker maintains a public registry via Docker Hub; other vendors provide registries for different collections of images, including Azure Container Registry. Alternatively, enterprises can have a private registry on-premises for their own Docker images. Figure 2-4 shows how images and registries in Docker relate to other components. It also shows the multiple registry offerings from vendors. 7 CHAPTER 1 | Introduction to Containers and Docker Figure 2-4. Taxonomy of Docker terms and concepts The registry is like a bookshelf where images are stored and available to be pulled for building containers to run services or web apps. There are private Docker registries on-premises and on the public cloud. Docker Hub is a public registry maintained by Docker, along the Docker Trusted Registry an enterprise-grade solution, Azure offers the Azure Container Registry. AWS, Google, and others also have container registries. Putting images in a registry lets you store static and immutable application bits, including all their dependencies at a framework level. Those images can then be versioned and deployed in multiple environments and therefore provide a consistent deployment unit. Private image registries, either hosted on-premises or in the cloud, are recommended when: Your images must not be shared publicly due to confidentiality. You want to have minimum network latency between your images and your chosen deployment environment. For example, if your production environment is Azure cloud, you probably want to store your images in Azure Container Registry so that network latency will be minimal. In a similar way, if your production environment is on-premises, you might want to have an on-premises Docker Trusted Registry available within the same local network. 8 CHAPTER 1 | Introduction to Containers and Docker CHAPTER 2 Choosing Between.NET and.NET Framework for Docker Containers There are two supported frameworks for building server-side containerized Docker applications with.NET:.NET Framework and.NET 7. They share many.NET platform components, and you can share code across the two. However, there are fundamental differences between them, and which framework you use will depend on what you want to accomplish. This section provides guidance on when to choose each framework. General guidance This section provides a summary of when to choose.NET 7 or.NET Framework. We provide more details about these choices in the sections that follow. Use.NET 7, with Linux or Windows Containers, for your containerized Docker server application when: You have cross-platform needs. For example, you want to use both Linux and Windows Containers. Your application architecture is based on microservices. You need to start containers fast and want a small footprint per container to achieve better density or more containers per hardware unit in order to lower your costs. In short, when you create new containerized.NET applications, you should consider.NET 7 as the default choice. It has many benefits and fits best with the containers philosophy and style of working. An extra benefit of using.NET 7 is that you can run side-by-side.NET versions for applications within the same machine. This benefit is more important for servers or VMs that do not use containers, because containers isolate the versions of.NET that the app needs. (As long as they are compatible with the underlying OS.) Use.NET Framework for your containerized Docker server application when: Your application currently uses.NET Framework and has strong dependencies on Windows. 9 CHAPTER 2 | Choosing Between.NET and.NET Framework for Docker Containers You need to use Windows APIs that are not supported by.NET 7. You need to use third-party.NET libraries or NuGet packages that are not available for.NET 7. Using.NET Framework on Docker can improve your deployment experiences by minimizing deployment issues. This “lift and shift” scenario is important for containerizing legacy applications that were originally developed with the traditional.NET Framework, like ASP.NET WebForms, MVC web apps, or WCF (Windows Communication Foundation) services. Additional resources E-book: Modernize existing.NET Framework applications with Azure and Windows Containers https://aka.ms/liftandshiftwithcontainersebook Sample apps: Modernization of legacy ASP.NET web apps by using Windows Containers https://aka.ms/eshopmodernizing When to choose.NET for Docker containers The modularity and lightweight nature of.NET 7 makes it perfect for containers. When you deploy and start a container, its image is far smaller with.NET 7 than with.NET Framework. In contrast, to use.NET Framework for a container, you must base your image on the Windows Server Core image, which is a lot heavier than the Windows Nano Server or Linux images that you use for.NET 7. Additionally,.NET 7 is cross-platform, so you can deploy server apps with Linux or Windows container images. However, if you are using the traditional.NET Framework, you can only deploy images based on Windows Server Core. The following is a more detailed explanation of why to choose.NET 7. Developing and deploying cross platform Clearly, if your goal is to have an application (web app or service) that can run on multiple platforms supported by Docker (Linux and Windows), the right choice is.NET 7, because.NET Framework only supports Windows..NET 7 also supports macOS as a development platform. However, when you deploy containers to a Docker host, that host must (currently) be based on Linux or Windows. For example, in a development environment, you could use a Linux VM running on a Mac. Visual Studio provides an integrated development environment (IDE) for Windows and supports Docker development. Visual Studio for Mac is an IDE, evolution of Xamarin Studio, that runs on macOS and supports Docker-based application development. This tool should be the preferred choice for developers working in Mac machines who also want to use a powerful IDE. You can also use Visual Studio Code on macOS, Linux, and Windows. Visual Studio Code fully supports.NET 7, including IntelliSense and debugging. Because VS Code is a lightweight editor, you 10 CHAPTER 2 | Choosing Between.NET and.NET Framework for Docker Containers can use it to develop containerized apps on the machine in conjunction with the Docker CLI and the.NET CLI. You can also target.NET 7 with most third-party editors like Sublime, Emacs, vi, and the open-source OmniSharp project, which also provides IntelliSense support. In addition to the IDEs and editors, you can use the.NET CLI for all supported platforms. Using containers for new (“green-field”) projects Containers are commonly used in conjunction with a microservices architecture, although they can also be used to containerize web apps or services that follow any architectural pattern. You can use.NET Framework on Windows Containers, but the modularity and lightweight nature of.NET 7 makes it perfect for containers and microservices architectures. When you create and deploy a container, its image is far smaller with.NET 7 than with.NET Framework. Create and deploy microservices on containers You could use the traditional.NET Framework for building microservices-based applications (without containers) by using plain processes. That way, because the.NET Framework is already installed and shared across processes, processes are light and fast to start. However, if you are using containers, the image for the traditional.NET Framework is also based on Windows Server Core and that makes it too heavy for a microservices-on-containers approach. However, teams have been looking for opportunities to improve the experience for.NET Framework users as well. Recently, size of the Windows Server Core container images have been reduced to >40% smaller. On the other hand,.NET 7 is the best candidate if you’re embracing a microservices-oriented system that is based on containers because.NET 7 is lightweight. In addition, its related container images, for either Linux or Windows Nano Server, are lean and small, making containers light and fast to start. A microservice is meant to be as small as possible: to be light when spinning up, to have a small footprint, to have a small Bounded Context (check DDD, Domain-Driven Design), to represent a small area of concerns, and to be able to start and stop fast. For those requirements, you will want to use small and fast-to-instantiate container images like the.NET 7 container image. A microservices architecture also allows you to mix technologies across a service boundary. This approach enables a gradual migration to.NET 7 for new microservices that work in conjunction with other microservices or with services developed with Node.js, Python, Java, GoLang, or other technologies. Deploying high density in scalable systems When your container-based system needs the best possible density, granularity, and performance,.NET and ASP.NET Core are your best options. ASP.NET Core is up to 10 times faster than ASP.NET in the traditional.NET Framework, and it leads to other popular industry technologies for microservices, such as Java servlets, Go, and Node.js. This approach is especially relevant for microservices architectures, where you could have hundreds of microservices (containers) running. With ASP.NET Core images (based on the.NET runtime) on Linux or Windows Nano, you can run your system with a much lower number of servers or VMs, ultimately saving costs in infrastructure and hosting. 11 CHAPTER 2 | Choosing Between.NET and.NET Framework for Docker Containers When to choose.NET Framework for Docker containers While.NET 7 offers significant benefits for new applications and application patterns,.NET Framework will continue to be a good choice for many existing scenarios. Migrating existing applications directly to a Windows Server container You might want to use Docker containers just to simplify deployment, even if you are not creating microservices. For example, perhaps you want to improve your DevOps workflow with Docker— containers can give you better isolated test environments and can also eliminate deployment issues caused by missing dependencies when you move to a production environment. In cases like these, even if you are deploying a monolithic application, it makes sense to use Docker and Windows Containers for your current.NET Framework applications. In most cases for this scenario, you will not need to migrate your existing applications to.NET 7; you can use Docker containers that include the traditional.NET Framework. However, a recommended approach is to use.NET 7 as you extend an existing application, such as writing a new service in ASP.NET Core. Using third-party.NET libraries or NuGet packages not available for.NET 7 Third-party libraries are quickly embracing.NET Standard, which enables code sharing across all.NET flavors, including.NET 7. With.NET Standard 2.0 and later, the API surface compatibility across different frameworks has become significantly larger. Even more,.NET Core 2.x and newer applications can also directly reference existing.NET Framework libraries (see.NET Framework 4.6.1 supporting.NET Standard 2.0). In addition, the Windows Compatibility Pack extends the API surface available for.NET Standard 2.0 on Windows. This pack allows recompiling most existing code to.NET Standard 2.x with little or no modification, to run on Windows. However, even with that exceptional progression since.NET Standard 2.0 and.NET Core 2.1 or later, there might be cases where certain NuGet packages need Windows to run and might not support.NET Core or later. If those packages are critical for your application, then you will need to use.NET Framework on Windows Containers. Using.NET technologies not available for.NET 7 Some.NET Framework technologies aren’t available in.NET 7. Some of them might become available in later releases, but others don’t fit the new application patterns targeted by.NET Core and might never be available. The following list shows most of the technologies that aren’t available in.NET 7: 12 CHAPTER 2 | Choosing Between.NET and.NET Framework for Docker Containers ASP.NET Web Forms. This technology is only available on.NET Framework. Currently there are no plans to bring ASP.NET Web Forms to.NET or later. Workflow-related services. Windows Workflow Foundation (WF), Workflow Services (WCF + WF in a single service), and WCF Data Services (formerly known as ADO.NET Data Services) are only available on.NET Framework. There are currently no plans to bring them to.NET 7. In addition to the technologies listed in the official.NET roadmap, other features might be ported to the new unified.NET platform. You might consider participating in the discussions on GitHub so that your voice can be heard. And if you think something is missing, file a new issue in the dotnet/runtime GitHub repository. Using a platform or API that doesn’t support.NET 7 Some Microsoft and third-party platforms don’t support.NET 7. For example, some Azure services provide an SDK that isn’t yet available for consumption on.NET 7 yet. Most Azure SDK should eventually be ported to.NET 7/.NET Standard, but some might not for several reasons. You can see the available Azure SDKs in the Azure SDK Latest Releases page. In the meantime, if any platform or service in Azure still doesn’t support.NET 7 with its client API, you can use the equivalent REST API from the Azure service or the client SDK on.NET Framework. Porting existing ASP.NET application to.NET 7.NET Core is a revolutionary step forward from.NET Framework. It offers a host of advantages over.NET Framework across the board from productivity to performance, and from cross-platform support to developer satisfaction. If you are using.NET Framework and planning to migrate your application to.NET Core or.NET 5+, see Porting Existing ASP.NET Apps to.NET Core. Additional resources.NET fundamentals https://learn.microsoft.com/dotnet/fundamentals Porting Projects to.NET 5 https://learn.microsoft.com/events/dotnetconf-2020/porting-projects-to-net-5.NET on Docker Guide https://learn.microsoft.com/dotnet/core/docker/introduction Decision table:.NET implementations to use for Docker The following decision table summarizes whether to use.NET Framework or.NET 7. Remember that for Linux containers, you need Linux-based Docker hosts (VMs or servers), and that for Windows Containers, you need Windows Server-based Docker hosts (VMs or servers). 13 CHAPTER 2 | Choosing Between.NET and.NET Framework for Docker Containers Important Your development machines will run one Docker host, either Linux or Windows. Related microservices that you want to run and test together in one solution will all need to run on the same container platform. Architecture / App Type Linux containers Windows Containers Microservices on containers.NET 7.NET 7 Monolithic app.NET 7.NET Framework.NET 7 Best-in-class performance and.NET 7.NET 7 scalability Windows Server legacy app (“brown- –.NET Framework field”) migration to containers New container-based development.NET 7.NET 7 (“green-field”) ASP.NET Core.NET 7.NET 7 (recommended).NET Framework ASP.NET 4 (MVC 5, Web API 2, and –.NET Framework Web Forms) SignalR services.NET Core 2.1 or higher.NET Framework version.NET Core 2.1 or higher version WCF, WF, and other legacy WCF in.NET Core (client.NET Framework frameworks library only) or CoreWCF WCF in.NET 7 (client library only) or CoreWCF Consumption of Azure services.NET 7.NET Framework (eventually most Azure.NET 7 services will provide client (eventually most Azure SDKs for.NET 7) services will provide client SDKs for.NET 7) What OS to target with.NET containers Given the diversity of operating systems supported by Docker and the differences between.NET Framework and.NET 7, you should target a specific OS and specific versions depending on the framework you are using. For Windows, you can use Windows Server Core or Windows Nano Server. These Windows versions provide different characteristics (IIS in Windows Server Core versus a self-hosted web server like Kestrel in Nano Server) that might be needed by.NET Framework or.NET 7, respectively. For Linux, multiple distros are available and supported in official.NET Docker images (like Debian). 14 CHAPTER 2 | Choosing Between.NET and.NET Framework for Docker Containers In Figure 3-1, you can see the possible OS version depending on the.NET framework used. Figure 3-1. Operating systems to target depending on versions of the.NET framework When deploying legacy.NET Framework applications you have to target Windows Server Core, compatible with legacy apps and IIS, but it has a larger image. When deploying.NET 7 applications, you can target Windows Nano Server, which is cloud optimized, uses Kestrel and is smaller and starts faster. You can also target Linux, supporting Debian, Alpine, and others. You can also create your own Docker image in cases where you want to use a different Linux distro or where you want an image with versions not provided by Microsoft. For example, you might create an image with ASP.NET Core running on the traditional.NET Framework and Windows Server Core, which is a not-so-common scenario for Docker. When you add the image name to your Dockerfile file, you can select the operating system and version depending on the tag you use, as in the following examples: Image Comments mcr.microsoft.com/dotnet/runtime:7.0.NET 7 multi-architecture: Supports Linux and Windows Nano Server depending on the Docker host. mcr.microsoft.com/dotnet/aspnet:7.0 ASP.NET Core 7.0 multi-architecture: Supports Linux and Windows Nano Server depending on the Docker host. The aspnetcore image has a few optimizations for ASP.NET Core. mcr.microsoft.com/dotnet/aspnet:7.0-.NET 7 runtime-only on Linux Debian distro bullseye-slim mcr.microsoft.com/dotnet/aspnet:7.0-.NET 7 runtime-only on Windows Nano Server (Windows nanoserver-1809 Server version 1809) 15 CHAPTER 2 | Choosing Between.NET and.NET Framework for Docker Containers Official.NET Docker images The Official.NET Docker images are Docker images created and optimized by Microsoft. They’re publicly available on Microsoft Artifact Registry. You can search over the catalog to find all.NET image repositories, for example.NET SDK repository. Each repository can contain multiple images, depending on.NET versions, and depending on the OS and versions (Linux Debian, Linux Alpine, Windows Nano Server, Windows Server Core, and so on). Image repositories provide extensive tagging to help you select not just a specific framework version, but also to choose an OS (Linux distribution or Windows version)..NET and Docker image optimizations for development versus production When building Docker images for developers, Microsoft focused on the following main scenarios: Images used to develop and build.NET apps. Images used to run.NET apps. Why multiple images? When developing, building, and running containerized applications, you usually have different priorities. By providing different images for these separate tasks, Microsoft helps optimize the separate processes of developing, building, and deploying apps. During development and build During development, what is important is how fast you can iterate changes, and the ability to debug the changes. The size of the image isn’t as important as the ability to make changes to your code and see the changes quickly. Some tools and “build-agent containers”, use the development.NET image (mcr.microsoft.com/dotnet/sdk:7.0) during development and build process. When building inside a Docker container, the important aspects are the elements that are needed to compile your app. This includes the compiler and any other.NET dependencies. Why is this type of build image important? You don’t deploy this image to production. Instead, it’s an image that you use to build the content you place into a production image. This image would be used in your continuous integration (CI) environment or build environment when using Docker multi-stage builds. In production What is important in production is how fast you can deploy and start your containers based on a production.NET image. Therefore, the runtime-only image based on mcr.microsoft.com/dotnet/aspnet:7.0 is small so that it can travel quickly across the network from your Docker registry to your Docker hosts. The contents are ready to run, enabling the fastest time from starting the container to processing results. In the Docker model, there is no need for compilation from C# code, as there’s when you run dotnet build or dotnet publish when using the build container. 16 CHAPTER 2 | Choosing Between.NET and.NET Framework for Docker Containers In this optimized image, you put only the binaries and other content needed to run the application. For example, the content created by dotnet publish contains only the compiled.NET binaries, images,.js, and.css files. Over time, you’ll see images that contain pre-jitted (the compilation from IL to native that occurs at run time) packages. Although there are multiple versions of the.NET and ASP.NET Core images, they all share one or more layers, including the base layer. Therefore, the amount of disk space needed to store an image is small; it consists only of the delta between your custom image and its base image. The result is that it’s quick to pull the image from your registry. When you explore the.NET image repositories at Microsoft Artifact Registry, you’ll find multiple image versions classified or marked with tags. These tags help to decide which one to use, depending on the version you need, like those in the following table: Image Comments mcr.microsoft.com/dotnet/aspnet:7.0 ASP.NET Core, with runtime only and ASP.NET Core optimizations, on Linux and Windows (multi-arch) mcr.microsoft.com/dotnet/sdk:7.0.NET 7, with SDKs included, on Linux and Windows (multi-arch) You can find all the available docker images in dotnet-docker and also refer to the latest preview releases by using nightly build mcr.microsoft.com/dotnet/nightly/* 17 CHAPTER 2 | Choosing Between.NET and.NET Framework for Docker Containers CHAPTER 3 Architecting container and microservice-based applications Microservices offer great benefits but also raise huge new challenges. Microservice architecture patterns are fundamental pillars when creating a microservice-based application. Earlier in this guide, you learned basic concepts about containers and Docker. That information was the minimum you needed to get started with containers. Even though containers are enablers of, and a great fit for microservices, they aren’t mandatory for a microservice architecture. Many architectural concepts in this architecture section could be applied without containers. However, this guide focuses on the intersection of both due to the already introduced importance of containers. Enterprise applications can be complex and are often composed of multiple services instead of a single service-based application. For those cases, you need to understand other architectural approaches, such as the microservices and certain Domain-Driven Design (DDD) patterns plus container orchestration concepts. Note that this chapter describes not just microservices on containers, but any containerized application, as well. Container design principles In the container model, a container image instance represents a single process. By defining a container image as a process boundary, you can create primitives that can be used to scale or batch the process. When you design a container image, you’ll see an ENTRYPOINT definition in the Dockerfile. This definition defines the process whose lifetime controls the lifetime of the container. When the process completes, the container lifecycle ends. Containers might represent long-running processes like web servers, but can also represent short-lived processes like batch jobs, which formerly might have been implemented as Azure WebJobs. If the process fails, the container ends, and the orchestrator takes over. If the orchestrator was configured to keep five instances running and one fails, the orchestrator will create another container instance to replace the failed process. In a batch job, the process is started with parameters. When the process completes, the work is complete. This guidance drills-down on orchestrators, later on. 18 CHAPTER 3 | Architecting container and microservice-based applications You might find a scenario where you want multiple processes running in a single container. For that scenario, since there can be only one entry point per container, you could run a script within the container that launches as many programs as needed. For example, you can use Supervisor or a similar tool to take care of launching multiple processes inside a single container. However, even though you can find architectures that hold multiple processes per container, that approach isn’t very common. Containerizing monolithic applications You might want to build a single, monolithically deployed web application or service and deploy it as a container. The application itself might not be internally monolithic, but structured as several libraries, components, or even layers (application layer, domain layer, data-access layer, etc.). Externally, however, it’s a single container—a single process, a single web application, or a single service. To manage this model, you deploy a single container to represent the application. To increase capacity, you scale out, that is, just add more copies with a load balancer in front. The simplicity comes from managing a single deployment in a single container or VM. Figure 4-1. Example of the architecture of a containerized monolithic application You can include multiple components, libraries, or internal layers in each container, as illustrated in Figure 4-1. A monolithic containerized application has most of its functionality within a single container, with internal layers or libraries, and scales out by cloning the container on multiple servers/VMs. However, this monolithic pattern might conflict with the container principle “a container does one thing, and does it in one process”, but might be ok for some cases. The downside of this approach becomes evident if the application grows, requiring it to scale. If the entire application can scale, it isn’t really a problem. However, in most cases, just a few parts of the application are the choke points that require scaling, while other components are used less. For example, in a typical e-commerce application, you likely need to scale the product information subsystem, because many more customers browse products than purchase them. More customers use 19 CHAPTER 3 | Architecting container and microservice-based applications their basket than use the payment pipeline. Fewer customers add comments or view their purchase history. And you might have only a handful of employees that need to manage the content and marketing campaigns. If you scale the monolithic design, all the code for these different tasks is deployed multiple times and scaled at the same grade. There are multiple ways to scale an application-horizontal duplication, splitting different areas of the application, and partitioning similar business concepts or data. But, in addition to the problem of scaling all components, changes to a single component require complete retesting of the entire application, and a complete redeployment of all the instances. However, the monolithic approach is common, because the development of the application is initially easier than for microservices approaches. Thus, many organizations develop using this architectural approach. While some organizations have had good enough results, others are hitting limits. Many organizations designed their applications using this model because tools and infrastructure made it too difficult to build service-oriented architectures (SOA) years ago, and they did not see the need- until the application grew. From an infrastructure perspective, each server can run many applications within the same host and have an acceptable ratio of efficiency in resources usage, as shown in Figure 4-2. Figure 4-2. Monolithic approach: Host running multiple apps, each app running as a container Monolithic applications in Microsoft Azure can be deployed using dedicated VMs for each instance. Additionally, using Azure virtual machine scale sets, you can easily scale the VMs. Azure App Service can also run monolithic applications and easily scale instances without requiring you to manage the VMs. Since 2016, Azure App Services can run single instances of Docker containers as well, simplifying deployment. As a QA environment or a limited production environment, you can deploy multiple Docker host VMs and balance them using the Azure balancer, as shown in Figure 4-3. This lets you manage scaling with a coarse-grain approach, because the whole application lives within a single container. 20 CHAPTER 3 | Architecting container and microservice-based applications Figure 4-3. Example of multiple hosts scaling up a single container application Deployment to the various hosts can be managed with traditional deployment techniques. Docker hosts can be managed with commands like docker run or docker-compose performed manually, or through automation such as continuous delivery (CD) pipelines. Deploying a monolithic application as a container There are benefits to using containers to manage monolithic application deployments. Scaling container instances is far faster and easier than deploying additional VMs. Even if you use virtual machine scale sets, VMs take time to start. When deployed as traditional application instances instead of containers, the configuration of the application is managed as part of the VM, which isn’t ideal. Deploying updates as Docker images is far faster and network efficient. Docker images typically start in seconds, which speeds rollouts. Tearing down a Docker image instance is as easy as issuing a docker stop command, and typically completes in less than a second. Because containers are immutable by design, you never need to worry about corrupted VMs. In contrast, update scripts for a VM might forget to account for some specific configuration or file left on disk. While monolithic applications can benefit from Docker, we’re touching only on the benefits. Additional benefits of managing containers come from deploying with container orchestrators, which manage the various instances and lifecycle of each container instance. Breaking up the monolithic application into subsystems that can be scaled, developed, and deployed individually is your entry point into

Use Quizgecko on...
Browser
Browser