Use a private endpoint with an Azure Container Apps environment

In this article, you learn how to use a private endpoint to securely access your Azure Container App without exposing it to the public Internet.

A private endpoint uses a private IP address from your virtual network (VNet). This endpoint connects you privately and securely to a service powered by Azure Private Link.

Prerequisites

Create a container app

Begin by signing in to the Azure portal.

  1. Search for Container Apps in the top search bar.

  2. Select Container Apps in the search results.

  3. Select the Create button.

  4. In the Create Container App page on the Basics tab, enter the following values.

    Setting Action
    Subscription Select your Azure subscription.
    Resource group Select Create new and enter my-container-apps.
    Container app name Enter my-container-app.
    Deployment source Select Container image.
    Region Select Central US.
  5. In the Create Container Apps Environment field, select the Create new link.

  6. In the Create Container Apps Environment page on the Basics tab, enter the following values:

    Setting Value
    Environment name Enter my-environment.
    Zone redundancy Select Disabled
  7. Select the Networking tab to create a virtual network (VNet). By default, public network access is enabled, which means private endpoints are disabled.

  8. Disable public network access.

  9. Leave Use your own virtual network set to No. You can use an existing VNet, but private endpoints are only supported by workload profiles environments, which require a subnet with a minimum CIDR range of /27 or larger. To learn more about subnet sizing, see the networking architecture overview.

  10. Set Enable private endpoints to Yes.

  11. Set Private endpoint name to my-private-endpoint.

  12. In the Private endpoint virtual network field, select the Create new link.

  13. In the Create Virtual Network page, set Virtual Network to my-private-endpoint-vnet. Select OK.

  14. In the Private endpoint virtual network Subnet field, select the Create new link.

  15. In the Create Subnet page, set Subnet Name to my-private-endpoint-vnet-subnet. Select OK.

  16. Leave DNS set to Azure Private DNS Zone.

  17. Select Create.

  18. In the Create Container App page on the Basics tab, select Next : Container >.

  19. In the Create Container App page on the Container tab, select Use quickstart image.

  20. Select Review and create at the bottom of the page.

    If no errors are found, the Create button is enabled.

    If there are errors, any tab containing errors is marked with a red dot. Navigate to the appropriate tab. Fields containing an error are highlighted in red. Once all errors are fixed, select Review and create again.

  21. Select Create.

    A page with the message Deployment is in progress is displayed. Once the deployment is successfully completed, you see the message: Your deployment is complete.

    When you browse to the container app endpoint, you receive ERR_CONNECTION_CLOSED because your container app environment has public access disabled. Instead, you access your container app using your private endpoint.

Prerequisites

  • Azure account with an active subscription.

  • The latest version of the Azure CLI. To ensure you're running the latest version, run the following command.

    az upgrade
    
  • The latest version of the Azure Container Apps extension for the Azure CLI. To ensure you're running the latest version, run the following command.

    az extension add --name containerapp --upgrade --allow-preview true
    

    Note

    Starting in May 2024, Azure CLI extensions no longer enable preview features by default. To access Container Apps preview features, install the Container Apps extension with --allow-preview true.

For more information about prerequisites and setup, see Quickstart: Deploy your first container app with containerapp up.

Set environment variables

Set the following environment variables.

RESOURCE_GROUP="my-container-apps"
LOCATION="centralus"
ENVIRONMENT_NAME="my-environment"
CONTAINERAPP_NAME="my-container-app"
VNET_NAME="my-custom-vnet"
SUBNET_NAME="my-custom-subnet"
PRIVATE_ENDPOINT="my-private-endpoint"
PRIVATE_ENDPOINT_CONNECTION="my-private-endpoint-connection"
PRIVATE_DNS_ZONE="privatelink.${LOCATION}.azurecontainerapps.io"
DNS_LINK="my-dns-link"

Create an Azure resource group

Create a resource group to organize the services related to your container app deployment.

az group create \
    --name $RESOURCE_GROUP \
    --location $LOCATION

Create a virtual network

