Edit

Quickstart: Create a function in Azure from the command line

In this article, you use local command-line tools to create a function that responds to HTTP requests. After verifying your code locally, you deploy it to a serverless Flex Consumption hosting plan in Azure Functions.

Completing this quickstart incurs a small cost of a few USD cents or less in your Azure account.

Make sure to select your preferred development language at the top of the article.

Important

Go support for Azure Functions is currently in public preview. During preview, Go function apps are supported only on the Flex Consumption plan.

Prerequisites

  • Rust toolchain using rustup. Use the rustc --version command to check your version.

Install the Azure Functions Core Tools

The recommended way to install Core Tools depends on the operating system of your local development computer.

The following steps use a Windows installer (MSI) to install Core Tools v4.x. For more information about other package-based installers, see the Core Tools readme.

Download and run the Core Tools installer, based on your version of Windows:

If you previously used Windows installer (MSI) to install Core Tools on Windows, you should uninstall the old version from Add Remove Programs before installing the latest version.

Tip

To install Core Tools on Windows Subsystem for Linux (WSL), follow the instructions on the Linux tab.

Create and activate a virtual environment

In a suitable folder, run the following commands to create and activate a virtual environment named .venv. Make sure to use one of the Python versions supported by Azure Functions.

python -m venv .venv
source .venv/bin/activate

If Python didn't install the venv package on your Linux distribution, run the following command:

sudo apt-get install python3-venv

You run all subsequent commands in this activated virtual environment.

Create a local code project and function

In Azure Functions, your code project is an app that contains one or more individual functions that each respond to a specific trigger. All functions in a project share the same configurations and are deployed as a unit to Azure. In this section, you create a code project that contains a single function.

  1. Run the func init command to create a Go functions project:

    func init MyGoFunctionApp --worker-runtime go
    

    This command creates a project folder named MyGoFunctionApp that includes the following files:

    File Description
    host.json Host configuration for the function app.
    local.settings.json Settings used when running locally.
    main.go Entry point with a sample HTTP-triggered function.
    go.mod Go module file for dependency management.
    go.sum Go module checksum file.
  2. Navigate to the project folder:

    cd MyGoFunctionApp
    
  3. Open main.go to review the generated code. It contains a sample HTTP-triggered function:

    package main
    
    import (
        "log"
        "net/http"
    
        "github.com/azure/azure-functions-golang-worker/sdk"
        "github.com/azure/azure-functions-golang-worker/worker"
    )
    
    // HTTPTriggerHandler handles standard HTTP requests
    func HTTPTriggerHandler(w http.ResponseWriter, r *http.Request) {
        log.Printf("Processing HTTP Trigger for %s", r.URL.Path)
        w.WriteHeader(http.StatusOK)
        w.Write([]byte("Hello from Go Worker!"))
    }
    
    func main() {
        app := sdk.FunctionApp()
        app.HTTP("hello", HTTPTriggerHandler,
            sdk.WithMethods("GET", "POST"),
            sdk.WithAuth("anonymous"),
        )
        worker.Start(app)
    }
    

    Go functions use the standard net/http types (http.ResponseWriter and *http.Request) for HTTP triggers. Functions are registered in main() by using the Go worker SDK and functional options, and no function.json files are needed.

  1. In a terminal or command prompt, run this func init command to create a function app project in the current folder:

    func init --worker-runtime dotnet-isolated 
    
  1. In a terminal or command prompt, run this func init command to create a function app project in the current folder:

    func init --worker-runtime node --language javascript 
    
  1. In a terminal or command prompt, run this func init command to create a function app project in the current folder:

    func init --worker-runtime powershell 
    
  1. In a terminal or command prompt, run this func init command to create a function app project in the current folder:

    func init --worker-runtime python 
    
  1. In a terminal or command prompt, run this func init command to create a function app project in the current folder:

    func init --worker-runtime node --language typescript 
    
  1. In a terminal or command prompt, run this func init command to create a function app project in the current folder:

    func init --worker-runtime custom 
    
  1. In an empty folder, run this mvn command to generate the code project from an Azure Functions Maven archetype:

    mvn archetype:generate -DarchetypeGroupId=com.microsoft.azure -DarchetypeArtifactId=azure-functions-archetype -DjavaVersion=17
    

    Important

    • Use -DjavaVersion=11 if you want your functions to run on Java 11. To learn more, see Java versions.
    • Set the JAVA_HOME environment variable to the install location of the correct version of the JDK to complete this article.
  2. Maven asks you for values needed to finish generating the project on deployment.
    Provide the following values when prompted:

    Prompt Value Description
    groupId com.fabrikam A value that uniquely identifies your project across all projects, following the package naming rules for Java.
    artifactId fabrikam-functions A value that is the name of the jar, without a version number.
    version 1.0-SNAPSHOT Choose the default value.
    package com.fabrikam A value that is the Java package for the generated function code. Use the default.
  3. Type Y or press Enter to confirm.

    Maven creates the project files in a new folder with a name of artifactId, which in this example is fabrikam-functions.

  4. Navigate into the project folder:

    cd fabrikam-functions
    

    You can review the template-generated code for your new HTTP trigger function in Function.java in the \src\main\java\com\fabrikam project directory.

  1. Use this func new command to add a function to your project:

    func new --name HttpExample --template "HTTP trigger" --authlevel "function"
    

    A new code file is added to your project. In this case, the --name argument is the unique name of your function (HttpExample) and the --template argument specifies an HTTP trigger.

