Audio/Video Calling from a Custom App into a Teams Meeting
Level: Intermediate
In this tutorial, you'll learn how Azure Communication Services can be used in a custom React application to allow a user to make an audio/video call into a Microsoft Teams meeting. You'll learn about the different building blocks that can be used to make this scenario possible and be provided with hands-on steps to walk you through the different Microsoft Cloud services involved.
What You'll Build in this Tutorial
Overview of the Application Solution

Prerequisites
- Node - Node 16+ and npm 7+ are used for this project
- git
- Visual Studio Code
- Azure Functions Extension for VS Code
- Azure subscription
- Microsoft 365 developer tenant
- GitHub account
Technologies used in this tutorial include
- React
- Azure Communication Services
- Azure Functions
- Microsoft Graph
- Microsoft Teams
Create an Azure Communication Services Resource
In this exercise you'll create an Azure Communication Services (ACS) resource in the Azure Portal.
To get started, perform the following tasks:
Visit the Azure Portal in your browser and sign in.
Type communication services in the search bar at the top of the page and select Communication Services from the options that appear.
Select Create in the toolbar.
Perform the following tasks:
- Select your Azure subscription.
- Select the resource group to use (create a new one if one doesn't exist).
- Enter an ACS resource name. It must be a unique value.
- Select a data location.
Select Review + Create followed by Create.
Once your ACS resource is created, navigate to it, and select Settings --> Identities & User Access Tokens.
Select the Voice and video calling (VOIP) checkbox.
Select Generate.
Copy the Identity and User Access token values to a local file. You'll need the values later in this exercise.
Select Settings --> Keys and copy the Primary key connection string value to the local file where you copied the user identity and token values.
To run the application you'll need a Teams meeting link. Go to Microsoft Teams, sign in with your Microsoft 365 developer tenant, and select the Calendar option on the left.
Tip
If you don't currently have a Microsoft 365 account, you can sign up for the Microsoft 365 Developer Program subscription. It's free for 90 days and will continually renew as long as you're using it for development activity. If you have a Visual Studio Enterprise or Professional subscription, both programs include a free Microsoft 365 developer subscription, active for the life of your Visual Studio subscription.
Select a any date/time on the calendar, add a title for the meeting, invite a user from your Microsoft 365 developer tenant, and select Save.
Select the new meeting you added in the calendar and copy the Teams meeting link that is displayed into the same file where you stored the ACS user identity, token, and connection string.
Now that your ACS resource is setup and you have a Teams meeting join link, let's get the React application up and running.
Integrate Azure Communication Services Calling into a React App
In this exercise you'll add the ACS UI calling composite into a React app to enable making audio/video calls from a custom app into a Microsoft Teams meeting.
Visit GitHub and sign in. If you don't already have a GitHub account, you can select the Sign up option to create one.
Visit the Microsoft Cloud GitHub Repository.
Select the Fork option to add the repository to your desired GitHub organization/account.
Run the following command to clone this repository to your machine. Replace <YOUR_ORG_NAME> with your GitHub organization/account name.
git clone https://github.com/<YOUR_ORG_NAME>/MicrosoftCloudOpen the samples/acs-to-teams-meeting/client/react project folder in Visual Studio Code.
Open the package.json file in VS Code and note the following ACS packages are included:
@azure/communication-common @azure/communication-reactDouble-check that you have npm 7 or higher installed by opening a terminal window and running the following command:
npm --versionTip
If you don't have npm 7 or higher installed you can update npm to the latest version by running
npm install -g npm.Open a terminal window and run the
npm installcommand in the react folder to install the application dependencies.Open App.tsx and take a moment to explore the imports at the top of the file. These handle importing ACS security and audio/video calling symbols that will be used in the app.
import { AzureCommunicationTokenCredential, CommunicationUserIdentifier } from '@azure/communication-common'; import { CallComposite, fromFlatCommunicationIdentifier, useAzureCommunicationCallAdapter } from '@azure/communication-react'; import React, { useState, useMemo, useEffect } from 'react'; import './App.css';Note
You'll see how the
CallCompositecomponent is used later in this exercise. It provides the core UI functionality for Azure Communication Services to enable making an audio/video call from the app into a Microsoft Teams meeting.Locate the
Appcomponent and perform the following tasks:- Take a moment to examine the
useStatedefinitions in the component. - Replace the
userIduseStatefunction's empty quotes with the ACS user identity value you copied in the previous exercise. - Replace the
tokenuseStatefunction's empty quotes with the ACS token value you copied in the previous exercise. - Replace the
teamsMeetingLinkuseStatefunction's empty quotes with the Teams meeting link value you copied in the previous exercise.
// Replace '' with the ACS user identity value const [userId, setUserId] = useState<string>(''); // Replace '' with the ACS token value const [token, setToken] = useState<string>(''); // Replace '' with the Teams meeting link value const [teamsMeetingLink, setTeamsMeetingLink] = useState<string>('');Note
Later in this tutorial you'll see how to retrieve the
userId,token, andteamsMeetingLinkvalues dynamically.- Take a moment to examine the
Take a moment to explore the
useMemofunctions in theAppcomponent.- The
credentialuseMemofunction creates a newAzureCommunicationTokenCredentialinstance once the token has a value. - The
callAdapterArgsuseMemofunction returns an object that has the arguments that are used to make an audio/video call. Notice that is uses theuserId,credential, andteamsMeetingLinkvalues in the ACS call arguments.
const credential = useMemo(() => { if (token) { return new AzureCommunicationTokenCredential(token) } return; }, [token]); const callAdapterArgs = useMemo(() => { if (userId && credential && displayName && teamsMeetingLink) { return { userId: fromFlatCommunicationIdentifier(userId) as CommunicationUserIdentifier, displayName, credential, locator: { meetingLink: teamsMeetingLink }, } } return {}; }, [userId, credential, displayName, teamsMeetingLink]);Note
useMemois used in this scenario because we only want theAzureCommunicationTokenCredentialobject and the call adapter args to be created once as the necessary parameters are passed in. View additional details about useMemo here.- The
Once the
credentialsandcallAdapterArgsare ready, the following line handles creating an ACS call adapter using theuseAzureCommunicationCallAdapterReact hook provided by ACS. ThecallAdapterobject will be used later in the UI calling composite component.const callAdapter = useAzureCommunicationCallAdapter(callAdapterArgs);Note
Because
useAzureCommunicationCallAdapteris a React hook, it won't assign a value tocallAdapteruntil thecallAdapterArgsvalue is valid.Earlier you assigned the user identity, token, and Teams meeting link to state values in the
Appcomponent. That works fine for now, but in a later exercise you'll see how to dynamically retrieve those values. Since you set the values earlier, comment out the code in theuseEffectfunction as shown next. Once you get the Azure Functions running in the next exercises, you'll revisit this code.useEffect(() => { /* Commenting out for now const init = async () => { setMessage('Getting ACS user'); //Call Azure Function to get the ACS user identity and token let res = await fetch(process.env.REACT_APP_ACS_USER_FUNCTION as string); let user = await res.json(); setUserId(user.userId); setToken(user.token); setMessage('Getting Teams meeting link...'); //Call Azure Function to get the meeting link res = await fetch(process.env.REACT_APP_TEAMS_MEETING_FUNCTION as string); let link = await res.text(); setTeamsMeetingLink(link); setMessage(''); console.log('Teams meeting link', link); } init(); */ }, []);Locate the following JSX code. It uses the
CallCompositesymbol you saw imported to render the user interface used to make an audio/video call from the React app into a Teams meeting. ThecallAdapteryou explored earlier is passed to itsadapterproperty to provide the required arguments.if (callAdapter) { return ( <div> <h1>Contact Customer Service</h1> <div className="wrapper"> <CallComposite adapter={callAdapter} /> </div> </div> ); }Save the file before continuing.
Run
npm startin your terminal window to run the application. Ensure you run the command within the react folder.After the applications builds you should see a calling UI displayed. Enable selecting your microphone and camera and initiate the call. You should see that you're placed in a waiting room. If you join the meeting you setup earlier in Microsoft Teams, you can allow the guest to enter the meeting.
Press Ctrl + C to stop the application. Now that you've successfully run it, let's explore how you can dynamically get the ACS user identity and token and automatically create a Microsoft Teams meeting and return the join URL using Microsoft Graph.
Dynamically Create a Microsoft Teams Meeting using Microsoft Graph
In this exercise, you'll automate the process of creating a Microsoft Teams meeting link and passing to the ACS by using Azure Functions and Microsoft Graph.
You'll need to create an Azure Active Directory (AAD) app for Daemon app authentication. In this step, authentication will be handled in the background with app credentials, and AAD app will use Application Permissions to make Microsoft Graph API calls. Microsoft Graph will be used to dynamically create a Microsoft Teams meeting and return the Teams meeting URL.
Perform the following steps to create an AAD app:
- Go to Azure Portal and select Azure Active Directory.
- Select the App registration tab followed by + New registration.
- Fill in the new app registration form details as shown below and select Register:
- Name: ACS Teams Interop App
- Supported account types: Accounts in any organizational directory (Any Azure AD directory - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)
- Redirect URI: leave this blank
- After the app is registered, go to API permissions and select + Add a permission.
- Select Microsoft Graph followed by Application permissions.
- Select the
Calendars.ReadWritepermission and then select Add. - After adding the permissions, select Grant admin consent for <YOUR_ORGANIZATION_NAME>.
- Go to the Certificates & secrets tab, select + New client secret, and then select Add.
- Copy the value of the secret into a local file. You'll use the value later in this exercise.
- Go to the Overview tab and copy the
Application (client) IDandDirectory (tenant) IDvalues into the same local file that you used in the previous step.
Open the samples/acs-to-teams-meeting/server/typescript project folder in Visual Studio Code.
Create a local.settings.json file with the following values:
{ "IsEncrypted": false, "Values": { "FUNCTIONS_WORKER_RUNTIME": "node", "TENANT_ID": "", "CLIENT_ID": "", "CLIENT_SECRET": "", "USER_ID": "", "ACS_CONNECTION_STRING": "" }, "Host": { "LocalHttpPort": 7071, "CORS": "*", "CORSCredentials": false }, "watchDirectories": [ "Shared" ] }- Use the values you copied into the local file to update the
TENANT_ID,CLIENT_IDandCLIENT_SECRETvalues. - Define
USER_IDwith the user id that you'd like to create a Microsoft Teams Meeting.
You can get the User ID from the Azure Portal. Select Azure Active Directory and navigate to the Users tab on the side bar. Search for your user name and select it to see the user details. Inside the user details,
Object IDrepresents theUser ID. Copy theObject IDvalue and use it for theUSER_IDvalue in local.settings.json.
Note
ACS_CONNECTION_STRINGwill be used in the next exercise so you don't need to update it yet.- Use the values you copied into the local file to update the
Open the package.json file in VS Code and note that the following Microsoft Graph and Identity packages are included:
@azure/communication-identity @azure/identity @microsoft/microsoft-graph-clientOpen a terminal window in the typescript folder and run the
npm installcommand to install the application dependencies.Open Shared/graph.ts and take a moment to explore the imports at the top of the file. This code handles importing authentication and client symbols that will be used in the Azure Function to call Microsoft Graph.
import { startDateTimeAsync, endDateTimeAsync } from './dateTimeFormat'; import { ClientSecretCredential } from '@azure/identity'; import { Client } from '@microsoft/microsoft-graph-client'; import { TokenCredentialAuthenticationProvider } from '@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials'; import 'isomorphic-fetch';Tip
You'll also see imports from dateTimeFormat.ts which will be used later in this exercise.
startDateTimeAsyncandendDateTimeAsyncwill be used while creating a Microsoft Teams meeting link to define start date and end date for the meeting.Take a moment to examine
clientSecretCredentialandappGraphClient, they will be used later in the authentication process and when calling the Microsoft Graph API:let clientSecretCredential; let appGraphClient;Locate the
ensureGraphForAppOnlyAuthfunction:ClientSecretCredentialuses theTenant Id,Client IdandClient Secretvalues from the Azure Active Directory app.- The
authProviderobject is defined as an Azure Active Directory app that will authenticate in the background and use app-only permissions (such asCalendars.ReadWrite) to make Microsoft Graph API calls.
function ensureGraphForAppOnlyAuth() { if (!clientSecretCredential) { clientSecretCredential = new ClientSecretCredential( process.env.TENANT_ID, process.env.CLIENT_ID, process.env.CLIENT_SECRET ); } if (!appGraphClient) { const authProvider = new TokenCredentialAuthenticationProvider( clientSecretCredential, { scopes: [ 'https://graph.microsoft.com/.default' ] }); appGraphClient = Client.initWithMiddleware({ authProvider: authProvider }); } }Take a moment to explore the
createNewMeetingAsyncfunction. It posts data to the Microsoft Graph Calendar Events API which dynamically creates an event in a user's calendar and returns the new event details:async function createNewMeetingAsync(userId) { ensureGraphForAppOnlyAuth(); let startTime = await startDateTimeAsync(); let endTime = await endDateTimeAsync(); const newMeeting = `/users/${userId}/calendar/events`; const event = { subject: 'Customer Service Meeting', start: { dateTime: startTime, timeZone: 'UTC' }, end: { dateTime: endTime, timeZone: 'UTC' }, isOnlineMeeting: true }; const newEvent = await appGraphClient.api(newMeeting).post(event); return newEvent; } export default createNewMeetingAsync;Go to TeamsMeetingFunction/index.ts and explore the Http Trigger function:
createNewMeetingAsyncis imported from graph.ts. It handles creating and retrieving new event details.userIdis retrieved from local.settings.json inside the Http Trigger function. This is done by accessing theUSER_IDenvironment variable by usingprocess.env.USER_ID.- When the function is triggered, it calls
createNewMeetingAsyncwith the defined user id and returns the new event details inteamMeetingLinkparameter. - The function accesses the Teams meeting join URL by calling
meeting.onlineMeeting.joinUrland returns the value in the body of the response.
import { AzureFunction, Context, HttpRequest } from "@azure/functions"; import createNewMeetingAsync from '../Shared/graph'; let teamsMeetingLink; const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest){ context.log("Request received"); const userId = process.env.USER_ID; context.log('UserId', userId); teamsMeetingLink = await createNewMeetingAsync(userId); const body = JSON.stringify(teamsMeetingLink); const meeting = JSON.parse(body); context.log("meeting:", meeting); context.res = { // status: 200, /* Defaults to 200 */ body: meeting.onlineMeeting.joinUrl } }; export default httpTrigger;Use a terminal window to run
npm startin the samples/acs-video-to-teams-meeting/server/typescript folder to run the function locally.Now that the
TeamsMeetingFunctionis ready to use, let's call the function from the React app.Go back to the samples/acs-to-teams-meeting/client/react folder in VS Code. Add a .env file into the folder with the following values:
REACT_APP_TEAMS_MEETING_FUNCTION=http://localhost:7071/api/TeamsMeetingFunction REACT_APP_ACS_USER_FUNCTION=http://localhost:7071/api/ACSTokenFunctionThese values will be passed into React as it builds so that you can easily change them as needed during the build process.
Open samples/acs-to-teams-meeting/client/react/App.tsx file in VS Code.
Locate the
teamsMeetingLinkstate variable in the component. Remove the hardcoded teams link and replace it with empty quotes:const [teamsMeetingLink, setTeamsMeetingLink] = useState<string>('');Locate the
useEffectfunction and change it to look like the following. This handles calling the Azure Function you looked at earlier which creates a Teams meeting and returns the meeting join link:useEffect(() => { const init = async () => { /* Commenting out for now setMessage('Getting ACS user'); //Call Azure Function to get the ACS user identity and token const res = await fetch(process.env.REACT_APP_ACS_USER_FUNCTION as string); const user = await res.json(); setUserId(user.userId); setToken(user.token); */ setMessage('Getting Teams meeting link...'); //Call Azure Function to get the meeting link const resTeams = await fetch(process.env.REACT_APP_TEAMS_MEETING_FUNCTION as string); const link = await resTeams.text(); setTeamsMeetingLink(link); setMessage(''); console.log('Teams meeting link', link); } init(); }, []);Save the file before continuing.
Open another terminal window,
cdinto the react folder, and runnpm startto build and run the application.After the application builds, you should see the ACS calling UI displayed and can then call into the Teams meeting that was dynamically created by Microsoft Graph.
Stop both of the terminal processes (React and Azure Functions) by entering Ctrl + C in each terminal window.
Dynamically Create an Azure Communication Services Identity and Token
In this exercise you'll learn how to dynamically retrieve user identity and token values from Azure Communication Services using Azure Functions. Once retrieved, the values will be passed to the ACS UI composite to enable a call to be made by a customer.
Open local.settings.json and update the
ACS_CONNECTION_STRINGvalue with the ACS connection string you saved in an earlier exercise.Open samples/acs-to-teams-meeting/server/typescript/ACSTokenFunction/index.ts in Visual Studio Code. It has the following code:
import { CommunicationIdentityClient } from '@azure/communication-identity'; module.exports = async function (context, req) { // Get ACS connection string from local.settings.json (or App Settings when in Azure) const connectionString = process.env.ACS_CONNECTION_STRING; let tokenClient = new CommunicationIdentityClient(connectionString); const user = await tokenClient.createUser(); const userToken = await tokenClient.getToken(user, ["voip"]); context.res = { body: { userId: user.communicationUserId, ...userToken } }; }The function performs the following tasks:
Imports
CommunicationIdentityClientwhich will be used to create the user identity and token.import { CommunicationIdentityClient } from '@azure/communication-identity';Gets the ACS connection string from an environment variable named
ACS_CONNECTION_STRING.const connectionString = process.env.ACS_CONNECTION_STRING;
Note
This is the connection string value you added into the local.settings.json file earlier.
Creates a new
CommunicationIdentityClientinstance and passes the ACS connection string to it.let tokenClient = new CommunicationIdentityClient(connectionString);Creates an ACS user and gets a Voice Over IP token.
const user = await tokenClient.createUser(); const userToken = await tokenClient.getToken(user, ["voip"]);Sends the userId and token values back to the caller.
context.res = { body: { userId: user.communicationUserId, ...userToken } };
Go to the samples/acs-to-teams-meeting/server/typescript folder in a terminal window and run
npm start.Now that the Azure Functions are running locally, the client needs to be able to call into them to get the ACS user identity and token values.
Open samples/acs-to-teams-meeting/client/react/App.tsx file in your editor.
Locate the
userIdandtokenstate variables in the component. Remove the hardcoded values and replace them with empty quotes:const [userId, setUserId] = useState<string>(''); const [token, setToken] = useState<string>('');Locate the
useEffectfunction and change it to look like the following to enable calling the Azure Function to retrieve an ACS user identity and token:useEffect(() => { const init = async () => { setMessage('Getting ACS user'); //Call Azure Function to get the ACS user identity and token let res = await fetch(process.env.REACT_APP_ACS_USER_FUNCTION as string); let user = await res.json(); setUserId(user.userId); setToken(user.token); setMessage('Getting Teams meeting link...'); //Call Azure Function to get the meeting link res = await fetch(process.env.REACT_APP_TEAMS_MEETING_FUNCTION as string); let link = await res.text(); setTeamsMeetingLink(link); setMessage(''); console.log('Teams meeting link', link); } init(); }, []);Save the file before continuing.
Open a separate terminal and run
npm startin the react folder. After it builds you should see the ACS calling UI displayed and you can call into the Teams meeting that was dynamically created by Microsoft Graph.Stop both of the terminal processes (React and Azure Functions) by selecting Ctrl + C.
Commit your git changes and push them to your GitHub repository using Visual Studio Code:
- Select the Source Control icon (3rd one down in the Visual Studio Code toolbar).
- Enter a commit message and select Commit.
- Select Sync Changes.
Deploy the App to Azure Static Web Apps
In this exercise you'll learn how to deploy the ACS React app and the Azure Functions to the cloud using Azure Static Web Apps.
Visit the Azure Portal in your browser and sign in.
Type static web apps in the top search bar and select Static Web Apps from the options that appear.
Select Create in the toolbar.
Perform the following tasks:
- Select your subscription.
- Select the resource group to use (create a new one if needed). You can use the same resource group that you used for ACS if you'd like.
- Enter an Azure Static Web Apps name of acs-to-teams-meeting.
- Select the Free plan type.
- Select a region.
Select the GitHub radio button and sign in to your GitHub account.
After signing in, select your GitHub:
- Organization
- Repository: Select the MicrosoftCloud repository you forked earlier in this tutorial
- Branch: Select main
In the Build Details section perform the following tasks:
- Build Presets: React
- App location: /samples/acs-to-teams-meeting/client/react
- Api location: /samples/acs-to-teams-meeting/server/typescript
- Output location: build
Select Review + create.
Review the details and select Create.
Notice the URL that is created for your static web app. Copy the URL shown on the Overview screen to a file. You'll need it later in this exercise.
Select Settings --> Configuration for your new static web app.
Add all of the following key/value pairs into the Application settings by selecting the + Add button. Get the values from your local.settings.json in the server/typescript folder.
# Get the values from your local.settings.json file TENANT_ID: <YOUR_VALUE> CLIENT_ID: <YOUR_VALUE> CLIENT_SECRET: <YOUR_VALUE> USER_ID: <YOUR_VALUE> ACS_CONNECTION_STRING: <YOUR_VALUE>Select the Save button at the top of the Configuration screen in the Azure Portal.
Now that you've finished setting up the Azure Static Web App, go back to your GitHub repository (the one you forked earlier) in the browser and notice a .yml file has been added into the .github/workflows folder.
Open the .yml file in VS Code and add the following YAML immediately after the
###### End of Repository/Build Configurations ######comment. Replace the <YOUR_AZURE_SWA_DOMAIN> placeholders with your Azure Static Web Apps URL value.IMPORTANT: Ensure that the
env:property is indented properly. It should match up with the indentation of thewith:property above it.env: # Add environment variables here REACT_APP_ACS_USER_FUNCTION: https://<YOUR_AZURE_SWA_DOMAIN>/api/ACSTokenFunction REACT_APP_TEAMS_MEETING_FUNCTION: https://<YOUR_AZURE_SWA_DOMAIN>/api/TeamsMeetingFunctionNote
This will add environment variables into the build process for the React app so that it knows what APIs to call to get the ACS user token as well as to create a Teams meeting.
Save the .yml file and push the changes up to your GitHub repository. This will trigger a new build of the React application and then deploy it to your Azure Static Web App.
Once the build process completes, visit the URL for your Azure Static Web App and you should see the application running.
You've successfully deployed your application using Azure Static Web Apps!
Deploy the App to Azure Functions and Azure Container Apps
Important
In addition to the pre-requisites listed for this tutorial, you'll also need to install the Azure CLI on your machine to complete this exercise.
In this exercise you'll learn how to deploy the Microsoft Graph and ACS functions discussed in earlier exercises to Azure Functions. You'll also build a container image and deploy it to Azure Container Apps.
Deploy to Azure Functions
Let's get started by using VS Code to deploy the functions code to Azure Functions.
Open the samples/acs-to-teams-meeting/server/typescript project folder in Visual Studio Code.
You should have already run
npm installand see a node_modules folder in the project root. If not, open a command window and runnpm installto install the dependencies.Open the VS Code command pallet (Shift+Cmd+P on Mac | Shift+Ctrl+P on Windows), and select Azure Functions: Create Function App in Azure.
You'll be prompted to enter the following information:
- Your Azure subscription name.
- The function name: acsFunctions<YOUR_LAST_NAME>.
Note
A globally unique name is required. You can make the name more unique by adding a number or your last name to the end of the name.
- The runtime stack - Select the latest Node.js LTS version.
- The region (select any region you'd like).
Once the Azure Function App is created, you'll see a message about viewing the details.
Go back to the command pallet in VS Code and select Azure Functions: Deploy to Function App. You'll be asked to select your subscription and the Function App name you created earlier.
Once the function is deployed to Azure, do the following:
- Select the Azure extension in VS Code (click the Azure icon in the sidebar).
- Expand your subscription.
- Expand your Function App.
- Right-click on the function and select Browse Website. Ensure the function app is working correctly before proceeding.
Copy the Azure Function domain to a local file. You'll use the value later in this exercise.
Deploy to Azure Container Apps
The first task you'll perform is to create a new Azure Container Registry (ACR) resource. Once the registry is created, you'll build an image and push it to the registry.
Open a command window and run the following command to login to your Azure subscription:
az loginAdd the following shell variables substituting your values for the placeholders as appropriate. Add your <GITHUB_USERNAME> as a lowercase value and substitute your Azure Functions domain for the <AZURE_FUNCTIONS_DOMAIN> value (include the
https://in the domain value).GITHUB_USERNAME="<YOUR_GITHUB_USERNAME>" RESOURCE_GROUP="<YOUR_RESOURCE_GROUP_NAME>" ACR_NAME="aca"$GITHUB_USERNAME AZURE_FUNCTIONS_DOMAIN="<YOUR_AZURE_FUNCTIONS_URL>"Create a new Azure Container Registry resource by running the following command:
az acr create \ --resource-group $RESOURCE_GROUP \ --name $ACR_NAME \ --sku Basic \ --admin-enabled trueOpen the samples/acs-to-teams-meeting/client/react/Dockerfile file in your editor and notice that the following tasks are performed:
- The React application is built and assigned to the build stage.
- The nginx server is configured and the output of the build stage is copied into the nginx server image.
Build the container image in Azure by running the following command from the root of the samples/acs-to-teams-meeting/client/react folder. Replace <YOUR_FUNCTIONS_DOMAIN> with your Azure Functions domain that you copied to a local file earlier in this exercise.
az acr build --registry $ACR_NAME --image acs-to-teams-meeting \ --build-arg REACT_APP_ACS_USER_FUNCTION=$AZURE_FUNCTIONS_DOMAIN/api/ACSTokenFunction \ --build-arg REACT_APP_TEAMS_MEETING_FUNCTION=$AZURE_FUNCTIONS_DOMAIN/api/TeamsMeetingFunction .Run the following command to list the images in your registry. You should see your new image listed.
az acr repository list --name $ACR_NAME --output tableNow that the image is deployed, you need to create an Azure Container App that can run the container.
Visit the Azure Portal in your browser and sign in.
Type container apps in the top search bar and select Container Apps from the options that appear.
Select Create in the toolbar.
Note
Although you're using the Azure Portal, a Container App can also be created by using the Azure CLI. For more information, see Quickstart: Deploy your first container app. You'll see an example of how the Azure CLI can be used at the end of this exercise as well.
Perform the following tasks:
- Select your subscription.
- Select the resource group to use (create a new one if needed). You can use the same resource group that you used for your ACS resource if you'd like. Copy your resource group name to the same local file where you stored your Azure Functions domain.
- Enter a Container app name of acs-to-teams-meeting.
- Select a region.
- Select Create new in the Container Apps Environment section.
- Enter an Environment name of acs-to-teams-meeting-env.
- Select the Create button.
- Select Next: App settings >.
Enter the following values in the Create Container App screen:
- Deselect the Use quickstart image checkbox.
- Name: acs-to-teams-meeting
- Image source: Azure Container Registry
- Registry: <YOUR_ACR_REGISTRY_NAME>.azurecr.io
- Image: acs-to-teams-meeting
- Image tag: latest
- CPU and Memory: 0.25 CPU cores, -.5 Gi memory
In the Application ingress settings section, do the following:
- Select the Enabled checkbox.
- Select the Accepting traffic from anywhere radio button.
This will create an entry point (ingress) for your React application and allow it to be called from anywhere. Azure Container Apps redirects all traffic to HTTPS.
- Target Port: 80
Select Review + create. Once validation passes, select the Create button.
If you get an error it may be due to your container apps environment being inactive for too long. The simplest solution will be to go through the process of creating the container app again. Alternatively, you can run the following command to create the container app using the Azure CLI:
az containerapp create --name acs-to-teams-meeting --resource-group $RESOURCE_GROUP \ --location westus --image acs-to-teams-meeting \ --cpu 0.25 --memory 0.5 --environment-name acs-to-teams-meeting-env \ --ingress-enabled true --ingress-target-port 80 --ingress-type External \ --ingress-protocol Https --ingress-traffic AnywhereOnce your container app deployment completes, navigate to it in the Azure Portal and select the Application Url on the Overview screen to view the application running in the nginx container!
Congratulations!
You've completed this tutorial

Have an issue with this section? If so, please give us some feedback so we can improve this section.
Feedback
Submit and view feedback for

Formed in 2009, the Archive Team (not to be confused with the archive.org Archive-It Team) is a rogue archivist collective dedicated to saving copies of rapidly dying or deleted websites for the sake of history and digital heritage. The group is 100% composed of volunteers and interested parties, and has expanded into a large amount of related projects for saving online and digital history.
