Determine the Azure Container App memory usage

To determine how much memory the Azure Container App needs, we can use the Metrics feature. To monitor the resource usage

  • Log into the Azure Portal at https://portal.azure.com
  • Open the Container Apps page, and select the application
  • On left in the Monitoring menu select Metrics
  • Click the Add metric button and select the Memory Working Set Bytes and Max value

Pass environment variables to Azure Container Apps

To pass secrets, configuration values to Azure Container Apps we can use the Azure CLI or the Azure Portal.

To pass an environment variable value to toe Azure Container App using the Azure CLI execute the command in a terminal

az containerapp update --name <app-name> --resource-group <rg> \
  --set-env-vars NODE_OPTIONS="--max-old-space-size=4096"

To use the Azure Portal web interface

  • Log into the Azure Portal at https://portal.azure.com
  • On the Container Apps page select the application
  • In the Application, Containers, page open the Environment variables tab and add a new environment variable. Click the Save as a new revision button

Deploy the new version of the application in Azure Container Apps

Azure Container Apps (ACA) run containers in a serverless environment with zero environment maintenance requirement. To deploy a new application in Azure Container Apps follow the steps at Deploy a web application in Azure Container Apps (ACA)

To deploy a new version of the same app in Azure Container Apps

  • Log in to the Azure Portal at https://portal.azure.com
  • In the top search bar search for container apps and select Container Apps in the list
  • In the application list click the name of the application
  • In the Application menu select Revisions and Replicas
  • Click the Create new revision button
  • Select a prior revision as a base configuration, enter a name for the new provision, and select the container image. Click the Next: Scale button
  • If you always want to have at least one replica running for immediate availability, select 1 for Min replicas. If volumes are needed for the app, click the Next: Volumes button, otherwise click the Create button
  • Click the Notifications button to monitor the progress

Push a Docker container image to the Azure Container Registry

To push a Docker container image to the Azure Container Registry

Build the Docker container image

  • Navigate to https://www.docker.com/ and create a free Docker Hub account
  • Install the Docker Desktop application
  • Start the Docker Desktop application
  • Open a terminal and navigate to the application root directory where the Dockerfile is located
  • In the terminal execute the command
    docker build -t MY_IMAGE .
  • Push the image to the registry
	az login
	az acr login --name MY_REGISTRY
	docker tag MY_IMAGE:latest MY_REGISTRY.azurecr.io/MY_REPOSITORY/MY_IMAGE:latest
	docker push MY_REGISTRY.azurecr.io/MY_REPOSITORY/MY_IMAGE:latest

Troubleshooting

Error message when building the image

docker build -t …:latest .
ERROR: error during connect: Head “http://%2F%2F.%2Fpipe%2FdockerDesktopLinuxEngine/_ping”: open //./pipe/dockerDesktopLinuxEngine: The system cannot find the file specified.

Solution

Start the Docker Desktop application

Error message when pushing the image to Azure Container Registry

error from registry: authentication required, visit https://aka.ms/acr/authorization for more information. CorrelationId: 2a33d0ac-091c-4158-b927-397c6e5692cf

Solution

Create an Azure Container Registry

The Azure Container Registry hosts container images for deployment in any of the container hosting services.

Create a new Azure Container Registry

  • Log into the Azure Portal at http://portal.azure.com
  • In the search bar search for container registry and select Container registries
  • Click the Create button to create a new Azure container registry
  • Set the values and click the Next: Networking button
  • You need a Premium subscription to set up private access for better security. Click the Next: Encryption button
  • Encryption is also only available for Premium subscriptions. Click the Next: Tags button
  • Set up tags for better cost reporting
  • If you want to automate the registry creation in the future, click the Download a template for automation link. Click the Create button to create the registry.

To change the Azure Resource Group name

If you have created an Azure Resource Group, and want to change the name, unfortunately you cannot rename it. To change the name create a new resource group and move all resources from the old group to the new one.

Create a new resource group

  • In the main Azure page search for resource groups and select Resource groups from the list
  • Click the Create button and select Create new resource group
  • Enter the name of the resource group and click the Review + cerate button
  • Click the Automation link to download the creation script
  • Click the Cerate button to create the resource group