The project root folder contains various files for the project, including configurations files named local.settings.json and host.json. Because local.settings.json can contain secrets downloaded from Azure, the file is excluded from source control by default in the .gitignore file.

Create and build your function

The function.json file in the HttpExample folder declares an HTTP trigger function. You complete the function by adding a handler and compiling it into an executable.

  1. Press Ctrl + Shift + ` or select New Terminal from the Terminal menu to open a new integrated terminal in VS Code.

  2. In the function app root (the same folder as host.json), initialize a Rust project named handler.

    cargo init --name handler
    
  3. In Cargo.toml, add the following dependencies necessary to complete this quickstart. The example uses the warp web server framework.

    [dependencies]
    warp = "0.3"
    tokio = { version = "1", features = ["rt", "macros", "rt-multi-thread"] }
    
  4. In src/main.rs, add the following code and save the file. This is your Rust custom handler.

    use std::collections::HashMap;
    use std::env;
    use std::net::Ipv4Addr;
    use warp::{http::Response, Filter};
    
    #[tokio::main]
    async fn main() {
        let example1 = warp::get()
            .and(warp::path("api"))
            .and(warp::path("HttpExample"))
            .and(warp::query::<HashMap<String, String>>())
            .map(|p: HashMap<String, String>| match p.get("name") {
                Some(name) => Response::builder().body(format!("Hello, {}. This HTTP triggered function executed successfully.", name)),
                None => Response::builder().body(String::from("This HTTP triggered function executed successfully. Pass a name in the query string for a personalized response.")),
            });
    
        let port_key = "FUNCTIONS_CUSTOMHANDLER_PORT";
        let port: u16 = match env::var(port_key) {
            Ok(val) => val.parse().expect("Custom Handler port is not a number!"),
            Err(_) => 3000,
        };
    
        warp::serve(example1).run((Ipv4Addr::LOCALHOST, port)).await
    }
    
  5. Compile a binary for your custom handler. An executable file named handler (handler.exe on Windows) is output in the function app root folder.

    cargo build --release
    cp target/release/handler .
    

Configure your function app

The function host needs to be configured to run your custom handler binary when it starts.

  1. Open host.json.

  2. In the customHandler.description section, set the value of defaultExecutablePath to handler (on Windows, set it to handler.exe).

  3. In the customHandler section, add a property named enableForwardingHttpRequest and set its value to true. For functions consisting of only an HTTP trigger, this setting simplifies programming by allow you to work with a typical HTTP request instead of the custom handler request payload.

  4. Confirm the customHandler section looks like this example. Save the file.

    "customHandler": {
      "description": {
        "defaultExecutablePath": "handler",
        "workingDirectory": "",
        "arguments": []
      },
      "enableForwardingHttpRequest": true
    }
    

The function app is configured to start your custom handler executable.

Run the function locally

Verify your new function by running the project locally and calling the function endpoint.

  1. Use this command to start the local Azure Functions runtime host in the root of the project folder:

    func start  
    
    npm install
    npm start
    
    mvn clean package  
    mvn azure-functions:run
    

    Toward the end of the output, the following lines appear:

     ...
    
     Now listening on: http://0.0.0.0:7071
     Application started. Press Ctrl+C to shut down.
    
     Http Functions:
    
             HttpExample: [GET,POST] http://localhost:7071/api/HttpExample
     ...
    
     

    Toward the end of the output, the HTTP endpoint for your function is displayed:

     Functions:
    
             hello: [GET,POST] http://localhost:7071/api/hello
     
  2. Call the function endpoint to verify it works:

    Copy the URL of your HttpExample function from this output to a browser and browse to the function URL. You should receive a success response with a "hello world" message.

    Note

    Because access key authorization isn't enforced when running locally, the function URL returned doesn't include the access key value and you don't need it to call your function.

    With the function running locally, open a browser and navigate to the following URL:

    http://localhost:7071/api/hello
    

    You should see the following response:

    Hello from Go Worker!
    
  3. When you're done, use Ctrl+C and choose y to stop the functions host.

Create supporting Azure resources for your function

Before you can deploy your function code to Azure, you need to create these resources:

  • A resource group, which is a logical container for related resources.
  • A default Storage account, which is used by the Functions host to maintain state and other information about your functions.
  • A user-assigned managed identity, which the Functions host uses to connect to the default storage account.
  • A function app, which provides the environment for executing your function code. A function app maps to your local function project and lets you group functions as a logical unit for easier management, deployment, and sharing of resources.

Use the Azure CLI commands in these steps to create the required resources.

  1. If you haven't done so already, sign in to Azure:

    az login
    

    The az login command signs you into your Azure account. Skip this step when running in Azure Cloud Shell.

  2. If you haven't already done so, use this az extension add command to install the Application Insights extension:

    az extension add --name application-insights
    
  3. Use this az group create command to create a resource group named AzureFunctionsQuickstart-rg in your chosen region:

    az group create --name "AzureFunctionsQuickstart-rg" --location "<REGION>"
    

    In this example, replace <REGION> with a region near you that supports the Flex Consumption plan. Use the az functionapp list-flexconsumption-locations command to view the list of currently supported regions.

  4. Use this az storage account create command to create a general-purpose storage account in your resource group and region:

    az storage account create --name <STORAGE_NAME> --location "<REGION>" --resource-group "AzureFunctionsQuickstart-rg" \
    --sku "Standard_LRS" --allow-blob-public-access false --allow-shared-key-access false
    

    In this example, replace <STORAGE_NAME> with a name that is appropriate to you and unique in Azure Storage. Names must contain three to 24 characters numbers and lowercase letters only. Standard_LRS specifies a general-purpose account, which is supported by Functions. This new account can only be accessed by using Microsoft Entra-authenticated identities that have been granted permissions to specific resources.

  5. Use this script to create a user-assigned managed identity, parse the returned JSON properties of the object using jq, and grant Storage Blob Data Owner permissions in the default storage account:

    output=$(az identity create --name "func-host-storage-user" --resource-group "AzureFunctionsQuickstart-rg" --location <REGION> \
    --query "{userId:id, principalId: principalId, clientId: clientId}" -o json)
    
    userId=$(echo $output | jq -r '.userId')
    principalId=$(echo $output | jq -r '.principalId')
    clientId=$(echo $output | jq -r '.clientId')
    
    storageId=$(az storage account show --resource-group "AzureFunctionsQuickstart-rg" --name <STORAGE_NAME> --query 'id' -o tsv)
    az role assignment create --assignee-object-id $principalId --assignee-principal-type ServicePrincipal \
    --role "Storage Blob Data Owner" --scope $storageId
    

    If you don't have the jq utility in your local Bash shell, it's available in Azure Cloud Shell. In this example, replace <STORAGE_NAME> and <REGION> with your default storage account name and region, respectively.

    The az identity create command creates an identity named func-host-storage-user. The returned principalId is used to assign permissions to this new identity in the default storage account by using the az role assignment create command. The az storage account show command is used to obtain the storage account ID.

  6. Use this az functionapp create command to create the function app in Azure:

    az functionapp create --resource-group "AzureFunctionsQuickstart-rg" --name <APP_NAME> --flexconsumption-location <REGION> \
    --runtime dotnet-isolated --runtime-version <LANGUAGE_VERSION> --storage-account <STORAGE_NAME> \
    --deployment-storage-auth-type UserAssignedIdentity --deployment-storage-auth-value "func-host-storage-user"
    
    az functionapp create --resource-group "AzureFunctionsQuickstart-rg" --name <APP_NAME> --flexconsumption-location <REGION> \
    --runtime java --runtime-version <LANGUAGE_VERSION> --storage-account <STORAGE_NAME> \
    --deployment-storage-auth-type UserAssignedIdentity --deployment-storage-auth-value "func-host-storage-user"
    
    az functionapp create --resource-group "AzureFunctionsQuickstart-rg" --name <APP_NAME> --flexconsumption-location <REGION> \
    --runtime node --runtime-version <LANGUAGE_VERSION> --storage-account <STORAGE_NAME> \
    --deployment-storage-auth-type UserAssignedIdentity --deployment-storage-auth-value "func-host-storage-user"
    
    az functionapp create --resource-group "AzureFunctionsQuickstart-rg" --name <APP_NAME> --flexconsumption-location <REGION> \
    --runtime python --runtime-version <LANGUAGE_VERSION> --storage-account <STORAGE_NAME> \
    --deployment-storage-auth-type UserAssignedIdentity --deployment-storage-auth-value "func-host-storage-user"
    
    az functionapp create --resource-group "AzureFunctionsQuickstart-rg" --name <APP_NAME> --flexconsumption-location <REGION> \
    --runtime python --runtime-version <LANGUAGE_VERSION> --storage-account <STORAGE_NAME> \
    --deployment-storage-auth-type UserAssignedIdentity --deployment-storage-auth-value "func-host-storage-user"
    
    az functionapp create --resource-group "AzureFunctionsQuickstart-rg" --name <APP_NAME> --flexconsumption-location <REGION> \
    --runtime other --storage-account <STORAGE_NAME> \
    --deployment-storage-auth-type UserAssignedIdentity --deployment-storage-auth-value "func-host-storage-user"
    

    In this example, replace these placeholders with the appropriate values:

    • <APP_NAME>: a globally unique name appropriate to you. The <APP_NAME> is also the default DNS domain for the function app.
    • <STORAGE_NAME>: the name of the account you used in the previous step.
    • <REGION>: your current region.
    • <LANGUAGE_VERSION>: use the same supported language stack version you verified locally, when applicable.

    This command creates a function app running in your specified language runtime on Linux in the Flex Consumption Plan, which is free for the amount of usage you incur here. The command also creates an associated Azure Application Insights instance in the same resource group, with which you can use to monitor your function app executions and view logs. For more information, see Monitor Azure Functions. The instance incurs no costs until you activate it.

  7. Use this script to add your user-assigned managed identity to the Monitoring Metrics Publisher role in your Application Insights instance:

    appInsights=$(az monitor app-insights component show --resource-group "AzureFunctionsQuickstart-rg" \
        --app <APP_NAME> --query "id" --output tsv)
    principalId=$(az identity show --name "func-host-storage-user" --resource-group "AzureFunctionsQuickstart-rg" \
        --query principalId -o tsv)
    az role assignment create --role "Monitoring Metrics Publisher" --assignee $principalId --scope $appInsights
    

    In this example, replace <APP_NAME> with the name of your function app. The az role assignment create command adds your user to the role. The resource ID of your Application Insights instance and the principal ID of your user are obtained by using the az monitor app-insights component show and az identity show commands, respectively.

Update application settings

To enable the Functions host to connect to the default storage account by using shared secrets, replace the AzureWebJobsStorage connection string setting with several settings that are prefixed with AzureWebJobsStorage__. These settings define a complex setting that your app uses to connect to storage and Application Insights with a user-assigned managed identity.

  1. Use this script to get the client ID of the user-assigned managed identity and uses it to define managed identity connections to both storage and Application Insights:

    clientId=$(az identity show --name func-host-storage-user \
        --resource-group AzureFunctionsQuickstart-rg --query 'clientId' -o tsv)
    az functionapp config appsettings set --name <APP_NAME> --resource-group "AzureFunctionsQuickstart-rg" \
        --settings AzureWebJobsStorage__accountName=<STORAGE_NAME> \
        AzureWebJobsStorage__credential=managedidentity AzureWebJobsStorage__clientId=$clientId \
        APPLICATIONINSIGHTS_AUTHENTICATION_STRING="ClientId=$clientId;Authorization=AAD"
    

    In this script, replace <APP_NAME> and <STORAGE_NAME> with the names of your function app and storage account, respectively.

  2. Run the az functionapp config appsettings delete command to remove the existing AzureWebJobsStorage connection string setting, which contains a shared secret key:

    az functionapp config appsettings delete --name <APP_NAME> --resource-group "AzureFunctionsQuickstart-rg" --setting-names AzureWebJobsStorage
    

    In this example, replace <APP_NAME> with the names of your function app.

At this point, the Functions host can connect to the storage account securely by using managed identities instead of shared secrets. You can now deploy your project code to the Azure resources.

Create supporting Azure resources for your function

Before you can deploy your function code to Azure, you need to create a resource group, a storage account, and a function app. Use the Azure CLI commands in these steps to create the required resources.

  1. If you haven't done so already, sign in to Azure:

    az login
    

    The az login command signs you into your Azure account. Skip this step when running in Azure Cloud Shell.

  2. Use the az group create command to create a resource group named AzureFunctionsQuickstart-rg in your chosen region:

    az group create --name AzureFunctionsQuickstart-rg --location <REGION>
    

    In this example, replace <REGION> with a region near you that supports the Flex Consumption plan. Use the az functionapp list-flexconsumption-locations command to view the list of currently supported regions.

  3. Use the az storage account create command to create a general-purpose storage account in your resource group and region:

    az storage account create --name <STORAGE_NAME> --location <REGION> --resource-group AzureFunctionsQuickstart-rg --sku Standard_LRS
    

    In this example, replace <STORAGE_NAME> with a globally unique name. Names must contain three to 24 characters and only lowercase letters and numbers.

  4. Create the function app in Azure:

    az functionapp create --resource-group AzureFunctionsQuickstart-rg --name <APP_NAME> --storage-account <STORAGE_NAME> --flexconsumption-location <REGION> --runtime go --runtime-version 1.0 --functions-version 4
    

    Replace <APP_NAME> with a globally unique name and <STORAGE_NAME> with the account name you used in the previous step. This command also creates an associated Azure Application Insights instance in the same resource group, with which you can monitor your function app and view logs. For more information, see Monitor Azure Functions.

  5. Disable HTTP/2 on the function app, which is required during the Go public preview:

    az resource update --resource-group AzureFunctionsQuickstart-rg --resource-type Microsoft.Web/sites --name <APP_NAME> --set properties.siteConfig.http20Enabled=false
    

Deploy the function project to Azure

After you've successfully created your function app in Azure, you're now ready to deploy your local functions project by using the func azure functionapp publish command.

  1. In your root project folder, run this func azure functionapp publish command:

    func azure functionapp publish <APP_NAME>
    

    In this example, replace <APP_NAME> with the name of your app. A successful deployment shows results similar to the following output (truncated for simplicity):

     ...
    
     Getting site publishing info...
     Creating archive for current directory...
     Performing remote build for functions project.
    
     ...
    
     Deployment successful.
     Remote build succeeded!
     Syncing triggers...
     Functions in msdocs-azurefunctions-qs:
         HttpExample - [httpTrigger]
             Invoke url: https://msdocs-azurefunctions-qs.azurewebsites.net/api/httpexample
     
  2. In your local terminal or command prompt, run this command to get the URL endpoint value, including the access key:

    func azure functionapp list-functions <APP_NAME> --show-keys
    

    In this example, again replace <APP_NAME> with the name of your app.

  3. Copy the returned endpoint URL and key, which you use to invoke the function endpoint.

Update the pom.xml file

After you successfully create your function app in Azure, update the pom.xml file so that Maven can deploy to your new app. Otherwise, Maven creates a new set of Azure resources during deployment.

  1. In Azure Cloud Shell, use this az functionapp show command to get the deployment container URL and ID of the new user-assigned managed identity:

    az functionapp show --name <APP_NAME> --resource-group AzureFunctionsQuickstart-rg  \
        --query "{userAssignedIdentityResourceId: properties.functionAppConfig.deployment.storage.authentication.userAssignedIdentityResourceId, \
        containerUrl: properties.functionAppConfig.deployment.storage.value}"
    

    In this example, replace <APP_NAME> with the names of your function app.

  2. In the project root directory, open the pom.xml file in a text editor, locate the properties element, and update these specific property values:

    Property name Value
    java.version Use the same supported language stack version you verified locally, such as 17.
    azure.functions.maven.plugin.version 1.37.1
    azure.functions.java.library.version 3.1.0
    functionAppName The name of your function app in Azure.
  3. Find the configuration section of the azure-functions-maven-plugin and replace it with this XML fragment:

    <configuration>
        <appName>${functionAppName}</appName>
        <resourceGroup>AzureFunctionsQuickstart-rg</resourceGroup>
        <pricingTier>Flex Consumption</pricingTier>
        <region>....</region>
        <runtime>
            <os>linux</os>
            <javaVersion>${java.version}</javaVersion>
        </runtime>
        <deploymentStorageAccount>...</deploymentStorageAccount>
        <deploymentStorageResourceGroup>AzureFunctionsQuickstart-rg</deploymentStorageResourceGroup>
        <deploymentStorageContainer>...</deploymentStorageContainer>
        <storageAuthenticationMethod>UserAssignedIdentity</storageAuthenticationMethod>
        <userAssignedIdentityResourceId>...</userAssignedIdentityResourceId>
        <appSettings>
            <property>
                <name>FUNCTIONS_EXTENSION_VERSION</name>
                <value>~4</value>
            </property>
        </appSettings>
    </configuration>
    
  4. In the new configuration element, make these specific replacements of the ellipses (...) values:

    Configuration Value
    region The region code of your existing function app, such as eastus.
    deploymentStorageAccount The name of your storage account.
    deploymentStorageContainer The name of the deployment share, which comes after the \ in the containerUrl value you obtained.
    userAssignedIdentityResourceId The fully qualified resource ID of your managed identity, which you obtained.
  5. Save your changes to the pom.xml file.

You can now use Maven to deploy your code project to your existing app.

Deploy the function project to Azure

  1. From the command prompt, run this command:

    mvn clean package azure-functions:deploy
    
  2. After your deployment succeeds, run this Core Tools command to get the URL endpoint value, including the access key:

    func azure functionapp list-functions <APP_NAME> --show-keys
    

    In this example, again replace <APP_NAME> with the name of your app.

  3. Copy the returned endpoint URL and key, which you use to invoke the function endpoint.

Deploy the function project to Azure

After you successfully create your function app in Azure, you're ready to deploy your local functions project. Use the func azure functionapp publish command to deploy your project to Azure:

func azure functionapp publish <APP_NAME>

Replace <APP_NAME> with the name of your function app.

Invoke the function on Azure

Because your function uses an HTTP trigger and supports GET requests, you invoke it by making an HTTP request to its URL using the function-level access key. It's easiest to execute a GET request in a browser.

Paste the URL and access key you copied into a browser address bar.

The endpoint URL should look something like this example:

https://contoso-app.azurewebsites.net/api/httpexample?code=aabbccdd...

In this case, you must also provide an access key in the query string when making a GET request to the endpoint URL. Using an access key is recommended to limit access from random clients. When making a POST request using an HTTP client, you should instead provide the access key in the x-functions-key header.

When you navigate to this URL, the browser should display similar output as when you ran the function locally.

Invoke the function on Azure

After deployment completes, open the following URL in a browser to verify that the function runs in Azure:

https://<APP_NAME>.azurewebsites.net/api/hello

You should see the same Hello from Go Worker! response that you saw when you ran the function locally.

Clean up resources

If you continue to the next step and add an Azure Storage queue output binding, keep all your resources in place as you'll build on what you've already done.

Otherwise, use the following command to delete the resource group and all its contained resources to avoid incurring further costs.

az group delete --name AzureFunctionsQuickstart-rg

Clean up resources

If you continue to the next step, keep all resources in place as you build on what you already created.

Otherwise, use the following command to delete the resource group and all its contained resources to avoid incurring further costs.

az group delete --name AzureFunctionsQuickstart-rg

Next steps

For more information about developing Go functions, see the following resources: