Azure / azure-functions-docker

This repo contains the base Docker images for working with azure functions
MIT License
258 stars 117 forks source link

Docker image 4-python3.8 does not work with both FastAPI and other triggers #982

Open nordange opened 10 months ago

nordange commented 10 months ago

Until last week a FastAPI app (AsgiFunctionApp) could be combined with other trigger triggers (timer, queue etc.) without problems. Docker image 4.24.4-python3.8 works fine, both 4-python3.8 does not.

No job functions can be found with the latest image, running the build image both locally and on Azure. The previous image works fine.

The latest image works with the FastAPI app only or the time trigger only, but not the combination of them.

Latest build does not work: FROM mcr.microsoft.com/azure-functions/python:4-python3.8 Previous version works FROM mcr.microsoft.com/azure-functions/python:4.24.4-python3.8

Error:

info: Microsoft.Azure.WebJobs.Hosting.JobHostService[0]
      Starting JobHost
info: Host.Startup[401]
      Starting Host (HostId=a23694ad0c92-2137340777, InstanceId=6d81be77-bf73-4702-9fc4-9acc8df474af, Version=4.27.4.4, ProcessId=1, AppDomainId=1, InDebugMode=False, InDiagnosticMode=False, FunctionsExtensionVersion=(null))
info: Host.Startup[314]
      Loading functions metadata
info: Host.Startup[326]
      Reading functions metadata (Custom)
info: Host.Startup[327]
      1 functions found (Custom)
info: Host.Startup[315]
      0 functions loaded
info: Host.Startup[0]
      Generating 0 job function(s)
warn: Host.Startup[0]
      No job functions found. Try making your job classes and methods public. If you're using binding extensions (e.g. Azure Storage, ServiceBus, Timers, etc.) make sure you've called the registration method for the extension(s) in your startup code (e.g. builder.AddAzureStorage(), builder.AddServiceBus(), builder.AddTimers(), etc.).

My Dockerfile:

#FROM mcr.microsoft.com/azure-functions/python:4-python3.8 # does not work
FROM mcr.microsoft.com/azure-functions/python:4.24.4-python3.8 # works

EXPOSE 80

ENV AzureWebJobsScriptRoot=/home/site/wwwroot
ENV AzureFunctionsJobHost__Logging__Console__IsEnabled=true
ENV AzureWebJobsFeatureFlags=EnableWorkerIndexing 
ENV AzureWebJobsStorage="AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;DefaultEndpointsProtocol=http;BlobEndpoint=http://host.docker.internal:10000/devstoreaccount1;QueueEndpoint=http://host.docker.internal:10001/devstoreaccount1;TableEndpoint=http://host.docker.internal:10002/devstoreaccount1;"

COPY requirements.txt /
RUN pip install -r /requirements.txt

COPY . /home/site/wwwroot`

My function_app.py

import azure.functions as func
from fastapi import FastAPI
import logging

fastapi_app = FastAPI()

app = func.AsgiFunctionApp(app=fastapi_app, http_auth_level=func.AuthLevel.ANONYMOUS)

@fastapi_app.get("/hello/{name}")
async def get_name(name: str):
    return {"name": name}

@app.function_name(name="SimpleTimer")
@app.schedule(schedule="*/2 * * * *", arg_name="mytimer", run_on_startup=False)
def timer_function(mytimer: func.TimerRequest) -> None:
    logging.info("Timer triggered")

My host.json

{
  "version": "2.0",
  "extensions": {
    "http": {
      "routePrefix": ""
    }
  },
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    }
  },
  "extensionBundle": {
    "id": "Microsoft.Azure.Functions.ExtensionBundle",
    "version": "[4.*, 5.0.0)"
  }
}
sudharsan2020 commented 10 months ago

@nordange Error message No job functions found usually indicates a missing dependency which is difficult to troubleshoot. We generally resolve the issue by stepping inside the docker container installing Azure Function tools manually and then running func start --verbose to identify the issue.

Apart from this, I don't see any other troubleshooting approaches.

Installing Azure Function Core tools:

curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-jammy-prod jammy main" > /etc/apt/sources.list.d/dotnetdev.list'
apt-get update
apt-get install azure-functions-core-tools-4
OlavMSG commented 9 months ago

@sudharsan2020 , I have investigated the problem a bit. However, I have not yet stepped into the docker container as you suggested.

I investigated using both python 3.8 and python 3.10, running locally using func start --verbose and using a docker container.

Using python 3.x and func start --verbose I get the error message:

Result: Failure
Exception: AttributeError: 'AsgiFunctionApp' object has no attribute 'function_name'
Stack:   File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8\WINDOWS\X64\azure_functions_worker\dispatcher.py", line 345, in _handle__functions_metadata_request
    fx_metadata_results = self.index_functions(function_path)
  File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8\WINDOWS\X64\azure_functions_worker\dispatcher.py", line 617, in index_functions
    indexed_functions = loader.index_function_app(function_path)
  File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8\WINDOWS\X64\azure_functions_worker\utils\wrappers.py", line 44, in call
    return func(*args, **kwargs)
  File "C:\Program Files\Microsoft\Azure Functions Core Tools\workers\python\3.8\WINDOWS\X64\azure_functions_worker\loader.py", line 214, in index_function_app
    imported_module = importlib.import_module(module_name)
  File "...\Anaconda3\envs\...\lib\importlib\__init__.py", line 127, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
  File "<frozen importlib._bootstrap>", line 991, in _find_and_load
  File "<frozen importlib._bootstrap>", line 975, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 671, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 848, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "...\function_app.py", line 16, in <module>
    @app.function_name(name="SimpleTimer")

This then results in the No job functions found message. Running in a docker container gives the same result as @nordange when using the 4-python3.x docker image. The 4.24.4-python3.x docker image still works fine.

After reading the error message above, I removed line 16, @app.function_name(name="SimpleTimer"), form function_app.py. With this line removed all is fine, both python 3.8 and python 3.10, running locally using func start --verbose and using a docker container works fine.

This solution makes us able to run the code, however, this leaves the question why 'AsgiFunctionApp' object has no attribute 'function_name' and why FunctionApp does.

mortendaehli commented 6 months ago

This seems to be resolved in a coming release of the Azure Functions Python worker. See Issue here: https://github.com/Azure/azure-functions-python-worker/issues/1422