Move the resources from the old resource group to the new one

  • Open the old resource group, and click the first resource
  • Click the move link next to the old resource group name
  • Select the new resource group from the list
  • The validation status displays the current activity
  • Some resources cannot be moved
    • Restore points
  • If the resource can be moved, click the Next button at the bottom of the page
  • Select the checkbox and click the Move button
  • To monitor the progress of the move click the Notifications icon. The source and destination resource groups are locked during the move, so only one move can be processed at a time.
  • As the resource has been moved, the refresh button cannot display the new parent information. Go back to the Resource Group list and select the old resource group again top move the rest of the resources.

Deploy a web application in Azure Container Apps (ACA)

To deploy an application to Azure Container Apps

  • Log into the Azure Portal at http://portal.azure.com
  • In the top search bar search for container apps and select Container Apps in the list
  • Click the arrow next to Create and select Container App
  • Create a new Resource Group if needed, enter the app name (all lower case characters), select the Region. Select the environment, or click the Create new environment link. The West US 3 is the newest region in the west, located in Phoenix, Arizona, and provides Availability Zone support. Although West US is located in California, but does not provide availability zone support. Availability zone support offers very important redundancy within the same region in case of network and power outage, and natural disasters. The data transfer between availability zones within the same region is free, and many services can utilize the redundancy.
  • Enter the environment name, and select the zone redundancy, and click the Create button. For non mission critical apps the zone redundancy is usually not necessary, as it doubles the infrastructure cost.
  • Click the Next: Container button
  • Container
    • If there is no available container image to deploy, select Use quickstart image. This will deploy a temporary Hello World web application.
    • If you already have a container image to deploy, select the image location and resource requirements. Click the Next: Ingress button


  • For web applications enable ingress and traffic from anywhere, set the port to 80. Click the Next: Tags button
  • Add a name tag to the application for cost tracking, and click the Next: Review + create button
  • When the validation Passed

    Click the Download a template for automation link at the bottom of the page
  • On the next page click the Download button
  • In the upper right corner click the X to close the Template page
  • At the bottom of the page click the Create button
  • When the deployment is complete, click the Go to resource button
  • In the upper right of the page click the application URL link to open it in the browser.

Manage GitHub Copilot budget

The GitHub Copilot budget allows us to make sure we get the necessary premium assistance with a predictable price.

AI agent usage is charged by the complexity of the request and response, so the charges are very unpredictable

The $10 GitHub Copilot Pro subscription includes the free tier usage, that is may not enough if we use premium features, like Anthropic’s Claude Sonnet (for rapid drafts), and Claude Opus (for polishing the final, most complex sections).

When you have reached the limits of the free tier, you can update the budget to responsibly request more help to finish the project. To update the GitHub Copilot Coding Agent budget

  • Navigate to Budgets and alerts
  • In the All Premium Request SKUs line click the ellipses and select Edit
  • Enter the amount you are planning to spend on the AI Coding Agent and click the Update budget button

Creating Tailwind theme collections

Tailwind is a rapid web development tool to style user interfaces using English like expressions. It has advantages and disadvantages.

Advantages

Instead of complex CSS, use English like style class names to control all aspects of the web interface

Disadvantages

When we use CSS, we create classes to style similar elements, like submitButton, searchField. Tailwind classes define a specific visual property, like background, border, text color. There is no room to create styles for similar objects. Using Tailwind it can be tedious to keep the visuals consistent in a large web application. If we want to update the style of all buttons on multiple pages, we have to visit all of them to change the class names.

In this tutorial we will develop a system that merges the advantages of the CSS thematic classes and the friendliness of Tailwind.

We will create a class collection, a middle layer between the Tailwind classes and the elements to specify the look of all controls with the same purpose. You still can override the values at the individual control level with the ! (important) postfix.

Class collection

Create the styles/classes.ts file in the same directory where the style sheets are located for consistency. In this example we will create separate themes for the panel header, and the panel body. All contains light and dark mode Tailwind classes for background, border, button text, hover styling.

// Define color themes for different panel types
// Each theme includes classes for borders, backgrounds, text, inputs, buttons, and drag states
export const ColorThemes = {
  panelHeader: {
    bg: "bg-slate-200 dark:bg-slate-700",
    text: "text-black dark:text-white",
    input: "bg-white dark:bg-slate-600 text-black dark:text-white placeholder:text-slate-500 dark:placeholder:text-slate-400",
    button: "bg-black/50 dark:bg-white/20 text-white/80 dark:text-white hover:bg-black/40 dark:hover:bg-white/50",
  },
  panelBody: {
    border: "border-blue-200 dark:border-slate-600",
    bg: "bg-slate-100 dark:bg-slate-700",
    text: "text-blue-200 dark:text-blue-800",
    hover: "hover:bg-blue-100 dark:hover:bg-slate-700",
    button: "bg-blue-600 dark:bg-blue-800 hover:bg-blue-500 dark:hover:bg-blue-700",
  },
};

Usage

In the .tsx file import the class collection and create constant references.

// Import color themes to standardize appearance for light and dark modes
import { ColorThemes } from "~/styles/classes";

Style the controls. Enclose the entire className definition in curly braces, and use backtick to allow variable usage in the string. You can add additional Tailwind classes to the element to set specific visual features.

    <div className={`${ColorThemes.panelBody.bg} ${ColorThemes.panelBody.border} rounded-xl`} >

To override the background color for this element, use the ! (important) postfix

<div className={`${ColorThemes.panelBody.bg} bg-black! rounded-xl`} >

Using React Router (Remix) with Material Tailwind components

Material UI is a great Google React UI component library. It looks great, provides consistent look for web applications, but it has two disadvantages:

  • The icon library has more than 9000 icons, it takes a long time to load all of them, as there is no tree shaking to ignore the unused items.
  • The Tailwind styling classes don’t always work, because the Material UI built-in themes of colors and other settings take precedent.

Material Tailwind is an opensource library recreating the consistent look of Material UI, but allowing Tailwind themes to control the look.

To set a React Router (Remix) web application to use Material Tailwind

Install Tailwind CSS with React Router (Remix)

Install Tailwind CSS

pnpm install tailwindcss @tailwindcss/vite

Configure the Vite plugin. Add the bold lines to the vite.config.js file

import { reactRouter } from "@react-router/dev/vite";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
import tailwindcss from "@tailwindcss/vite";
export default defineConfig({
  plugins: [
    tailwindcss(),
    reactRouter(),
    tsconfigPaths(),
  ],
});

Add to the app.css file

@import "tailwindcss";

See Install Tailwind CSS with React Router

Install @material-tailwind/react as a dependency

Execute the command

pnpm i @material-tailwind/react

Create the tailwind.config.js file in the root of the web application directory

const withMT = require("@material-tailwind/react/utils/withMT");
module.exports = withMT({
  content: ["./app/**/*.{js,jsx,ts,tsx}"], // Add your template paths here
  theme: {
    extend: {},
  },
  plugins: [],
});

If you are using a monorepo, to host multiple applications in the same repository, and the node_modules directory is not in the application directory, use this tailwind.config.js file in the root of the web application

import type { Config } from "tailwindcss";
 
import withMT from "@material-tailwind/react/utils/withMT";
 
export default withMT({
  content: [
    "./app/**/*.{js,ts,jsx,tsx}",
    "path-to-your-node_modules/@material-tailwind/react/components/**/*.{js,ts,jsx,tsx}",
    "path-to-your-node_modules/@material-tailwind/react/theme/components/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
} satisfies Config);

Theme Provider

Wrap the entire application with the ThemeProvider. Create the app/entry.client file

import { RemixBrowser } from "@remix-run/react";
import { startTransition } from "react";
import { hydrateRoot } from "react-dom/client";
import { ThemeProvider } from "@material-tailwind/react";
 
startTransition(() => {
  hydrateRoot(
    document,
    <ThemeProvider>
      <RemixBrowser />
    </ThemeProvider>
  );
});

Web page example

This example displays a button using the Material Tailwind library

import MaterialTailwind from "@material-tailwind/react";
const { Button } = MaterialTailwind;
 
export default function Example() {
  return <Button>Button</Button>;
}

See Material Tailwind with Remix