From 7bf6d18fbecf73682a29641906e857a3292ea0b6 Mon Sep 17 00:00:00 2001 From: Simon Kurtz <84809797+simonkurtz-MSFT@users.noreply.github.com> Date: Tue, 21 Nov 2023 11:46:39 -0500 Subject: [PATCH] Add container optimizations (#147) * Add container optimizations * Fix copy/paste issue * Add frontend UI and backend svc as well * Move appendix from 13 to 30 * Move appendix from 13 to 30 * Move authors to 29 * Change Optimize modules from 99 to 12 * Update path from 99 to 12 * Minor copy change --- CONTRIBUTING.md | 2 +- README.md | 2 +- docs/aca/00-workshop-intro/4-prerequisites.md | 2 +- docs/aca/03-aca-dapr-integration/index.md | 2 +- docs/aca/04-aca-dapr-stateapi/index.md | 2 +- docs/aca/05-aca-dapr-pubsubapi/index.md | 4 +- docs/aca/06-aca-dapr-bindingsapi/index.md | 2 +- .../Backend.Api.Dockerfile | 24 ++ .../Backend.Api.Dockerfile.chiseled | 24 ++ .../Backend.Api.Dockerfile.chiseled.aot | 24 ++ .../Backend.Svc.Dockerfile | 24 ++ .../Backend.Svc.Dockerfile.chiseled.aot | 24 ++ .../Frontend.Ui.Dockerfile | 24 ++ .../Frontend.Ui.Dockerfile.chiseled.aot | 24 ++ docs/aca/12-optimize-containers/index.md | 310 ++++++++++++++++++ .../index.md | 0 .../01-run-debug-dapr-app-vscode.md | 4 +- .../02-github-local-codespaces.md | 0 .../03-variables.md | 2 +- .../Set-Variables.ps1 | 0 .../{13-appendix => 30-appendix}/launch.json | 0 .../{13-appendix => 30-appendix}/tasks.json | 0 .../backend-api-chiseled-aot-image-stats.png | Bin 0 -> 25578 bytes .../backend-api-chiseled-aot.png | Bin 0 -> 4421 bytes .../backend-api-chiseled-image-stats.png | Bin 0 -> 25450 bytes .../backend-api-chiseled.png | Bin 0 -> 3725 bytes .../backend-api-status-quo-image-stats.png | Bin 0 -> 25953 bytes .../backend-api-status-quo.png | Bin 0 -> 2651 bytes docs/index.markdown | 2 +- mkdocs.yml | 9 +- snippets/persist-state.md | 13 +- 31 files changed, 507 insertions(+), 17 deletions(-) create mode 100644 docs/aca/12-optimize-containers/Backend.Api.Dockerfile create mode 100644 docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled create mode 100644 docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled.aot create mode 100644 docs/aca/12-optimize-containers/Backend.Svc.Dockerfile create mode 100644 docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled.aot create mode 100644 docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile create mode 100644 docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled.aot create mode 100644 docs/aca/12-optimize-containers/index.md rename docs/aca/{12-about-the-authors => 29-about-the-authors}/index.md (100%) rename docs/aca/{13-appendix => 30-appendix}/01-run-debug-dapr-app-vscode.md (98%) rename docs/aca/{13-appendix => 30-appendix}/02-github-local-codespaces.md (100%) rename docs/aca/{13-appendix => 30-appendix}/03-variables.md (96%) rename docs/aca/{13-appendix => 30-appendix}/Set-Variables.ps1 (100%) rename docs/aca/{13-appendix => 30-appendix}/launch.json (100%) rename docs/aca/{13-appendix => 30-appendix}/tasks.json (100%) create mode 100644 docs/assets/images/12-optimize-containers/backend-api-chiseled-aot-image-stats.png create mode 100644 docs/assets/images/12-optimize-containers/backend-api-chiseled-aot.png create mode 100644 docs/assets/images/12-optimize-containers/backend-api-chiseled-image-stats.png create mode 100644 docs/assets/images/12-optimize-containers/backend-api-chiseled.png create mode 100644 docs/assets/images/12-optimize-containers/backend-api-status-quo-image-stats.png create mode 100644 docs/assets/images/12-optimize-containers/backend-api-status-quo.png diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bdac44d9..eda79cd5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -121,7 +121,7 @@ Enhancement suggestions are tracked as [GitHub issues](https://github.com/Azure/ ### Making Contributions -Please familiarize yourself with how to run this project [here](https://azure.github.io/aca-dotnet-workshop/aca/13-appendix/02-github-local-codespaces). +Please familiarize yourself with how to run this project [here](https://azure.github.io/aca-dotnet-workshop/aca/30-appendix/02-github-local-codespaces). Whenever you are submitting any changes to the guide, please follow these recommendations: diff --git a/README.md b/README.md index f3082af8..3edb548c 100644 --- a/README.md +++ b/README.md @@ -20,4 +20,4 @@ We are most grateful for community involvement. Please see [CONTRIBUTING.md](htt ##### Acknowledgment -The workshop's material, concepts, and code samples draw inspiration from a collection of blog articles authored by [Taiseer Joudeh](https://github.com/tjoudeh) and published on his [personal blog](https://bitoftech.net). The [workshop authors](https://azure.github.io/aca-dotnet-workshop/aca/12-about-the-authors/) have worked collaboratively to modify and augment the content, resulting in the current version of the workshop. +The workshop's material, concepts, and code samples draw inspiration from a collection of blog articles authored by [Taiseer Joudeh](https://github.com/tjoudeh) and published on his [personal blog](https://bitoftech.net). The [workshop authors](https://azure.github.io/aca-dotnet-workshop/aca/29-about-the-authors/) have worked collaboratively to modify and augment the content, resulting in the current version of the workshop. diff --git a/docs/aca/00-workshop-intro/4-prerequisites.md b/docs/aca/00-workshop-intro/4-prerequisites.md index 30ecfb8f..8b28d97e 100644 --- a/docs/aca/00-workshop-intro/4-prerequisites.md +++ b/docs/aca/00-workshop-intro/4-prerequisites.md @@ -78,7 +78,7 @@ This workshop typically spans several days. As such, you may close your tools, e - In the root create a new file called `Set-Variables.ps1`. -- Copy the [Set-Variables.ps1 script](../../aca/13-appendix/03-variables.md){target=_blank} into the newly-created `Set-Variables.ps1` file and save it. +- Copy the [Set-Variables.ps1 script](../../aca/30-appendix/03-variables.md){target=_blank} into the newly-created `Set-Variables.ps1` file and save it. - Perform an initial commit of the `Set-Variables.ps1` file. diff --git a/docs/aca/03-aca-dapr-integration/index.md b/docs/aca/03-aca-dapr-integration/index.md index 4819c94e..21c855ff 100644 --- a/docs/aca/03-aca-dapr-integration/index.md +++ b/docs/aca/03-aca-dapr-integration/index.md @@ -245,7 +245,7 @@ We are ready now to verify the changes on the Frontend Web App and test locally. Notice how we assigned the Dapr App Id “tasksmanager-frontend-webapp” to the Frontend WebApp. !!! note - If you need to run both microservices together, you need to keep calling `dapr run` manually each time in the terminal. And when you have multiple microservices talking to each other you need to run at the same time to debug the solution. This can be a convoluted process. You can refer to the [debug and launch Dapr applications in VSCode](../13-appendix/01-run-debug-dapr-app-vscode.md) to see how to configure VScode for running and debugging Dapr applications. + If you need to run both microservices together, you need to keep calling `dapr run` manually each time in the terminal. And when you have multiple microservices talking to each other you need to run at the same time to debug the solution. This can be a convoluted process. You can refer to the [debug and launch Dapr applications in VSCode](../30-appendix/01-run-debug-dapr-app-vscode.md) to see how to configure VScode for running and debugging Dapr applications. #### 2.5 Test `{{ apps.frontend }}` and `{{ apps.backend }}` Locally Using Dapr diff --git a/docs/aca/04-aca-dapr-stateapi/index.md b/docs/aca/04-aca-dapr-stateapi/index.md index dd4f5f3c..112cc7b3 100644 --- a/docs/aca/04-aca-dapr-stateapi/index.md +++ b/docs/aca/04-aca-dapr-stateapi/index.md @@ -304,7 +304,7 @@ To add the component file state store, add a new folder named **components** und Now you should be ready to launch both applications and start doing CRUD operations from the Frontend Web App including querying the store. All your data will be stored in Cosmos DB Database you just provisioned. -If you have been running the different microservices using the [debug and launch Dapr applications in VSCode](../13-appendix/01-run-debug-dapr-app-vscode.md) then remember to uncomment the following line inside tasks.json file. +If you have been running the different microservices using the [debug and launch Dapr applications in VSCode](../30-appendix/01-run-debug-dapr-app-vscode.md) then remember to uncomment the following line inside tasks.json file. This will instruct dapr to load the local projects components located at **./components** instead of the global components' folder. ```json hl_lines="2" diff --git a/docs/aca/05-aca-dapr-pubsubapi/index.md b/docs/aca/05-aca-dapr-pubsubapi/index.md index 2a42dcc4..f1a13209 100644 --- a/docs/aca/05-aca-dapr-pubsubapi/index.md +++ b/docs/aca/05-aca-dapr-pubsubapi/index.md @@ -48,7 +48,7 @@ However, we want to have more control and provide our own component file, so let --8<-- "docs/aca/05-aca-dapr-pubsubapi/dapr-pubsub-redis.yaml" ``` -To try out the Pub/Sub API, run the Backend API from VS Code by running the below command or using the Run and Debug tasks we have created in the [appendix](../13-appendix/01-run-debug-dapr-app-vscode.md). +To try out the Pub/Sub API, run the Backend API from VS Code by running the below command or using the Run and Debug tasks we have created in the [appendix](../30-appendix/01-run-debug-dapr-app-vscode.md). === ".NET 6 or below" @@ -298,7 +298,7 @@ Shut down the sessions. #### 2.6 Optional: Update VS Code Tasks and Launch Configuration Files -If you have followed the steps in the [appendix](../13-appendix/01-run-debug-dapr-app-vscode.md) so far in order to be able to run the three services together (frontend, backend api, and backend processor) and debug them in VS Code, we need to update the files `tasks.json` and `launch.json` to include the new service we have added. +If you have followed the steps in the [appendix](../30-appendix/01-run-debug-dapr-app-vscode.md) so far in order to be able to run the three services together (frontend, backend api, and backend processor) and debug them in VS Code, we need to update the files `tasks.json` and `launch.json` to include the new service we have added. ??? example "Click to expand the files to update" diff --git a/docs/aca/06-aca-dapr-bindingsapi/index.md b/docs/aca/06-aca-dapr-bindingsapi/index.md index ed7f2bbf..998bd930 100644 --- a/docs/aca/06-aca-dapr-bindingsapi/index.md +++ b/docs/aca/06-aca-dapr-bindingsapi/index.md @@ -225,7 +225,7 @@ Now we are ready to give it an end-to-end test on our dev machines. To do so, ru --8<-- "snippets/dapr-run-backend-service.md:dapr-components" +in this [section](../30-appendix/01-run-debug-dapr-app-vscode.md). --> Open Azure Storage Explorer on your local machine. If you don't have it installed you can install it from [here](https://azure.microsoft.com/en-us/products/storage/storage-explorer/#overview){target=_blank}. Login to your Azure Subscription and navigate to the storage account already created, create a queue, and use the same name you already used in the Dapr Input configuration file. diff --git a/docs/aca/12-optimize-containers/Backend.Api.Dockerfile b/docs/aca/12-optimize-containers/Backend.Api.Dockerfile new file mode 100644 index 00000000..396a1ddd --- /dev/null +++ b/docs/aca/12-optimize-containers/Backend.Api.Dockerfile @@ -0,0 +1,24 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 5000 + +ENV ASPNETCORE_URLS=http://+:5000 + +USER app +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG configuration=Release +WORKDIR /src +COPY ["TasksTracker.TasksManager.Backend.Api/TasksTracker.TasksManager.Backend.Api.csproj", "TasksTracker.TasksManager.Backend.Api/"] +RUN dotnet restore "TasksTracker.TasksManager.Backend.Api/TasksTracker.TasksManager.Backend.Api.csproj" +COPY . . +WORKDIR "/src/TasksTracker.TasksManager.Backend.Api" +RUN dotnet build "TasksTracker.TasksManager.Backend.Api.csproj" -c $configuration -o /app/build + +FROM build AS publish +ARG configuration=Release +RUN dotnet publish "TasksTracker.TasksManager.Backend.Api.csproj" -c $configuration -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.TasksManager.Backend.Api.dll"] diff --git a/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled b/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled new file mode 100644 index 00000000..2a1dfc35 --- /dev/null +++ b/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled @@ -0,0 +1,24 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled AS base +WORKDIR /app +EXPOSE 5000 + +ENV ASPNETCORE_URLS=http://+:5000 + +USER app +FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy AS build +ARG configuration=Release +WORKDIR /src +COPY ["TasksTracker.TasksManager.Backend.Api/TasksTracker.TasksManager.Backend.Api.csproj", "TasksTracker.TasksManager.Backend.Api/"] +RUN dotnet restore "TasksTracker.TasksManager.Backend.Api/TasksTracker.TasksManager.Backend.Api.csproj" +COPY . . +WORKDIR "/src/TasksTracker.TasksManager.Backend.Api" +RUN dotnet build "TasksTracker.TasksManager.Backend.Api.csproj" -c $configuration -o /app/build + +FROM build AS publish +ARG configuration=Release +RUN dotnet publish "TasksTracker.TasksManager.Backend.Api.csproj" -c $configuration -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.TasksManager.Backend.Api.dll"] diff --git a/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled.aot b/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled.aot new file mode 100644 index 00000000..862cdb9a --- /dev/null +++ b/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled.aot @@ -0,0 +1,24 @@ +FROM mcr.microsoft.com/dotnet/nightly/runtime-deps:8.0-jammy-chiseled-aot AS base +WORKDIR /app +EXPOSE 5000 + +ENV ASPNETCORE_URLS=http://+:5000 + +USER app +FROM mcr.microsoft.com/dotnet/nightly/sdk:8.0-jammy-aot AS build +ARG configuration=Release +WORKDIR /src +COPY ["TasksTracker.TasksManager.Backend.Api/TasksTracker.TasksManager.Backend.Api.csproj", "TasksTracker.TasksManager.Backend.Api/"] +RUN dotnet restore "TasksTracker.TasksManager.Backend.Api/TasksTracker.TasksManager.Backend.Api.csproj" +COPY . . +WORKDIR "/src/TasksTracker.TasksManager.Backend.Api" +RUN dotnet build "TasksTracker.TasksManager.Backend.Api.csproj" -c $configuration -o /app/build + +FROM build AS publish +ARG configuration=Release +RUN dotnet publish "TasksTracker.TasksManager.Backend.Api.csproj" -c $configuration -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.TasksManager.Backend.Api.dll"] diff --git a/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile b/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile new file mode 100644 index 00000000..b60a9b20 --- /dev/null +++ b/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile @@ -0,0 +1,24 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 5000 + +ENV ASPNETCORE_URLS=http://+:5000 + +USER app +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG configuration=Release +WORKDIR /src +COPY ["TasksTracker.Processor.Backend.Svc/TasksTracker.Processor.Backend.Svc.csproj", "TasksTracker.Processor.Backend.Svc/"] +RUN dotnet restore "TasksTracker.Processor.Backend.Svc/TasksTracker.Processor.Backend.Svc.csproj" +COPY . . +WORKDIR "/src/TasksTracker.Processor.Backend.Svc" +RUN dotnet build "TasksTracker.Processor.Backend.Svc.csproj" -c $configuration -o /app/build + +FROM build AS publish +ARG configuration=Release +RUN dotnet publish "TasksTracker.Processor.Backend.Svc.csproj" -c $configuration -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.Processor.Backend.Svc.dll"] diff --git a/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled.aot b/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled.aot new file mode 100644 index 00000000..8db548e0 --- /dev/null +++ b/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled.aot @@ -0,0 +1,24 @@ +FROM mcr.microsoft.com/dotnet/nightly/runtime-deps:8.0-jammy-chiseled-aot AS base +WORKDIR /app +EXPOSE 5000 + +ENV ASPNETCORE_URLS=http://+:5000 + +USER app +FROM mcr.microsoft.com/dotnet/nightly/sdk:8.0-jammy-aot AS build +ARG configuration=Release +WORKDIR /src +COPY ["TasksTracker.Processor.Backend.Svc/TasksTracker.Processor.Backend.Svc.csproj", "TasksTracker.Processor.Backend.Svc/"] +RUN dotnet restore "TasksTracker.Processor.Backend.Svc/TasksTracker.Processor.Backend.Svc.csproj" +COPY . . +WORKDIR "/src/TasksTracker.Processor.Backend.Svc" +RUN dotnet build "TasksTracker.Processor.Backend.Svc.csproj" -c $configuration -o /app/build + +FROM build AS publish +ARG configuration=Release +RUN dotnet publish "TasksTracker.Processor.Backend.Svc.csproj" -c $configuration -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.Processor.Backend.Svc.dll"] diff --git a/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile b/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile new file mode 100644 index 00000000..d59ec115 --- /dev/null +++ b/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile @@ -0,0 +1,24 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 5000 + +ENV ASPNETCORE_URLS=http://+:5000 + +USER app +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build +ARG configuration=Release +WORKDIR /src +COPY ["TasksTracker.WebPortal.Frontend.Ui/TasksTracker.WebPortal.Frontend.Ui.csproj", "TasksTracker.WebPortal.Frontend.Ui/"] +RUN dotnet restore "TasksTracker.WebPortal.Frontend.Ui/TasksTracker.WebPortal.Frontend.Ui.csproj" +COPY . . +WORKDIR "/src/TasksTracker.WebPortal.Frontend.Ui" +RUN dotnet build "TasksTracker.WebPortal.Frontend.Ui.csproj" -c $configuration -o /app/build + +FROM build AS publish +ARG configuration=Release +RUN dotnet publish "TasksTracker.WebPortal.Frontend.Ui.csproj" -c $configuration -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.WebPortal.Frontend.Ui.dll"] diff --git a/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled.aot b/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled.aot new file mode 100644 index 00000000..f0d24b3d --- /dev/null +++ b/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled.aot @@ -0,0 +1,24 @@ +FROM mcr.microsoft.com/dotnet/nightly/runtime-deps:8.0-jammy-chiseled-aot AS base +WORKDIR /app +EXPOSE 5000 + +ENV ASPNETCORE_URLS=http://+:5000 + +USER app +FROM mcr.microsoft.com/dotnet/nightly/sdk:8.0-jammy-aot AS build +ARG configuration=Release +WORKDIR /src +COPY ["TasksTracker.WebPortal.Frontend.Ui/TasksTracker.WebPortal.Frontend.Ui.csproj", "TasksTracker.WebPortal.Frontend.Ui/"] +RUN dotnet restore "TasksTracker.WebPortal.Frontend.Ui/TasksTracker.WebPortal.Frontend.Ui.csproj" +COPY . . +WORKDIR "/src/TasksTracker.WebPortal.Frontend.Ui" +RUN dotnet build "TasksTracker.WebPortal.Frontend.Ui.csproj" -c $configuration -o /app/build + +FROM build AS publish +ARG configuration=Release +RUN dotnet publish "TasksTracker.WebPortal.Frontend.Ui.csproj" -c $configuration -o /app/publish /p:UseAppHost=false + +FROM base AS final +WORKDIR /app +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.WebPortal.Frontend.Ui.dll"] diff --git a/docs/aca/12-optimize-containers/index.md b/docs/aca/12-optimize-containers/index.md new file mode 100644 index 00000000..82d76bd7 --- /dev/null +++ b/docs/aca/12-optimize-containers/index.md @@ -0,0 +1,310 @@ +--- +canonical_url: 'https://azure.github.io/aca-dotnet-workshop' +--- + +# Module 12 - Container Optimization + +!!! info "Module Duration" + 45-60 minutes + +## Objective + +In this module, we will accomplish two objectives: + +1. Learn how to reduce container footprints. +1. Build & deploy updated, optimized images to Azure. + +## Module Sections + +--8<-- "snippets/restore-variables.md" + +### 1. Optimizing Containers + +Azure Container Apps makes it simple to quickly become effective with containers. But even a managed container platform requires hygiene and can benefit greatly from smaller containers. + +In this module, we will look into the benefits of optimized containers such as: + +- Smaller images to store and transfer to and from the container registry. +- Potentially less *Common Vulnerabilities and Exposures (CVEs)*. +- No bloat and unnecessary components such as shells, package managers, etc. + +While available prior to .NET 8, the general availability introduction of .NET 8 in November 2023 came with an expanded focus on container optimization and a move away from general-purpose containers. + +Please ensure you have the Docker daemon ready. Running *Docker Desktop* does it. + +#### 1.1 The Status Quo + +Let's focus on our first project, the Backend API. This is an ASP.NET Core application. + +Our original `Dockerfile` looks like this: + +=== "Backend.Api Dockerfile" +```Dockerfile +--8<-- "docs/aca/12-optimize-containers/Backend.Api.Dockerfile" +``` + +```shell +cd ~\TasksTracker.ContainerApps +``` + +```shell +docker build -t backend-api-status-quo -f .\TasksTracker.TasksManager.Backend.Api\Dockerfile . + +docker image list +``` + +This yields a sizable image at **222 MB**! + +![Backend API Status Quo](../../assets/images/12-optimize-containers/backend-api-status-quo.png) + +This image is comprised of two images, 452 packages, and has 19 vulnerabilities. + +![Backend API Status Quo Image Stats](../../assets/images/12-optimize-containers/backend-api-status-quo-image-stats.png) + +#### 1.2. Chiseled Images + +Microsoft and Ubuntu's creator, Canonical, collaborated on the concept of a [chiseled image for .NET](https://learn.microsoft.com/en-us/dotnet/core/docker/container-images#scenario-based-images){target=_blank}. Take a general-purpose base image and start chiseling away until you are left with an image that contains nothing more than the bare necessities to run your workload. No shell, no package manager, no bloat. + +=== "Backend.Api Dockerfile.chiseled" +```Dockerfile hl_lines="1 8" +--8<-- "docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled" +``` + +Create a new file, `Dockerfile.chiseled` in the Backend Api root directory, then build the image again: + +```shell +docker build -t backend-api-chiseled -f .\TasksTracker.TasksManager.Backend.Api\Dockerfile.chiseled . + +docker image list +``` + +Our image now stands at a much smaller **115 MB** - a drop of 107 MB and a size just 51.8% of the status quo image! + +![Backend API Chiseled](../../assets/images/12-optimize-containers/backend-api-chiseled.png) + +This image is comprised of one image, 331 packages, and has five vulnerabilities. + +![Backend API Status Quo Image Stats](../../assets/images/12-optimize-containers/backend-api-chiseled-image-stats.png) + +#### 1.3 Chiseled & Ahead-of-time (AOT) Compilation + +[Ahead-of-time (AOT) compilation](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot){target_blank} was first introduced with .NET 7. AOT compiles the application to native code instead of Intermediate Language (IL). This means that we must have foresight as to what platform will be hosting the application. Our process is simplified by the fact that containers in Azure Container Apps are only Linux-hosted. By using native code, we will bypass the just-in-time (JIT) compiler when the container executes, which means we will have faster startup and a smaller memory footprint. It also means these images can run in environments where JIT compilation may not be permitted. + +=== "Backend.Api Dockerfile.chiseled.aot" +```Dockerfile hl_lines="1 8" +--8<-- "docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled.aot" +``` + +Create a new file, `Dockerfile.chiseled.aot` in the Backend Api root directory, then build the image again: + +```shell +docker build -t backend-api-chiseled-aot -f .\TasksTracker.TasksManager.Backend.Api\Dockerfile.chiseled.aot . + +docker image list +``` + +!!! note "Nightly Images" + + As the name implies, these images are produced nightly. They are not yet images that are versioned and stable in the registry. Your mileage may vary. + +Another massive reduction takes the image down to a mere **16 MB** - a total drop of 206 MB and a size just 7.2% of the status quo image! + +![Backend API Chiseled AOT](../../assets/images/12-optimize-containers/backend-api-chiseled-aot.png) + +This image is comprised of one image, just 23 packages, and has nine vulnerabilities. +Notably, the four additional vulnerabilities are in the `openssl 3.0.2` package in this image. + +![Backend API Status Quo Image Stats](../../assets/images/12-optimize-containers/backend-api-chiseled-aot-image-stats.png) + +#### 1.4 Deploying the new Status Quo + +While the image is vastly reduced, what hasn't changed is the functionality of the API. Whether you are executing it locally or deploying to Azure, the Backend API will continue to function as it always has. However, now it has less vulnerabilities, less time to transfer from the registry, less startup time, and less of a memory footprint. Furthermore, 16 MB is the uncompressed image. With compression, we are likely to continue dropping in size. + +Let's update our existing Backend API container app with a new build and revision: + +```shell hl_lines="6" +## Build Backend Service on ACR and Push to ACR + +az acr build ` +--registry $AZURE_CONTAINER_REGISTRY_NAME ` +--image "tasksmanager/$BACKEND_API_NAME" ` +--file 'TasksTracker.TasksManager.Backend.Api/Dockerfile.chiseled.aot' . + +# Update Backend API App container app and create a new revision +az containerapp update ` +--name $BACKEND_API_NAME ` +--resource-group $RESOURCE_GROUP ` +--revision-suffix v$TODAY-6 ` +--set-env-vars "ApplicationInsights__InstrumentationKey=secretref:appinsights-key" +``` + +Verify that the application continues to work: + +```shell +$FRONTEND_UI_BASE_URL +``` + +### 2. Optimizing Frontend UI & Backend Service Containers + +As all three projects use ASP.NET Core, we can follow the same approach with these two projects as well.how much you are able to reduce! + +#### 2.1 Frontend UI + +#### 2.1.1 The Status Quo + +Our original `Dockerfile` looks like this: + +=== "Frontend.Ui Dockerfile" +```Dockerfile +--8<-- "docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile" +``` + +```shell +cd ~\TasksTracker.ContainerApps +``` + +```shell +docker build -t frontend-ui-status-quo -f .\TasksTracker.WebPortal.Frontend.Ui\Dockerfile . + +docker image list +``` + +This yields an image size of **227 MB**. + +#### 2.1.2 Chiseled & Ahead-of-time (AOT) Compilation + +Skipping straight to AOT images: + +=== "Frontend.Ui Dockerfile.chiseled.aot" +```Dockerfile hl_lines="1 8" +--8<-- "docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled.aot" +``` + +Create a new file, `Dockerfile.chiseled.aot` in the Frontend Ui root directory, then build the image again: + +```shell +docker build -t frontend-ui-chiseled-aot -f .\TasksTracker.WebPortal.Frontend.Ui\Dockerfile.chiseled.aot . + +docker image list +``` + +This much-improved image is now **20.6 MB**. + +#### 2.2 Backend Service + +#### 2.2.1 The Status Quo + +Our original `Dockerfile` looks like this: + +=== "Backend.Svc Dockerfile" +```Dockerfile +--8<-- "docs/aca/12-optimize-containers/Backend.Svc.Dockerfile" +``` + +```shell +cd ~\TasksTracker.ContainerApps +``` + +```shell +docker build -t backend-svc-status-quo -f .\TasksTracker.Processor.Backend.Svc\Dockerfile . + +docker image list +``` + +This yields an image size of **222 MB**. + +#### 2.2.2 Chiseled & Ahead-of-time (AOT) Compilation + +Skipping straight to AOT images: + +=== "Backend.Svc Dockerfile.chiseled.aot" +```Dockerfile hl_lines="1 8" +--8<-- "docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled.aot" +``` + +Create a new file, `Dockerfile.chiseled.aot` in the Backend Svc root directory, then build the image again: + +```shell +docker build -t backend-svc-chiseled-aot -f .\TasksTracker.Processor.Backend.Svc\Dockerfile.chiseled.aot . + +docker image list +``` + +This much-improved image is now **16 MB**. + +### 3. Optimization Summary + +#### 3.1 Table of Improvements + +The Backend API and the Backend Svc projects are all but identical while the Frontend UI project is just slightly larger. All three projects were cut down to less than 10% of their original size! + +| | Image Size | Size Reduction | Size compared to Original | Packages | CVEs | +|----------------------------|-----------:|---------------:|--------------------------:|---------:|-----:| +| Backend API Original | 222 MB | | | 452 | 19 | +| Backend API Chiseled & AOT | 16 MB | 206 MB | 7.2% | 23 | 9 | +| Frontend UI Original | 226 MB | | | 447 | 19 | +| Frontend UI Chiseled & AOT | 21 MB | 205 MB | 9.3% | 18 | 9 | +| Backend Svc Original | 222 MB | | | 452 | 19 | +| Backend Svc Chiseled & AOT | 16 MB | 206 MB | 7.2% | 23 | 9 | + +#### 3.2 Build & Deploy All Services + +The last step is to build & deploy updated images. For good measure, let's do the Backend API as well even though we did it earlier already. + +```shell hl_lines="5 11 17" +# Build Backend API on ACR and Push to ACR +az acr build ` +--registry $AZURE_CONTAINER_REGISTRY_NAME ` +--image "tasksmanager/$BACKEND_API_NAME" ` +--file 'TasksTracker.TasksManager.Backend.Api/Dockerfile.chiseled.aot' . + +# Build Backend Service on ACR and Push to ACR +az acr build ` +--registry $AZURE_CONTAINER_REGISTRY_NAME ` +--image "tasksmanager/$BACKEND_SERVICE_NAME" ` +--file 'TasksTracker.Processor.Backend.Svc/Dockerfile.chiseled.aot' . + +# Build Frontend Web App on ACR and Push to ACR +az acr build ` +--registry $AZURE_CONTAINER_REGISTRY_NAME ` +--image "tasksmanager/$FRONTEND_WEBAPP_NAME" ` +--file 'TasksTracker.WebPortal.Frontend.Ui/Dockerfile.chiseled.aot' . +``` + +```shell +# Update Backend API App container app and create a new revision +az containerapp update ` +--name $BACKEND_API_NAME ` +--resource-group $RESOURCE_GROUP ` +--revision-suffix v$TODAY-7 ` +--set-env-vars "ApplicationInsights__InstrumentationKey=secretref:appinsights-key" + +# Update Frontend Web App container app and create a new revision +az containerapp update ` +--name $FRONTEND_WEBAPP_NAME ` +--resource-group $RESOURCE_GROUP ` +--revision-suffix v$TODAY-7 ` +--set-env-vars "ApplicationInsights__InstrumentationKey=secretref:appinsights-key" + +# Update Backend Background Service container app and create a new revision +az containerapp update ` +--name $BACKEND_SERVICE_NAME ` +--resource-group $RESOURCE_GROUP ` +--revision-suffix v$TODAY-7 ` +--set-env-vars "ApplicationInsights__InstrumentationKey=secretref:appinsights-key" +``` + +Verify that the application continues to work with the three much smaller containers: + +```shell +$FRONTEND_UI_BASE_URL +``` + +--8<-- "snippets/persist-state.md:module12" + +## Review + +In this module, we have accomplished two objectives: + +1. Learned how to reduce container footprints. +1. Built & deployed updated, optimized images to Azure. diff --git a/docs/aca/12-about-the-authors/index.md b/docs/aca/29-about-the-authors/index.md similarity index 100% rename from docs/aca/12-about-the-authors/index.md rename to docs/aca/29-about-the-authors/index.md diff --git a/docs/aca/13-appendix/01-run-debug-dapr-app-vscode.md b/docs/aca/30-appendix/01-run-debug-dapr-app-vscode.md similarity index 98% rename from docs/aca/13-appendix/01-run-debug-dapr-app-vscode.md rename to docs/aca/30-appendix/01-run-debug-dapr-app-vscode.md index 690de23d..3dee98b0 100644 --- a/docs/aca/13-appendix/01-run-debug-dapr-app-vscode.md +++ b/docs/aca/30-appendix/01-run-debug-dapr-app-vscode.md @@ -24,7 +24,7 @@ To accomplish this, open file `launch.json` and add the two configurations shown === "launch.json" ```json - --8<-- "docs/aca/13-appendix/launch.json" + --8<-- "docs/aca/30-appendix/launch.json" ``` !!! note @@ -43,7 +43,7 @@ Now we will add 4 tasks, for each application, there will be a task to support t === "tasks.json" ```json - --8<-- "docs/aca/13-appendix/tasks.json" + --8<-- "docs/aca/30-appendix/tasks.json" ``` ??? tip "Curious to learn more about the tasks.json file above?" diff --git a/docs/aca/13-appendix/02-github-local-codespaces.md b/docs/aca/30-appendix/02-github-local-codespaces.md similarity index 100% rename from docs/aca/13-appendix/02-github-local-codespaces.md rename to docs/aca/30-appendix/02-github-local-codespaces.md diff --git a/docs/aca/13-appendix/03-variables.md b/docs/aca/30-appendix/03-variables.md similarity index 96% rename from docs/aca/13-appendix/03-variables.md rename to docs/aca/30-appendix/03-variables.md index 8abf365e..bc0a6446 100644 --- a/docs/aca/13-appendix/03-variables.md +++ b/docs/aca/30-appendix/03-variables.md @@ -13,7 +13,7 @@ Execute this script to persist all variables in the current session at any time. === "Set-Variables.ps1" ```powershell - --8<-- "docs/aca/13-appendix/Set-Variables.ps1" + --8<-- "docs/aca/30-appendix/Set-Variables.ps1" ``` ## Restoring Variables diff --git a/docs/aca/13-appendix/Set-Variables.ps1 b/docs/aca/30-appendix/Set-Variables.ps1 similarity index 100% rename from docs/aca/13-appendix/Set-Variables.ps1 rename to docs/aca/30-appendix/Set-Variables.ps1 diff --git a/docs/aca/13-appendix/launch.json b/docs/aca/30-appendix/launch.json similarity index 100% rename from docs/aca/13-appendix/launch.json rename to docs/aca/30-appendix/launch.json diff --git a/docs/aca/13-appendix/tasks.json b/docs/aca/30-appendix/tasks.json similarity index 100% rename from docs/aca/13-appendix/tasks.json rename to docs/aca/30-appendix/tasks.json diff --git a/docs/assets/images/12-optimize-containers/backend-api-chiseled-aot-image-stats.png b/docs/assets/images/12-optimize-containers/backend-api-chiseled-aot-image-stats.png new file mode 100644 index 0000000000000000000000000000000000000000..0c2de8da0eddb81c9c23a07d5b81036e73831346 GIT binary patch literal 25578 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 literal 0 HcmV?d00001 diff --git a/docs/assets/images/12-optimize-containers/backend-api-chiseled-aot.png b/docs/assets/images/12-optimize-containers/backend-api-chiseled-aot.png new file mode 100644 index 0000000000000000000000000000000000000000..27051d426f165bf5323b273e06b38c6a6425055d GIT binary patch literal 4421 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

b$cq9)G$YXuKZsd(d~hPd!x zoRPe{OA8Ajfjwdq3lu@8Hfol4JNVvzn!YwXscHEhanPGDQ;TLZC$W3xnk;c3oo=d) zG4{Rslj--^H}ukd-g$qrZ+5nKa&mBTGCuVRt6Y6~$*p?-_k-*4+`ev#*WzM9qJ#(J zVF2gSgg&$MxOuo-RL-Em2Xy{Um8phxaWTljX60`xKL?k1+mrS}>!)rdJ|d#C!@!&5 z<0+r>gT>PA-^{41LR?9vP!A4uG5`wFsTva-TbnNeCZXz&g_>c#`I0W_Gc>u6c4)}+ z-Dl|j9e?>TqHLe&T@@d3Y#xn?^mVMP#u#c&9{9j%D577W6 zyqKDaSH3QbJIYmi5GOoZXY8;QL-PHdZ-1Gmzssalb5l|>(Kmb*R(`2V5L5ES@{SbX ztI4V#r4y4*3Q10@Qr`T zbbkYZ(kI}qOkd$O6urp$!Rpzz3-}ax{%IsQLMJo&>q)WF<_^V!W2HM`lzwFfqvXjS z1OkYG;T-)2&CXsM->Y&D3fzjmQsSYS(G>8|AZX`BmV- zU-PvG+W1NXGUM9V2!&Ixy~pq+>a`=m^of{%b?L{j>5GCc4#7GBYDylLhU39VFY&{+ zZ}~y;oHGLmMeP#FVn!+H*_7xs@g2sdtlxOT?2`L=MgiT7>hu!3K!O(qq}B7=t_E%*B-XX$byPN9rXn(QKIPIv ziVhcO?=UW_?P9gdcC39uv|o)FI5HvCYOAZ`c`(vaCnhH5=jW&MZ}e!m>nt_7Md^*$ z22Yh}Rs=DO$uKt(#rl@r57%5Yi3TwajDOynW)QL6+L`oE1-0qIF=A%}Q+Ek(Kg1@= z)RM0saLcX>P5TH7kXd1c{=6*YjdVSs?PY?fMM`84vJcMBu`&NZsd|?uz$VB#yL3PG zMw@mJEnP-?lB>x`6~FUyRQRubQw5RaiUF+~?l)zwXa)@W7Z@bQ%2d)i%?81FvkiX& zmiWj-qPhFQZr!ZOmV&kld`%&5_Z4Ud9cwcwjYQswP|C-8pG{Y+hej)Q*#qxO5Ox{C5?7Q%y%Zl z3kF791d(#|Wip7Srwmc--vaD4(bEH;j6PvW`rd*8d( zyIv>II6?bCy-S{!8|X2Wi^IeG;TTo#ruyWZtN|_D8sfL!(gs}7z0<)mY*h2u>AR*Cjl2^_u;g z3mx-bXB7DC5XD+eG&2!7@h+>{<`$Q>K2toy#nQ~?7&4PL6SJctPakAb$}hiJ98zcM zt4CR*_G*t|A-=sK*#~te^5=5H9;Noo?3wEX>C`qRt%DDc%283m_>0@5^JA$U@nIhQ zty*LaTU*UrU^LbAnP=7VABBiACwxQT8w zEbWSi`&$$-YR(_K<1&h5P*&y+aq6keB5Novgt3jc?9Yt+1p}$>z&xbbJ!9}aHrKOD z2uX}5jUQ2s%N{`!m?Y@K%go$|_S|<)VyLuZL|z+$vvVQ5FofD+SeQxX@Ji?iFcw!h zQ4bftrQnm|`0x2ypTbBA&5617{iOI7!O5Pbh|O?!koUfXADwne+RWv*H$sM)ye;W- z4dR!|zpC`<3XQ2b$xBy7Vo1BUF?}ZIQvH1v1%2?vEgslRC@;{;{mAPsFX)B%3m^|x zk<1n>VDqBU&ZED^{{(=3d}0fPwg8~MoiO^8Sv;U#+*MS9ikM!|- zM@q0YIO+97O7jxQYzE>`wB{-414~wgkyF(cJ-24muw3ooS1b7;$RtwG^iO6PR(M~m zPytSRtZNst=UC9*8d*vT>0euYq9mW>A)1UgLt?u6)4w3K>?Q?VP(v28c3_Yha-?Zz zblf`KHEI}tbmlF7dTD6X!cbyt9gF6iopv( +{*whBncMIYLeAGOx)4^|S+d)>Q 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 F{{?|F`~3g_ literal 0 HcmV?d00001 diff --git a/docs/assets/images/12-optimize-containers/backend-api-chiseled.png b/docs/assets/images/12-optimize-containers/backend-api-chiseled.png new file mode 100644 index 0000000000000000000000000000000000000000..a523364fea2aa8cf2bbcbfe5ec65569e054599a7 GIT binary patch literal 3725 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 DzG^Kp literal 0 HcmV?d00001 diff --git a/docs/assets/images/12-optimize-containers/backend-api-status-quo-image-stats.png b/docs/assets/images/12-optimize-containers/backend-api-status-quo-image-stats.png new file mode 100644 index 0000000000000000000000000000000000000000..059223ee49368124e1da2e288e3d5f9239807923 GIT binary patch literal 25953 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 Xxl`O6!1~)i{skpDb=mSaAHMuA`lh@^ literal 0 HcmV?d00001 diff --git a/docs/assets/images/12-optimize-containers/backend-api-status-quo.png b/docs/assets/images/12-optimize-containers/backend-api-status-quo.png new file mode 100644 index 0000000000000000000000000000000000000000..f1fb748df87422ffcc06e9d706310281a7b716b8 GIT binary patch literal 2651 zcmV-h3Z(UkP)Px#1ZP1_K>z@;j|==^1poj59#BkFMGOoKl$4ar%*<3&R5Ua+ZEbC&q@;s`gSWT0 z{{R3lIF982000SaNLh0L01|Tm01|Tnj3T)Q000TbNkl?#GDXskqY2N9{w%Z_wCH zW*dr&Ycwt#*TvwA@|2e6f!z)5#{DsWcV!uCKq<=W`j?G)DWJ)+bjjsxdPUcF^S_u$ zdC(GIwXWl=%Q^*_)69&I+J_<^9^;bEGFu3_aQ*!dYK}%sxvOc+=401pPO2GWG>vt6 z>3ZyO_-S4X)}+5W?ac7&k$3ZTvECoFgeZ-sTR*4D+J}(eps}0G7D6sue=>K_NG1D2 zZ>C@MCc1Lan0;hV28zz$279yhltX&=ck_Qw|Fb=432_=v$NS|Dxtj$vviv5EU1YWq za$zR3D2+plxLzQrj@(P@v#(gwh;r07!%zO^UJ2G@@-g`^lldd>=KnhX>S$CFV70D; zPxXGe;}xaahmh}wAu8!AvyG4o7ZMwq8%%NLo<^SHII_+5Y%)8mU!@e~sPE{0={&X4 zWIc7CW;Qo#d+7RZ{*Tq%(WoTEY3wp}L%7pEg#0FrPfiB|E+_&-Y1|3lSa1l9&hC|o z(@6brJ2x)|Ym)EWnEW7(oATgjR1)Gr^)VW~4BU*iMOnmY?0*F`*3E9G z(J4;ftNB`F*qLy_geEAD&`57-3Ew!yseIU%aQB^4974qfe>w4)YN2Vw!h&)X3Ze^+ z;%Ct~=4CHA?@=1Hgy$C=gL=UsJ{-%!{5uyMgo+D}&rurJ2TdcE`D5CvI!2fOir!bk zkIydPUk(q`s3m;E@;{g5f8|4w|EIluo<_&DEV_} zq^Xy46m6w-2~*gNV;Z#tSgq?kxEZH>DDvx>>f!m#IL!s;7lGykQekKV8nHFL<=CKU z#MU_1|5-HVQv~3w*B#!TtYDej{T`PZs%ps|e~Mxz-$PUD4s@*|@cl9$wwU46cR!8Go4eL==oM=n=> zG(6EmN$*5=8lkyPaUW&KKPUg+&^WaGXYRQ2dHzFiG|~^^Y~3ZO?**TmB^vgxpH+G% z9-tALs}%Q9=p^OkC^T;Am*o*Y#Wj6%C3jjwF=nuw*fWKcdDS@A9DMRy6I*`-e0ghx z(*j%vdHPIFga?Qafzolv9lRDx~t`pFR%XU@Gyr|3X{g9bPB^eq9?OuCx=8qVb z8|0nAdN{|-%#dj0TLJ|g+Ovl~-KpF3DkpKx0iB#Lf{=XKnZFqcZji=#p-Y|` zZm}3!p>be$eS2q+VH&k$)-Y)I+M5fU;vr>_M=Ev=S8 zmWpmH0X7DnRNjC^D35r<(+EdbDej|SoD>?VW71P{Huu@`pYBr`JH@jDJOZUggxbpIWcwo

2-!#9LBjk;tfw@Sp+HWqfk&S zj}?vC8F#6qZs(mUsD-}!6s&%6|O=;z0g+^J`Ky9um>qb{@{U?s~4=sH*B8~Hu&`edWh5~^