diff --git a/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled b/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled index 86d1e5f1..c17d1f56 100644 --- a/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled +++ b/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled @@ -5,20 +5,11 @@ EXPOSE 8080 ENV ASPNETCORE_URLS=http://+:8080 USER app -FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy AS build -ARG configuration=Release +FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy AS publish 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 +RUN dotnet publish -o /app/publish FROM base AS final -WORKDIR /app COPY --from=publish /app/publish . -ENTRYPOINT ["dotnet", "TasksTracker.TasksManager.Backend.Api.dll"] +ENTRYPOINT ["dotnet", "TasksTracker.TasksManager.Backend.Api.dll"] \ No newline at end of file diff --git a/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled.aot b/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled.aot deleted file mode 100644 index 33737fb0..00000000 --- a/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled.aot +++ /dev/null @@ -1,24 +0,0 @@ -FROM mcr.microsoft.com/dotnet/nightly/runtime-deps:8.0-jammy-chiseled-aot AS base -WORKDIR /app -EXPOSE 8080 - -ENV ASPNETCORE_URLS=http://+:8080 - -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.Api.Dockerfile.concise b/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.concise new file mode 100644 index 00000000..cc4d8ab4 --- /dev/null +++ b/docs/aca/12-optimize-containers/Backend.Api.Dockerfile.concise @@ -0,0 +1,15 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 8080 + +ENV ASPNETCORE_URLS=http://+:8080 + +USER app +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS publish +WORKDIR /src +COPY . . +RUN dotnet publish -o /app/publish + +FROM base AS final +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.TasksManager.Backend.Api.dll"] \ No newline at end of file diff --git a/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled b/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled new file mode 100644 index 00000000..1771b846 --- /dev/null +++ b/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled @@ -0,0 +1,15 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled AS base +WORKDIR /app +EXPOSE 8080 + +ENV ASPNETCORE_URLS=http://+:8080 + +USER app +FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy AS publish +WORKDIR /src +COPY . . +RUN dotnet publish -o /app/publish + +FROM base AS final +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.Processor.Backend.Svc.dll"] \ No newline at end of file diff --git a/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled.aot b/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled.aot deleted file mode 100644 index 893be3c7..00000000 --- a/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled.aot +++ /dev/null @@ -1,24 +0,0 @@ -FROM mcr.microsoft.com/dotnet/nightly/runtime-deps:8.0-jammy-chiseled-aot AS base -WORKDIR /app -EXPOSE 8080 - -ENV ASPNETCORE_URLS=http://+:8080 - -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/Backend.Svc.Dockerfile.concise b/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.concise new file mode 100644 index 00000000..40baa9c0 --- /dev/null +++ b/docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.concise @@ -0,0 +1,15 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 8080 + +ENV ASPNETCORE_URLS=http://+:8080 + +USER app +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS publish +WORKDIR /src +COPY . . +RUN dotnet publish -o /app/publish + +FROM base AS final +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.Processor.Backend.Svc.dll"] \ No newline at end of file diff --git a/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled b/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled new file mode 100644 index 00000000..86125801 --- /dev/null +++ b/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled @@ -0,0 +1,15 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0-jammy-chiseled AS base +WORKDIR /app +EXPOSE 8080 + +ENV ASPNETCORE_URLS=http://+:8080 + +USER app +FROM mcr.microsoft.com/dotnet/sdk:8.0-jammy AS publish +WORKDIR /src +COPY . . +RUN dotnet publish -o /app/publish + +FROM base AS final +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.WebPortal.Frontend.Ui.dll"] \ No newline at end of file diff --git a/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled.aot b/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled.aot deleted file mode 100644 index 9af28f90..00000000 --- a/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled.aot +++ /dev/null @@ -1,24 +0,0 @@ -FROM mcr.microsoft.com/dotnet/nightly/runtime-deps:8.0-jammy-chiseled-aot AS base -WORKDIR /app -EXPOSE 8080 - -ENV ASPNETCORE_URLS=http://+:8080 - -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/Frontend.Ui.Dockerfile.concise b/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.concise new file mode 100644 index 00000000..9f9bdb9c --- /dev/null +++ b/docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.concise @@ -0,0 +1,15 @@ +FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base +WORKDIR /app +EXPOSE 8080 + +ENV ASPNETCORE_URLS=http://+:8080 + +USER app +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS publish +WORKDIR /src +COPY . . +RUN dotnet publish -o /app/publish + +FROM base AS final +COPY --from=publish /app/publish . +ENTRYPOINT ["dotnet", "TasksTracker.WebPortal.Frontend.Ui.dll"] \ No newline at end of file diff --git a/docs/aca/12-optimize-containers/index.md b/docs/aca/12-optimize-containers/index.md index 7cdae4f0..53810940 100644 --- a/docs/aca/12-optimize-containers/index.md +++ b/docs/aca/12-optimize-containers/index.md @@ -30,277 +30,183 @@ In this module, we will look into the benefits of optimized containers such as: 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. You can apply similar steps for .NET versions newer than 8, but we omit them here for brevity. +**For .NET 9, replace `8.0-jammy` with `9.0-noble`.** + 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: +Our original `Dockerfile` files look like this: === "Backend.Api Dockerfile" -```Dockerfile ---8<-- "docs/aca/12-optimize-containers/Backend.Api.Dockerfile" -``` + ```Dockerfile + --8<-- "docs/aca/12-optimize-containers/Backend.Api.Dockerfile" + ``` + +=== "Backend.Svc Dockerfile" + ```Dockerfile + --8<-- "docs/aca/12-optimize-containers/Backend.Svc.Dockerfile" + ``` + +=== "Frontend.Ui Dockerfile" + ```Dockerfile + --8<-- "docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile" + ``` ```shell cd ~\TasksTracker.ContainerApps -``` -```shell docker build -t backend-api-status-quo -f .\TasksTracker.TasksManager.Backend.Api\Dockerfile . +docker build -t backend-svc-status-quo -f .\TasksTracker.Processor.Backend.Svc\Dockerfile . +docker build -t frontend-ui-status-quo -f .\TasksTracker.WebPortal.Frontend.Ui\Dockerfile . docker image list ``` -This yields a sizable image at **222 MB**! +This yields sizable images at **226+ MB**! -![Backend API Status Quo](../../assets/images/12-optimize-containers/backend-api-status-quo.png) +![Docker Status Quo](../../assets/images/12-optimize-containers/docker-status-quo.png) -This image is comprised of two images, 452 packages, and has 19 vulnerabilities. +For example, the Backend API 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 +#### 1.2 More Concise Dockerfile -Microsoft and Ubuntu's creator, Canonical, collaborated on the concept of a [chiseled image for .NET](https://learn.microsoft.com/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. +The VS Code Docker extension produces a Dockerfile that's helpful for development but not as ideal for creation of production containers. We can significantly simplify and streamline the files (note that `publish` builds for `Release` by default, so we don't need to declare the configuration). These changes do not immediately impact image size yet. -=== "Backend.Api Dockerfile.chiseled" -```Dockerfile hl_lines="1 8" ---8<-- "docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled" -``` +=== "Concise Backend.API Dockerfile" + ```Dockerfile + --8<-- "docs/aca/12-optimize-containers/Backend.Api.Dockerfile.concise" + ``` -Create a new file, `Dockerfile.chiseled` in the Backend Api root directory, then build the image again: +=== "Concise Backend.Svc Dockerfile" + ```Dockerfile + --8<-- "docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.concise" + ``` + +=== "Concise Frontend.Ui Dockerfile" + ```Dockerfile + --8<-- "docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.concise" + ``` + +Create three new files, `Dockerfile.concise` in each of their respective directories, then run the following commands from the project root directory to build the concise images. All images will build, but they will continue to essentially be identical to the status quo images. ```shell -docker build -t backend-api-chiseled -f .\TasksTracker.TasksManager.Backend.Api\Dockerfile.chiseled . +docker build -t backend-api-concise -f .\TasksTracker.TasksManager.Backend.Api\Dockerfile.concise .\TasksTracker.TasksManager.Backend.Api +docker build -t backend-svc-concise -f .\TasksTracker.Processor.Backend.Svc\Dockerfile.concise .\TasksTracker.Processor.Backend.Svc +docker build -t frontend-ui-concise -f .\TasksTracker.WebPortal.Frontend.Ui\Dockerfile.concise .\TasksTracker.WebPortal.Frontend.Ui 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) +#### 1.3 Chiseled Images -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) +Microsoft and Ubuntu's creator, Canonical, collaborated on the concept of a [chiseled image for .NET](https://learn.microsoft.com/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. -#### 1.3 Chiseled & Ahead-of-time (AOT) Compilation +=== "Chiseled Backend.API Dockerfile" + ```Dockerfile + --8<-- "docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled" + ``` -[Ahead-of-time (AOT) compilation](https://learn.microsoft.com/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. +=== "Chiseled Backend.Svc Dockerfile" + ```Dockerfile + --8<-- "docs/aca/12-optimize-containers/Backend.Svc.Dockerfile.chiseled" + ``` -=== "Backend.Api Dockerfile.chiseled.aot" -```Dockerfile hl_lines="1 8" ---8<-- "docs/aca/12-optimize-containers/Backend.Api.Dockerfile.chiseled.aot" -``` +=== "Concise Frontend.Ui Dockerfile" + ```Chiseled + --8<-- "docs/aca/12-optimize-containers/Frontend.Ui.Dockerfile.chiseled" + ``` -Create a new file, `Dockerfile.chiseled.aot` in the Backend Api root directory, then build the image again: +Create three new files, `Dockerfile.chiseled` in each of their respective directories, then run the following commands from the project root directory to build the chiseled images: ```shell -docker build -t backend-api-chiseled-aot -f .\TasksTracker.TasksManager.Backend.Api\Dockerfile.chiseled.aot . +docker build -t backend-api-chiseled -f .\TasksTracker.TasksManager.Backend.Api\Dockerfile.chiseled .\TasksTracker.TasksManager.Backend.Api +docker build -t backend-svc-chiseled -f .\TasksTracker.Processor.Backend.Svc\Dockerfile.chiseled .\TasksTracker.Processor.Backend.Svc +docker build -t frontend-ui-chiseled -f .\TasksTracker.WebPortal.Frontend.Ui\Dockerfile.chiseled .\TasksTracker.WebPortal.Frontend.Ui 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. +**Our images are half of their original size now!** -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! +![Docker Chiseled](../../assets/images/12-optimize-containers/docker-chiseled.png) -![Backend API Chiseled AOT](../../assets/images/12-optimize-containers/backend-api-chiseled-aot.png) +This image is comprised of one image, 331 packages, and has five vulnerabilities. -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-image-stats.png) -![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 +#### 1.4 Deploying the Updated Images 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 +## Build ACR and Update the Container Apps 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: +--file 'TasksTracker.TasksManager.Backend.Api/Dockerfile.chiseled' .\TasksTracker.TasksManager.Backend.Api -```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' . +--file 'TasksTracker.Processor.Backend.Svc/Dockerfile.chiseled' .\TasksTracker.Processor.Backend.Svc -# 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' . -``` +--file 'TasksTracker.WebPortal.Frontend.Ui/Dockerfile.chiseled' .\TasksTracker.WebPortal.Frontend.Ui -```shell -# Update Backend API App container app and create a new revision +# Update all container apps az containerapp update ` ---name $BACKEND_API_NAME ` +--name $BACKEND_API_NAME ` --resource-group $RESOURCE_GROUP ` ---revision-suffix v$TODAY-7 ` +--revision-suffix v$TODAY-6 ` --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 ` +--name $BACKEND_SERVICE_NAME ` --resource-group $RESOURCE_GROUP ` ---revision-suffix v$TODAY-7 ` +--revision-suffix v$TODAY-6 ` --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 ` +--name $FRONTEND_WEBAPP_NAME ` --resource-group $RESOURCE_GROUP ` ---revision-suffix v$TODAY-7 ` +--revision-suffix v$TODAY-6 ` --set-env-vars "ApplicationInsights__InstrumentationKey=secretref:appinsights-key" ``` -Verify that the application continues to work with the three much smaller containers: +Verify that the application continues to work: ```shell $FRONTEND_UI_BASE_URL ``` ---8<-- "snippets/persist-state.md:module12" +### 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 significantly in size! + +| | Image Size | Size Reduction | Size compared to Original | Images | Packages | CVEs | +|----------------------------|-----------:|---------------:|--------------------------:|-------:|---------:|-----:| +| Backend API Status Quo | 226 MB | | | 2 | 451 | 25 | +| Backend API Concise | 226 MB | 0 MB | | 2 | 451 | 25 | +| Backend API Chiseled | 119 MB | 107 MB | 56.6% | 1 | 328 | 2 | +| Frontend UI Status Quo | 239 MB | | | 2 | 449 | 25 | +| Frontend UI Concise | 240 MB | -1 MB | | 2 | 449 | 25 | +| Frontend UI Chiseled | 133 MB | 106 MB | 55.6% | 1 | 326 | 2 | +| Backend Svc Status Quo | 226 MB | | | 2 | 451 | 25 | +| Backend Svc Concise | 226 MB | 0 MB | | 2 | 451 | 25 | +| Backend Svc Chiseled | 119 MB | 107 MB | 56.6% | 1 | 328 | 2 | ## Review 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 deleted file mode 100644 index 0c2de8da..00000000 Binary files a/docs/assets/images/12-optimize-containers/backend-api-chiseled-aot-image-stats.png and /dev/null differ 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 deleted file mode 100644 index 27051d42..00000000 Binary files a/docs/assets/images/12-optimize-containers/backend-api-chiseled-aot.png and /dev/null differ diff --git a/docs/assets/images/12-optimize-containers/backend-api-chiseled-image-stats.png b/docs/assets/images/12-optimize-containers/backend-api-chiseled-image-stats.png index 44719a37..5fb31cf2 100644 Binary files a/docs/assets/images/12-optimize-containers/backend-api-chiseled-image-stats.png and b/docs/assets/images/12-optimize-containers/backend-api-chiseled-image-stats.png differ 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 index 059223ee..e11c7d78 100644 Binary files a/docs/assets/images/12-optimize-containers/backend-api-status-quo-image-stats.png and b/docs/assets/images/12-optimize-containers/backend-api-status-quo-image-stats.png differ diff --git a/docs/assets/images/12-optimize-containers/docker-chiseled.png b/docs/assets/images/12-optimize-containers/docker-chiseled.png new file mode 100644 index 00000000..beba5c94 Binary files /dev/null and b/docs/assets/images/12-optimize-containers/docker-chiseled.png differ diff --git a/docs/assets/images/12-optimize-containers/docker-status-quo.png b/docs/assets/images/12-optimize-containers/docker-status-quo.png new file mode 100644 index 00000000..b219e0a8 Binary files /dev/null and b/docs/assets/images/12-optimize-containers/docker-status-quo.png differ