Getting started with Azure functions
Back in 2017 or so I seem to remember doing some “Azure Developer” type courses, one of which included writing and deploying an Azure Function. In the last week I have been wrestling with some complex Azure Functions written in C#, targetting dotnet 9.0.
Here are some notes from a Saturday experiment on writing an Azure function, getting it working locally, deploying to Azure Functions using Zip deploy, and configuring for Managed Identity and a ServiceBus trigger.
Notes on my setup
I am working on a Mac Mini, with an M1 (Arm) chip, using Visual Studio. Currently I’m looking to build it using locally-installed binaries, but I will also detail using a Dev Container, and using containers for deployment.
From Develop Azure Functions locally using Core Tools we see:
brew tap azure/functions
brew install azure-functions-core-tools@4
# if upgrading on a machine that has 2.x or 3.x installed:
brew link --overwrite azure-functions-core-tools@4
For me that meant I could run
which func
And see
/opt/homebrew/bin/func
And run:
func --version
Create your local project
The article then suggests
func init MyProjFolder --worker-runtime dotnet-isolated
Note - this is not what I ran - see after the troubleshooting note
No templates or subcommands found matching: ‘func’
I did run into this particular error, as detailed in Issue 4399, and followed the workaround from badsyntax
:
dotnet new globaljson
Edit global.json
, change sdk version to eg 8.0.203
or 9.0.102
Then I was able to:
func init myproject --worker-runtime dotnet-isolated --docker --target-framework net9.0
Execution model comparison
It is worth referring to Differences between the isolated worker model and the in-process model for .NET on Azure Functions
Support ends for the in-process model on November 10, 2026, so I’m choosing to learn the newer way.
Create new function with HTTP Trigger
cd ~/Developer/personal
mkdir -p funcexperiments
cd funcexperiments
dotnet new globaljson
cat global.json
We see that global.json
has
{
"sdk": {
"version": "9.0.300"
}
}
Edit it to be
{
"sdk": {
"version": "9.0.102"
}
}
Run
func new --template "Http Trigger" --name MyHttpTrigger --worker-runtime dotnet-isolated --docker --target-framework net9.0
tree
gives us:
.
├── Dockerfile
├── funcexperiments.csproj
├── global.json
├── host.json
├── local.settings.json
├── MyHttpTrigger.cs
├── obj
│ ├── funcexperiments.csproj.nuget.dgspec.json
│ ├── funcexperiments.csproj.nuget.g.props
│ ├── funcexperiments.csproj.nuget.g.targets
│ ├── project.assets.json
│ └── project.nuget.cache
├── Program.cs
└── Properties
└── launchSettings.json
If we use code2prompt with an exclude
glob pattern code2prompt ./ --exclude="**/obj/*"
, it honours .gitignore
and gives us:
Project Path: funcexperiments
Source Tree:
funcexperiments
├── Dockerfile
├── MyHttpTrigger.cs
├── Program.cs
├── Properties
│ └── launchSettings.json
├── funcexperiments.csproj
├── global.json
├── host.json
├── local.settings.json
└── obj
funcexperiments/Dockerfile
:
FROM mcr.microsoft.com/dotnet/sdk:9.0-preview AS installer-env
COPY . /src/dotnet-function-app
RUN cd /src/dotnet-function-app && \
mkdir -p /home/site/wwwroot && \
dotnet publish *.csproj --output /home/site/wwwroot
# To enable ssh & remote debugging on app service change the base image to the one below
# FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated9.0-appservice
FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated9.0
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
COPY ["/home/site/wwwroot", "/home/site/wwwroot"]
funcexperiments/MyHttpTrigger.cs
:
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace funcexperiments;
public class MyHttpTrigger
{
private readonly ILogger<MyHttpTrigger> _logger;
public MyHttpTrigger(ILogger<MyHttpTrigger> logger)
{
_logger = logger;
}
[Function("MyHttpTrigger")]
public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequest req)
{
_logger.LogInformation("C# HTTP trigger function processed a request.");
return new OkObjectResult("Welcome to Azure Functions!");
}
}
funcexperiments/Program.cs
:
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var builder = FunctionsApplication.CreateBuilder(args);
builder.ConfigureFunctionsWebApplication();
builder.Services
.AddApplicationInsightsTelemetryWorkerService()
.ConfigureFunctionsApplicationInsights();
builder.Build().Run();
funcexperiments/Properties/launchSettings.json
:
{
"profiles": {
"funcexperiments": {
"commandName": "Project",
"commandLineArgs": "--port 7106",
"launchBrowser": false
}
}
}
funcexperiments/funcexperiments.csproj
:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.23.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="2.0.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="2.0.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="2.0.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="2.0.2" />
</ItemGroup>
</Project>
funcexperiments/global.json
:
{
"sdk": {
"version": "9.0.102"
}
}
funcexperiments/host.json
:
{
"version": "2.0",
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
},
"enableLiveMetricsFilters": true
}
}
}
funcexperiments/local.settings.json
:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
}
}
Running func start
looks to do several things, including a dotnet build
, seen by the presence of the ./bin
directory
Determining projects to restore...
All projects are up-to-date for restore.
Determining projects to restore...
Restored /Users/nickromney/Developer/personal/funcexperiments/obj/Debug/net9.0/WorkerExtensions/WorkerExtensions.csproj (in 2.14 sec).
WorkerExtensions -> /Users/nickromney/Developer/personal/funcexperiments/obj/Debug/net9.0/WorkerExtensions/buildout/Microsoft.Azure.Functions.Worker.Extensions.dll
funcexperiments -> /Users/nickromney/Developer/personal/funcexperiments/bin/output/funcexperiments.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:07.25
Azure Functions Core Tools
Core Tools Version: 4.0.7317 Commit hash: N/A +5ca56d37938824531b691f094d0a77fd6f51af20 (64-bit)
Function Runtime Version: 4.1038.300.25164
[2025-05-31T15:04:54.667Z] Found /Users/nickromney/Developer/personal/funcexperiments/funcexperiments.csproj. Using for user secrets file configuration.
[2025-05-31T15:04:55.919Z] Worker process started and initialized.
Functions:
MyHttpTrigger: [GET,POST] http://localhost:7071/api/MyHttpTrigger
For detailed output, run func with --verbose flag.
If we go to the URL in a browser, we see “Welcome to Azure Functions!”, and in the terminal, evidence that the function has been triggered by an HTTP call:
[2025-05-31T15:06:24.375Z] Executing 'Functions.MyHttpTrigger' (Reason='This function was programmatically called via the host APIs.', Id=696ed6e9-5598-4b4c-adf9-1c1c77282a5c)
[2025-05-31T15:06:24.516Z] C# HTTP trigger function processed a request.
[2025-05-31T15:06:24.519Z] Executing OkObjectResult, writing value of type 'System.String'.
[2025-05-31T15:06:24.549Z] Executed 'Functions.MyHttpTrigger' (Succeeded, Id=696ed6e9-5598-4b4c-adf9-1c1c77282a5c, Duration=189ms)
As suggested, let’s run with func start --verbose
Determining projects to restore...
All projects are up-to-date for restore.
Determining projects to restore...
All projects are up-to-date for restore.
WorkerExtensions -> /Users/nickromney/Developer/personal/funcexperiments/obj/Debug/net9.0/WorkerExtensions/buildout/Microsoft.Azure.Functions.Worker.Extensions.dll
funcexperiments -> /Users/nickromney/Developer/personal/funcexperiments/bin/output/funcexperiments.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.31
Selected out-of-process host.
%%%%%%
%%%%%%
@ %%%%%% @
@@ %%%%%% @@
@@@ %%%%%%%%%%% @@@
@@ %%%%%%%%%% @@
@@ %%%% @@
@@ %%% @@
@@ %% @@
%%
%
Azure Functions Core Tools
Core Tools Version: 4.0.7317 Commit hash: N/A +5ca56d37938824531b691f094d0a77fd6f51af20 (64-bit)
Function Runtime Version: 4.1038.300.25164
[2025-05-31T15:10:56.328Z] Found /Users/nickromney/Developer/personal/funcexperiments/funcexperiments.csproj. Using for user secrets file configuration.
[2025-05-31T15:10:56.594Z] Building host: version spec: , startup suppressed: 'False', configuration suppressed: 'False', startup operation id: '3a78566e-c2fc-4686-bb2f-1f7ed72ef11a'
[2025-05-31T15:10:56.620Z] Reading host configuration file '/Users/nickromney/Developer/personal/funcexperiments/bin/output/host.json'
[2025-05-31T15:10:56.621Z] Host configuration file read:
[2025-05-31T15:10:56.621Z] {
[2025-05-31T15:10:56.621Z] "version": "2.0",
[2025-05-31T15:10:56.621Z] "logging": {
[2025-05-31T15:10:56.621Z] "applicationInsights": {
[2025-05-31T15:10:56.621Z] "samplingSettings": {
[2025-05-31T15:10:56.621Z] "isEnabled": true,
[2025-05-31T15:10:56.621Z] "excludedTypes": "Request"
[2025-05-31T15:10:56.621Z] },
[2025-05-31T15:10:56.621Z] "enableLiveMetricsFilters": true
[2025-05-31T15:10:56.621Z] }
[2025-05-31T15:10:56.621Z] }
[2025-05-31T15:10:56.621Z] }
[2025-05-31T15:10:56.637Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: python
[2025-05-31T15:10:56.646Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: java
[2025-05-31T15:10:56.646Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: powershell
[2025-05-31T15:10:56.647Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: node
[2025-05-31T15:10:56.652Z] Extension Bundle not loaded. Loading extensions from /Users/nickromney/Developer/personal/funcexperiments/bin/output. BundleConfigured: False, PrecompiledFunctionApp: False, LegacyBundle: False, DotnetIsolatedApp: True, isLogicApp: False
[2025-05-31T15:10:56.652Z] Script Startup resetting load context with base path: '/Users/nickromney/Developer/personal/funcexperiments/bin/output/.azurefunctions'.
[2025-05-31T15:10:56.654Z] Loading startup extension 'Startup'
[2025-05-31T15:10:56.678Z] Loaded extension 'Startup' (1.0.0.0)
[2025-05-31T15:10:56.687Z] Reading host configuration file '/Users/nickromney/Developer/personal/funcexperiments/bin/output/host.json'
[2025-05-31T15:10:56.687Z] Host configuration file read:
[2025-05-31T15:10:56.687Z] {
[2025-05-31T15:10:56.687Z] "version": "2.0",
[2025-05-31T15:10:56.687Z] "logging": {
[2025-05-31T15:10:56.687Z] "applicationInsights": {
[2025-05-31T15:10:56.687Z] "samplingSettings": {
[2025-05-31T15:10:56.687Z] "isEnabled": true,
[2025-05-31T15:10:56.687Z] "excludedTypes": "Request"
[2025-05-31T15:10:56.687Z] },
[2025-05-31T15:10:56.687Z] "enableLiveMetricsFilters": true
[2025-05-31T15:10:56.687Z] }
[2025-05-31T15:10:56.687Z] }
[2025-05-31T15:10:56.687Z] }
[2025-05-31T15:10:56.711Z] Starting host metrics provider.
[2025-05-31T15:10:56.774Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: python
[2025-05-31T15:10:56.774Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: java
[2025-05-31T15:10:56.775Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: powershell
[2025-05-31T15:10:56.775Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: node
[2025-05-31T15:10:56.776Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: python
[2025-05-31T15:10:56.776Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: java
[2025-05-31T15:10:56.776Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: powershell
[2025-05-31T15:10:56.776Z] FUNCTIONS_WORKER_RUNTIME set to dotnet-isolated. Skipping WorkerConfig for language: node
[2025-05-31T15:10:56.802Z] Initializing Warmup Extension.
[2025-05-31T15:10:56.825Z] Initializing Host. OperationId: '3a78566e-c2fc-4686-bb2f-1f7ed72ef11a'.
[2025-05-31T15:10:56.829Z] Host initialization: ConsecutiveErrors=0, StartupCount=1, OperationId=3a78566e-c2fc-4686-bb2f-1f7ed72ef11a
[2025-05-31T15:10:56.844Z] Loading functions metadata
[2025-05-31T15:10:56.845Z] Worker indexing is enabled
[2025-05-31T15:10:56.846Z] Fetching metadata for workerRuntime: dotnet-isolated
[2025-05-31T15:10:56.846Z] Reading functions metadata (Worker)
[2025-05-31T15:10:57.213Z] {
[2025-05-31T15:10:57.213Z] "ProcessId": 57263,
[2025-05-31T15:10:57.213Z] "RuntimeIdentifier": "osx-arm64",
[2025-05-31T15:10:57.213Z] "WorkerVersion": "2.0.0.0",
[2025-05-31T15:10:57.213Z] "ProductVersion": "2.0.0\u002Bd8b5fe998a8c92819b8ee41d2569d2525413e9c5",
[2025-05-31T15:10:57.213Z] "FrameworkDescription": ".NET 9.0.5",
[2025-05-31T15:10:57.213Z] "OSDescription": "Darwin 24.5.0 Darwin Kernel Version 24.5.0: Tue Apr 22 19:48:46 PDT 2025; root:xnu-11417.121.6~2/RELEASE_ARM64_T8103",
[2025-05-31T15:10:57.213Z] "OSArchitecture": "Arm64",
[2025-05-31T15:10:57.213Z] "CommandLine": "/Users/nickromney/Developer/personal/funcexperiments/bin/output/funcexperiments.dll --host 127.0.0.1 --port 52378 --workerId a07e9554-9a4f-4638-9936-b0e6ec4d8ff0 --requestId f1987092-4b4c-4b11-9bf7-6bb04db04ca1 --grpcMaxMessageLength 2147483647 --functions-uri http://127.0.0.1:52378/ --functions-worker-id a07e9554-9a4f-4638-9936-b0e6ec4d8ff0 --functions-request-id f1987092-4b4c-4b11-9bf7-6bb04db04ca1 --functions-grpc-max-message-length 2147483647"
[2025-05-31T15:10:57.213Z] }
[2025-05-31T15:10:57.312Z] 1 functions found (Worker)
[2025-05-31T15:10:57.317Z] Reading functions metadata (Custom)
[2025-05-31T15:10:57.321Z] 0 functions found (Custom)
[2025-05-31T15:10:57.324Z] 1 functions loaded
[2025-05-31T15:10:57.326Z] LoggerFilterOptions
[2025-05-31T15:10:57.326Z] {
[2025-05-31T15:10:57.326Z] "MinLevel": "None",
[2025-05-31T15:10:57.326Z] "Rules": [
[2025-05-31T15:10:57.326Z] {
[2025-05-31T15:10:57.326Z] "ProviderName": null,
[2025-05-31T15:10:57.326Z] "CategoryName": "Microsoft.Hosting.Lifetime",
[2025-05-31T15:10:57.326Z] "LogLevel": "None",
[2025-05-31T15:10:57.326Z] "Filter": null
[2025-05-31T15:10:57.326Z] },
[2025-05-31T15:10:57.326Z] {
[2025-05-31T15:10:57.326Z] "ProviderName": "Azure.Functions.Cli.Diagnostics.ColoredConsoleLoggerProvider",
[2025-05-31T15:10:57.326Z] "CategoryName": null,
[2025-05-31T15:10:57.326Z] "LogLevel": "None",
[2025-05-31T15:10:57.326Z] "Filter": null
[2025-05-31T15:10:57.326Z] },
[2025-05-31T15:10:57.326Z] {
[2025-05-31T15:10:57.326Z] "ProviderName": "Azure.Functions.Cli.Diagnostics.ColoredConsoleLoggerProvider",
[2025-05-31T15:10:57.326Z] "CategoryName": null,
[2025-05-31T15:10:57.326Z] "LogLevel": null,
[2025-05-31T15:10:57.326Z] "Filter": "<AddFilter>b__0"
[2025-05-31T15:10:57.326Z] },
[2025-05-31T15:10:57.326Z] {
[2025-05-31T15:10:57.326Z] "ProviderName": null,
[2025-05-31T15:10:57.326Z] "CategoryName": null,
[2025-05-31T15:10:57.326Z] "LogLevel": null,
[2025-05-31T15:10:57.326Z] "Filter": "<AddFilter>b__0"
[2025-05-31T15:10:57.326Z] },
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": null,
[2025-05-31T15:10:57.327Z] "CategoryName": null,
[2025-05-31T15:10:57.327Z] "LogLevel": null,
[2025-05-31T15:10:57.327Z] "Filter": "<AddFilter>b__0"
[2025-05-31T15:10:57.327Z] },
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.SystemLoggerProvider",
[2025-05-31T15:10:57.327Z] "CategoryName": null,
[2025-05-31T15:10:57.327Z] "LogLevel": "None",
[2025-05-31T15:10:57.327Z] "Filter": null
[2025-05-31T15:10:57.327Z] },
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.SystemLoggerProvider",
[2025-05-31T15:10:57.327Z] "CategoryName": null,
[2025-05-31T15:10:57.327Z] "LogLevel": null,
[2025-05-31T15:10:57.327Z] "Filter": "<AddFilter>b__0"
[2025-05-31T15:10:57.327Z] },
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": "Azure.Functions.Cli.Diagnostics.ColoredConsoleLoggerProvider",
[2025-05-31T15:10:57.327Z] "CategoryName": null,
[2025-05-31T15:10:57.327Z] "LogLevel": null,
[2025-05-31T15:10:57.327Z] "Filter": "<AddFilter>b__0"
[2025-05-31T15:10:57.327Z] }
[2025-05-31T15:10:57.327Z] ]
[2025-05-31T15:10:57.327Z] }
[2025-05-31T15:10:57.327Z] LoggerFilterOptions
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "MinLevel": "None",
[2025-05-31T15:10:57.327Z] "Rules": [
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": null,
[2025-05-31T15:10:57.327Z] "CategoryName": "Microsoft.Hosting.Lifetime",
[2025-05-31T15:10:57.327Z] "LogLevel": "None",
[2025-05-31T15:10:57.327Z] "Filter": null
[2025-05-31T15:10:57.327Z] },
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": "Azure.Functions.Cli.Diagnostics.ColoredConsoleLoggerProvider",
[2025-05-31T15:10:57.327Z] "CategoryName": null,
[2025-05-31T15:10:57.327Z] "LogLevel": "None",
[2025-05-31T15:10:57.327Z] "Filter": null
[2025-05-31T15:10:57.327Z] },
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": "Azure.Functions.Cli.Diagnostics.ColoredConsoleLoggerProvider",
[2025-05-31T15:10:57.327Z] "CategoryName": null,
[2025-05-31T15:10:57.327Z] "LogLevel": null,
[2025-05-31T15:10:57.327Z] "Filter": "<AddFilter>b__0"
[2025-05-31T15:10:57.327Z] },
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": null,
[2025-05-31T15:10:57.327Z] "CategoryName": null,
[2025-05-31T15:10:57.327Z] "LogLevel": null,
[2025-05-31T15:10:57.327Z] "Filter": "<AddFilter>b__0"
[2025-05-31T15:10:57.327Z] },
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": null,
[2025-05-31T15:10:57.327Z] "CategoryName": null,
[2025-05-31T15:10:57.327Z] "LogLevel": null,
[2025-05-31T15:10:57.327Z] "Filter": "<AddFilter>b__0"
[2025-05-31T15:10:57.327Z] },
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.SystemLoggerProvider",
[2025-05-31T15:10:57.327Z] "CategoryName": null,
[2025-05-31T15:10:57.327Z] "LogLevel": "None",
[2025-05-31T15:10:57.327Z] "Filter": null
[2025-05-31T15:10:57.327Z] },
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.SystemLoggerProvider",
[2025-05-31T15:10:57.327Z] "CategoryName": null,
[2025-05-31T15:10:57.327Z] "LogLevel": null,
[2025-05-31T15:10:57.327Z] "Filter": "<AddFilter>b__0"
[2025-05-31T15:10:57.327Z] },
[2025-05-31T15:10:57.327Z] {
[2025-05-31T15:10:57.327Z] "ProviderName": "Azure.Functions.Cli.Diagnostics.ColoredConsoleLoggerProvider",
[2025-05-31T15:10:57.328Z] "CategoryName": null,
[2025-05-31T15:10:57.328Z] "LogLevel": null,
[2025-05-31T15:10:57.328Z] "Filter": "<AddFilter>b__0"
[2025-05-31T15:10:57.328Z] }
[2025-05-31T15:10:57.328Z] ]
[2025-05-31T15:10:57.328Z] }
[2025-05-31T15:10:57.328Z] LanguageWorkerOptions
[2025-05-31T15:10:57.328Z] {
[2025-05-31T15:10:57.328Z] "WorkerConfigs": [
[2025-05-31T15:10:57.328Z] {
[2025-05-31T15:10:57.328Z] "Description": {
[2025-05-31T15:10:57.328Z] "Language": "dotnet-isolated",
[2025-05-31T15:10:57.328Z] "DefaultRuntimeName": null,
[2025-05-31T15:10:57.328Z] "DefaultRuntimeVersion": null,
[2025-05-31T15:10:57.328Z] "SupportedArchitectures": null,
[2025-05-31T15:10:57.328Z] "SupportedOperatingSystems": null,
[2025-05-31T15:10:57.328Z] "SupportedRuntimeVersions": null,
[2025-05-31T15:10:57.328Z] "SanitizeRuntimeVersionRegex": null,
[2025-05-31T15:10:57.328Z] "WorkerIndexing": "true",
[2025-05-31T15:10:57.328Z] "Extensions": [
[2025-05-31T15:10:57.328Z] ".dll"
[2025-05-31T15:10:57.328Z] ],
[2025-05-31T15:10:57.328Z] "UseStdErrorStreamForErrorsOnly": false,
[2025-05-31T15:10:57.328Z] "DefaultExecutablePath": "dotnet",
[2025-05-31T15:10:57.328Z] "DefaultWorkerPath": "/Users/nickromney/Developer/personal/funcexperiments/bin/output/funcexperiments.dll",
[2025-05-31T15:10:57.328Z] "WorkerDirectory": "/Users/nickromney/Developer/personal/funcexperiments/bin/output",
[2025-05-31T15:10:57.328Z] "Arguments": [],
[2025-05-31T15:10:57.328Z] "WorkerArguments": null,
[2025-05-31T15:10:57.328Z] "IsDisabled": null
[2025-05-31T15:10:57.328Z] },
[2025-05-31T15:10:57.328Z] "Arguments": {
[2025-05-31T15:10:57.328Z] "ExecutablePath": "dotnet",
[2025-05-31T15:10:57.328Z] "ExecutableArguments": [],
[2025-05-31T15:10:57.328Z] "WorkerPath": "/Users/nickromney/Developer/personal/funcexperiments/bin/output/funcexperiments.dll",
[2025-05-31T15:10:57.328Z] "WorkerArguments": []
[2025-05-31T15:10:57.328Z] },
[2025-05-31T15:10:57.328Z] "CountOptions": {
[2025-05-31T15:10:57.328Z] "SetProcessCountToNumberOfCpuCores": false,
[2025-05-31T15:10:57.328Z] "ProcessCount": 1,
[2025-05-31T15:10:57.328Z] "MaxProcessCount": 10,
[2025-05-31T15:10:57.328Z] "ProcessStartupInterval": "00:00:10",
[2025-05-31T15:10:57.328Z] "ProcessStartupTimeout": "00:01:00",
[2025-05-31T15:10:57.328Z] "InitializationTimeout": "00:00:10",
[2025-05-31T15:10:57.328Z] "EnvironmentReloadTimeout": "00:00:30",
[2025-05-31T15:10:57.328Z] "ProcessRestartInterval": "00:00:10",
[2025-05-31T15:10:57.328Z] "ProcessShutdownTimeout": "00:00:10"
[2025-05-31T15:10:57.328Z] }
[2025-05-31T15:10:57.328Z] }
[2025-05-31T15:10:57.328Z] ]
[2025-05-31T15:10:57.328Z] }
[2025-05-31T15:10:57.328Z] FunctionResultAggregatorOptions
[2025-05-31T15:10:57.328Z] {
[2025-05-31T15:10:57.328Z] "BatchSize": 1000,
[2025-05-31T15:10:57.328Z] "FlushTimeout": "00:00:30",
[2025-05-31T15:10:57.328Z] "IsEnabled": true
[2025-05-31T15:10:57.328Z] }
[2025-05-31T15:10:57.328Z] ConcurrencyOptions
[2025-05-31T15:10:57.328Z] {
[2025-05-31T15:10:57.328Z] "DynamicConcurrencyEnabled": false,
[2025-05-31T15:10:57.328Z] "MaximumFunctionConcurrency": 500,
[2025-05-31T15:10:57.328Z] "CPUThreshold": 0.8,
[2025-05-31T15:10:57.328Z] "SnapshotPersistenceEnabled": true
[2025-05-31T15:10:57.328Z] }
[2025-05-31T15:10:57.328Z] SingletonOptions
[2025-05-31T15:10:57.328Z] {
[2025-05-31T15:10:57.329Z] "LockPeriod": "00:00:15",
[2025-05-31T15:10:57.329Z] "ListenerLockPeriod": "00:00:15",
[2025-05-31T15:10:57.329Z] "LockAcquisitionTimeout": "10675199.02:48:05.4775807",
[2025-05-31T15:10:57.329Z] "LockAcquisitionPollingInterval": "00:00:05",
[2025-05-31T15:10:57.329Z] "ListenerLockRecoveryPollingInterval": "00:01:00"
[2025-05-31T15:10:57.329Z] }
[2025-05-31T15:10:57.329Z] ScaleOptions
[2025-05-31T15:10:57.329Z] {
[2025-05-31T15:10:57.329Z] "ScaleMetricsMaxAge": "00:02:00",
[2025-05-31T15:10:57.329Z] "ScaleMetricsSampleInterval": "00:00:10",
[2025-05-31T15:10:57.329Z] "MetricsPurgeEnabled": true,
[2025-05-31T15:10:57.329Z] "IsTargetScalingEnabled": true,
[2025-05-31T15:10:57.329Z] "IsRuntimeScalingEnabled": false
[2025-05-31T15:10:57.329Z] }
[2025-05-31T15:10:57.329Z] Starting JobHost
[2025-05-31T15:10:57.331Z] Starting Host (HostId=nicksmacmini-272155989, InstanceId=55cd622a-3a57-4922-b0e1-330876900dc6, Version=4.1038.300.25164, ProcessId=57223, AppDomainId=1, InDebugMode=False, InDiagnosticMode=False, FunctionsExtensionVersion=(null))
[2025-05-31T15:10:57.350Z] Generating 1 job function(s)
[2025-05-31T15:10:57.350Z] Worker process started and initialized.
[2025-05-31T15:10:57.368Z] Found the following functions:
[2025-05-31T15:10:57.368Z] Host.Functions.MyHttpTrigger
[2025-05-31T15:10:57.368Z]
[2025-05-31T15:10:57.372Z] HttpOptions
[2025-05-31T15:10:57.372Z] {
[2025-05-31T15:10:57.372Z] "DynamicThrottlesEnabled": false,
[2025-05-31T15:10:57.372Z] "EnableChunkedRequestBinding": false,
[2025-05-31T15:10:57.372Z] "MaxConcurrentRequests": -1,
[2025-05-31T15:10:57.372Z] "MaxOutstandingRequests": -1,
[2025-05-31T15:10:57.372Z] "RoutePrefix": "api"
[2025-05-31T15:10:57.372Z] }
[2025-05-31T15:10:57.372Z] Initializing function HTTP routes
[2025-05-31T15:10:57.372Z] Mapped function route 'api/MyHttpTrigger' [get,post] to 'MyHttpTrigger'
[2025-05-31T15:10:57.372Z]
[2025-05-31T15:10:57.375Z] Host initialized (40ms)
[2025-05-31T15:10:57.376Z] Host started (43ms)
[2025-05-31T15:10:57.376Z] Job host started
Functions:
MyHttpTrigger: [GET,POST] http://localhost:7071/api/MyHttpTrigger
Then if we go to the local URL, the logs will show:
[2025-05-31T15:12:14.629Z] Executing HTTP request: {
[2025-05-31T15:12:14.629Z] "requestId": "03406dca-26f9-46e3-9aa3-b1087f1c7a39",
[2025-05-31T15:12:14.629Z] "method": "GET",
[2025-05-31T15:12:14.629Z] "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
[2025-05-31T15:12:14.629Z] "uri": "/api/MyHttpTrigger"
[2025-05-31T15:12:14.629Z] }
[2025-05-31T15:12:14.733Z] Executing 'Functions.MyHttpTrigger' (Reason='This function was programmatically called via the host APIs.', Id=b78bab00-1013-4801-b3ea-06ec142b200b)
[2025-05-31T15:12:14.820Z] C# HTTP trigger function processed a request.
[2025-05-31T15:12:14.823Z] Executing OkObjectResult, writing value of type 'System.String'.
[2025-05-31T15:12:14.847Z] Executed 'Functions.MyHttpTrigger' (Succeeded, Id=b78bab00-1013-4801-b3ea-06ec142b200b, Duration=126ms)
[2025-05-31T15:12:14.853Z] Executed HTTP request: {
[2025-05-31T15:12:14.853Z] "requestId": "03406dca-26f9-46e3-9aa3-b1087f1c7a39",
[2025-05-31T15:12:14.853Z] "identities": "(WebJobsAuthLevel:Admin)",
[2025-05-31T15:12:14.853Z] "status": "200",
[2025-05-31T15:12:14.853Z] "duration": "224"
[2025-05-31T15:12:14.853Z] }
Building the container locally
The generated Dockerfile was
FROM mcr.microsoft.com/dotnet/sdk:9.0-preview AS installer-env
COPY . /src/dotnet-function-app
RUN cd /src/dotnet-function-app && \
mkdir -p /home/site/wwwroot && \
dotnet publish *.csproj --output /home/site/wwwroot
# To enable ssh & remote debugging on app service change the base image to the one below
# FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated9.0-appservice
FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated9.0
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
AzureFunctionsJobHost__Logging__Console__IsEnabled=true
COPY ["/home/site/wwwroot", "/home/site/wwwroot"]
Normally we would expect to be able to build with
docker build --tag func:v1.0.0 .
But if we do that with our global.json
in place we get this output
=> ERROR [3/3] RUN cd /src/dotnet-function-app && mkdir -p /home/site/wwwroot && dotnet publish *.csproj --output /home/site/wwwroot 0.1s
------
> [3/3] RUN cd /src/dotnet-function-app && mkdir -p /home/site/wwwroot && dotnet publish *.csproj --output /home/site/wwwroot:
0.045 The command could not be loaded, possibly because:
0.045 * You intended to execute a .NET application:
0.045 The application 'publish' does not exist.
0.045 * You intended to execute a .NET SDK command:
0.045 A compatible .NET SDK was not found.
0.045
0.045 Requested SDK version: 9.0.102
0.045 global.json file: /src/dotnet-function-app/global.json
0.045
0.045 Installed SDKs:
0.045
0.045 Install the [9.0.102] .NET SDK or update [/src/dotnet-function-app/global.json] to match an installed SDK.
0.045
0.045 Learn about SDK resolution:
0.045 https://aka.ms/dotnet/sdk-not-found
0.045 9.0.100-preview.7.24407.12 [/usr/share/dotnet/sdk]
If we remove the global.json
and rebuild we “fail further”, with:
[+] Building 27.4s (10/10) FINISHED docker-container:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 729B 0.0s
=> [internal] load metadata for mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated9.0 0.2s
=> [internal] load metadata for mcr.microsoft.com/dotnet/sdk:9.0-preview 0.2s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> CACHED [stage-1 1/2] FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated9.0@sha256:74b8891e7e2cef34da7037c33f07480dc0c1f417b69b8be251a6ecc2af1bf9ea 0.0s
=> => resolve mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated9.0@sha256:74b8891e7e2cef34da7037c33f07480dc0c1f417b69b8be251a6ecc2af1bf9ea 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 56.89kB 0.0s
=> CACHED [installer-env 1/3] FROM mcr.microsoft.com/dotnet/sdk:9.0-preview@sha256:241df9f9fd6365ed075ffcf8db22e16276683feed4cc1caa6c3a4a631a38e5ae 0.0s
=> => resolve mcr.microsoft.com/dotnet/sdk:9.0-preview@sha256:241df9f9fd6365ed075ffcf8db22e16276683feed4cc1caa6c3a4a631a38e5ae 0.0s
=> [installer-env 2/3] COPY . /src/dotnet-function-app 0.3s
=> [installer-env 3/3] RUN cd /src/dotnet-function-app && mkdir -p /home/site/wwwroot && dotnet publish *.csproj --output /home/site/wwwroot 26.8s
=> [stage-1 2/2] COPY --from=installer-env [/home/site/wwwroot, /home/site/wwwroot] 0.0s
WARNING: No output specified with docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load
View build details: docker-desktop://dashboard/build/default/default/vt0isz41yiscuuqov20uj060u
1 warning found (use docker --debug to expand):
- InvalidBaseImagePlatform: Base image mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated9.0 was pulled with platform "linux/amd64", expected "linux/arm64" for current build (line 10)
There is a discussion on the azure-funtions-docker project as to some workarounds
Passing the architecture looked to be almost there:
docker build --platform linux/amd64 --tag funcasb:v1.0.0 .
But failed towards the end with a QEMU issue:
=> ERROR [installer-env 3/3] RUN cd /src/dotnet-function-app && mkdir -p /home/site/wwwroot && dotnet publish *.csproj --output /home/site/wwwroot 0.0s
------
> [installer-env 3/3] RUN cd /src/dotnet-function-app && mkdir -p /home/site/wwwroot && dotnet publish *.csproj --output /home/site/wwwroot:
------
WARNING: No output specified with docker-container driver. Build result will only remain in the build cache. To push result image into registry use --push or to load image into docker use --load
Dockerfile:4
--------------------
3 | COPY . /src/dotnet-function-app
4 | >>> RUN cd /src/dotnet-function-app && \
5 | >>> mkdir -p /home/site/wwwroot && \
6 | >>> dotnet publish *.csproj --output /home/site/wwwroot
7 |
--------------------
ERROR: failed to solve: process "/dev/.buildkit_qemu_emulator /bin/sh -c cd /src/dotnet-function-app && mkdir -p /home/site/wwwroot && dotnet publish *.csproj --output /home/site/wwwroot" did not complete successfully: failed to copy xattrs: failed to set xattr "security.selinux" on /tmp/buildkit-qemu-emulator2001177974/dev/.buildkit_qemu_emulator: operation not supported
However, Podman had better support for QEMU:
podman build --platform linux/amd64 --tag funcasb:v1.0.0 .
This completed with
[1/2] STEP 1/3: FROM mcr.microsoft.com/dotnet/sdk:9.0-preview AS installer-env
Trying to pull mcr.microsoft.com/dotnet/sdk:9.0-preview...
Getting image source signatures
Copying blob sha256:f88cdf002049cb0e158db0a0e3924bc51fc6b8c55146f271da8884206b4fec5b
Copying blob sha256:17b1ebe9914e37626333b0bd99a0aadef524a569838764c2fd07a298a26fbed5
Copying blob sha256:5d622b182d9795def4b9b26079c10f7bf9894bf3711dbc3ff38faf179c0036bd
Copying blob sha256:24f7a1fc2b4940975fa942d9015fba6f9784bd20995f00dae48048fc9a3bb5fd
Copying blob sha256:a2318d6c47ec9cac5acc500c47c79602bcf953cec711a18bc898911a0984365b
Copying blob sha256:340611782603ab0bb45d9846e3673973c1d2cd331b21ac1daa6e779dcd57df9a
Copying blob sha256:608c1aabfc3b8f5ad333e1cb9cda0df8e35d9f130d50d942673b0ba2ab197eb2
Copying blob sha256:389d96c749ff94f89d4b59589a13f9ae111b74684ed4874f48cec02d955e2686
Copying blob sha256:7ed5695080334cf8d13b3e53a6174012a3aacb27a9209a4859e055796086853c
Copying config sha256:cb0d8de1b4ea298e62f149de92c56f1fbb80c9eb9ba03976ac206e2371c55c0d
Writing manifest to image destination
[1/2] STEP 2/3: COPY . /src/dotnet-function-app
--> 94a8c15faed9
[1/2] STEP 3/3: RUN cd /src/dotnet-function-app && mkdir -p /home/site/wwwroot && dotnet publish *.csproj --output /home/site/wwwroot
Determining projects to restore...
Restored /src/dotnet-function-app/MyFunctionApp.csproj (in 21.84 sec).
/usr/share/dotnet/sdk/9.0.100-preview.7.24407.12/Sdks/Microsoft.NET.Sdk/targets/Microsoft.NET.RuntimeIdentifierInference.targets(326,5): message NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy [/src/dotnet-function-app/MyFunctionApp.csproj]
Determining projects to restore...
Restored /src/dotnet-function-app/obj/Release/net9.0/WorkerExtensions/WorkerExtensions.csproj (in 10.59 sec).
WorkerExtensions -> /src/dotnet-function-app/obj/Release/net9.0/WorkerExtensions/buildout/Microsoft.Azure.Functions.Worker.Extensions.dll
MyFunctionApp -> /src/dotnet-function-app/bin/Release/net9.0/MyFunctionApp.dll
MyFunctionApp -> /home/site/wwwroot/
--> 8b5f1b2b297b
[2/2] STEP 1/3: FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated9.0
Trying to pull mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated9.0...
Getting image source signatures
Copying blob sha256:54a79b02e795174b13f99931f8a31f401464ac945ff67b7bef0d9fe4d70634d2
Copying blob sha256:0022984bc3f7a6df0ffd4ce42695a3dab09977f03ef67590b0e6fad03d6b6678
Copying blob sha256:61320b01ae5e0798393ef25f2dc72faf43703e60ba089b07d7170acbabbf8f62
Copying blob sha256:6a8895a0ba52c740865875fa34dbc2a3b09a5c89e6cf3479d3b2175f842c2fcd
Copying blob sha256:79714b2f18d502816627610458cbad07b53d7d723dae1cd29fa3dec387af12c3
Copying blob sha256:152867e67c592cf36ffe546b8ab320a4fd64a8f82b596be7bb339f0103fe4f30
Copying blob sha256:2568c5dff37adcf7bbffa5d7bf722eb67ac1a5c76bdc22e1a3b8c5c39d2685ac
Copying blob sha256:5f69367816298655177482e58b82feeba0ce322980149700020b7e2f1f08b80a
Copying blob sha256:32eb6ffc2fca4ce298a77b9e614c9f369b02b2f0b1c282fa9da3ad90d039a5cd
Copying blob sha256:b68abd424bd7cda8a9c7f575f5c57be2d670e5ab359355c8f0f506f1999e9fa5
Copying blob sha256:8b2f93b3e03bd3a9f1fd0c88cc45e2178b14369ec7c4b33046d30cb45a8a7baa
Copying blob sha256:9a9e47a92bc1738f782d2e950d337b36285c2dc5563e40cbe74d73063b0e5ead
Copying blob sha256:21b826a6f5a943227cf0208e920310b670ebd9ed8367add74e5ab8ac36b4baf0
Copying blob sha256:bb06343686edddf8dabae4f1f5a70fb69ced0b07ded7710a43152b1fe62630eb
Copying blob sha256:859a95522ef522c9529c5057f8c4cbe3597a5ce3495d8e879200f47322e2d342
Copying blob sha256:fe7824f4e14fd420ece4139267b2bd1e7feae5bb7344a57eeb4d8acb45d42b9c
Copying config sha256:19720b3c57f1ffe98e39619bb712931b2ddea441675730a9170673a4b7b1790a
Writing manifest to image destination
[2/2] STEP 2/3: ENV AzureWebJobsScriptRoot=/home/site/wwwroot AzureFunctionsJobHost__Logging__Console__IsEnabled=true
--> 932f0bfa5e13
[2/2] STEP 3/3: COPY --from=installer-env ["/home/site/wwwroot", "/home/site/wwwroot"]
[2/2] COMMIT funcasb:v1.0.0
--> f8e02ec11569
Successfully tagged localhost/funcasb:v1.0.0
f8e02ec115691f3b73b0ac85e0e8972b971c1817530565d28db0ae78b2bdf7f7