An environment in Azure Container Apps creates a secure boundary around a group of container apps. Container Apps deployed to the same environment are deployed in the same virtual network and write logs to the same Log Analytics workspace.

  1. Create an Azure virtual network (VNet) to associate with the Container Apps environment. The VNet must have a subnet available for the environment deployment. You can use an existing VNet, but private endpoints are only supported by workload profiles environments, which require a subnet with a minimum CIDR range of /27 or larger. To learn more about subnet sizing, see the networking architecture overview.

    az network vnet create \
        --resource-group $RESOURCE_GROUP \
        --name $VNET_NAME \
        --location $LOCATION \
        --address-prefix 10.0.0.0/16
    
  2. Create a subnet to associate with the VNet and to contain the private endpoint.

    az network vnet subnet create \
        --resource-group $RESOURCE_GROUP \
        --vnet-name $VNET_NAME \
        --name $SUBNET_NAME \
        --address-prefixes 10.0.0.0/21
    
  3. Retrieve the subnet ID. You use this to create the private endpoint.

    SUBNET_ID=$(az network vnet subnet show \
        --resource-group $RESOURCE_GROUP \
        --vnet-name $VNET_NAME \
        --name $SUBNET_NAME \
        --query "id" \
        --output tsv)
    

Create an environment

  1. Create the Container Apps environment using the VNet deployed in the preceding steps. Private endpoints are only supported by workload profiles environments, which is the default type for new environments.

    az containerapp env create \
        --name $ENVIRONMENT_NAME \
        --resource-group $RESOURCE_GROUP \
        --location $LOCATION
    
  2. Retrieve the environment ID. You use this to configure the environment.

    ENVIRONMENT_ID=$(az containerapp env show \
        --resource-group $RESOURCE_GROUP \
        --name $ENVIRONMENT_NAME \
        --query "id" \
        --output tsv)
    
  3. Disable public network access for the environment. This is needed to enable private endpoints.

    az containerapp env update \
        --id $ENVIRONMENT_ID \
        --public-network-access Disabled
    

Create a private endpoint

Create the private endpoint in the environment and subnet you created previously.

az network private-endpoint create \
    --resource-group $RESOURCE_GROUP \
    --location $LOCATION \
    --name $PRIVATE_ENDPOINT \
    --subnet $SUBNET_ID \
    --private-connection-resource-id $ENVIRONMENT_ID \
    --connection-name $PRIVATE_ENDPOINT_CONNECTION \
    --group-id managedEnvironments

Configure the private DNS zone

  1. Retrieve the private endpoint IP address. You use this to add a DNS record to your private DNS zone.

    PRIVATE_ENDPOINT_IP_ADDRESS=$(az network private-endpoint show \
        --name $PRIVATE_ENDPOINT \
        --resource-group $RESOURCE_GROUP \
        --query 'customDnsConfigs[0].ipAddresses[0]' \
        --output tsv)
    
  2. Retrieve the environment default domain. You use this to add a DNS record to your private DNS zone.

    DNS_RECORD_NAME=$(az containerapp env show \
        --id $ENVIRONMENT_ID \
        --query 'properties.defaultDomain' \
        --output tsv | sed 's/\..*//')
    
  3. Create a private DNS zone.

    az network private-dns zone create \
        --resource-group $RESOURCE_GROUP \
        --name $PRIVATE_DNS_ZONE
    
  4. Create a link between your VNet and your private DNS zone.

    az network private-dns link vnet create \
        --resource-group $RESOURCE_GROUP \
        --zone-name $PRIVATE_DNS_ZONE \
        --name $DNS_LINK \
        --virtual-network $VNET_NAME \
        --registration-enabled false
    
  5. Add a record for your private endpoint to your private DNS zone.

    az network private-dns record-set a add-record \
        --resource-group $RESOURCE_GROUP \
        --zone-name $PRIVATE_DNS_ZONE \
        --record-set-name $DNS_RECORD_NAME \
        --ipv4-address $PRIVATE_ENDPOINT_IP_ADDRESS
    

Deploy a container app

Deploy a container app in your environment. This container app simply uses the quickstart image.

When you browse to the container app endpoint, you receive ERR_CONNECTION_CLOSED because your container app environment has public access disabled. Instead, you access your container app using your private endpoint.

az containerapp up \
    --name $CONTAINERAPP_NAME \
    --resource-group $RESOURCE_GROUP \
    --location $LOCATION \
    --environment $ENVIRONMENT_NAME \
    --image mcr.microsoft.com/k8se/quickstart:latest \
    --target-port 80 \
    --ingress external \
    --query properties.configuration.ingress.fqdn

Verify the private endpoint connection

In this section, you create a virtual machine associated to your VNet so you can access the container app you defined using your private endpoint.

Create a virtual machine (VM)

Begin by signing in to the Azure portal.

  1. Search for Virtual machines in the top search bar.

  2. Select Virtual machines in the search results.

  3. Select Create.

  4. In the Create a virtual machine page on the Basics tab, enter the following values.

    Setting Action
    Subscription Select your Azure subscription.
    Resource group Select my-container-apps.
    Virtual machine name Enter azurevm.
    Region Select Central US.
    Availability options Select No infrastructure redundancy required.
    Security type Select Standard.
    Image Select Windows Server 2022 Datacenter : Azure Edition - x64 Gen2.
    Username Enter azureuser.
    Password Enter a password.
    Confirm password Enter the password again.
    Public inbound ports Select None.
  5. In the Networking tab, enter the following values.

    Setting Action
    Virtual network Select my-private-endpoint-vnet.
    Subnet Select my-private-endpoint-vnet-subnet (10.0.0.0/23).
    Public IP Select None.
    NIC network security group Select Advanced.
  6. Select Review + Create.

  7. Select Create.

Set environment variables

Set the following environment variables.

VM_NAME="azurevm"
VM_ADMIN_USERNAME="azureuser"

Create a virtual machine (VM)

Run the following command.

az vm create \
    --resource-group $RESOURCE_GROUP \
    --name $VM_NAME \
    --image Win2022Datacenter \
    --public-ip-address "" \
    --vnet-name $VNET_NAME \
    --subnet $SUBNET_NAME \
    --admin-username $VM_ADMIN_USERNAME

After you run this command, you're prompted for an administrator password for your VM.

The administrator username must be between 1 and 20 characters long.

The administrator password has the following requirements:

  • Must be between 12 and 123 characters long.
  • Must have 3 of the following: 1 lower case character, 1 upper case character, 1 number, and 1 special character.

Test the connection

  1. Begin by signing in to the Azure portal.

  2. Search for the VM you created in the top search bar and select it from the search results.

  3. In the Overview page for the VM, select Connect, then select Connect via Bastion.

  4. In the Bastion page, select Deploy Bastion.

  5. Set Username and VM Password to the username and password you used when you created the VM.

  6. Select Connect.

  7. After you connect, run PowerShell in the VM.

  8. In PowerShell, run the following command. Replace the <PLACEHOLDERS> with your values.

    nslookup <CONTAINER_APP_ENDPOINT>
    

    The output is similar to the following example, with your values replacing the <PLACEHOLDERS>.

    Server:  UnKnown
    Address:  168.63.129.16
    
    Non-authoritative answer:
    Name:    <ENVIRONMENT_DEFAULT_DOMAIN>.privatelink.<LOCATION>.azurecontainerapps.io
    
    Address:  10.0.0.4
    Aliases:  <CONTAINER_APP_ENDPOINT>
    
  9. Open a browser in the VM.

  10. Browse to the container app endpoint. You see the output for the quickstart container app image.

Clean up resources

If you're not going to continue to use this application, you can remove the my-container-apps resource group. This deletes the Azure Container Apps instance and all associated services. It also deletes the resource group that the Container Apps service automatically created and which contains the custom network components.

Caution

The following command deletes the specified resource group and all resources contained within it. If resources outside the scope of this guide exist in the specified resource group, they will also be deleted.

az group delete --name $RESOURCE_GROUP