Monday, 26 April 2021

Azure Function runs locally, but doesn't do anything after Docker container is built and run locally

I have an Azure Function, with custom imported python modules, that runs correctly when I use func start in the directory. But, the next step is to get it running locally in a Docker container. After I build and run (following the Azure instructions), nothing happens, and I get the following output:

info: Host.Triggers.Warmup[0]
      Initializing Warmup Extension.
info: Host.Startup[503]
      Initializing Host. OperationId: '9711d195-2ab7-4b93-8c53-dd577b6b70d5'.
info: Host.Startup[504]
      Host initialization: ConsecutiveErrors=0, StartupCount=1, OperationId=9711d195-2ab7-4b93-8c53-dd577b6b70d5
info: Microsoft.Azure.WebJobs.Hosting.OptionsLoggingService[0]
      LoggerFilterOptions
      {
        "MinLevel": "None",
        "Rules": [
          {
            "ProviderName": null,
            "CategoryName": null,
            "LogLevel": null,
            "Filter": "<AddFilter>b__0"
          },
          {
            "ProviderName": "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.SystemLoggerProvider",
            "CategoryName": null,
            "LogLevel": "None",
            "Filter": null
          },
          {
            "ProviderName": "Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics.SystemLoggerProvider",
            "CategoryName": null,
            "LogLevel": null,
            "Filter": "<AddFilter>b__0"
          }
        ]
      }
info: Microsoft.Azure.WebJobs.Hosting.OptionsLoggingService[0]
      FunctionResultAggregatorOptions
      {
        "BatchSize": 1000,
        "FlushTimeout": "00:00:30",
        "IsEnabled": true
      }
info: Microsoft.Azure.WebJobs.Hosting.OptionsLoggingService[0]
      SingletonOptions
      {
        "LockPeriod": "00:00:15",
        "ListenerLockPeriod": "00:01:00",
        "LockAcquisitionTimeout": "10675199.02:48:05.4775807",
        "LockAcquisitionPollingInterval": "00:00:05",
        "ListenerLockRecoveryPollingInterval": "00:01:00"
      }
info: Microsoft.Azure.WebJobs.Hosting.OptionsLoggingService[0]
      HttpOptions
      {
        "DynamicThrottlesEnabled": false,
        "MaxConcurrentRequests": -1,
        "MaxOutstandingRequests": -1,
        "RoutePrefix": "api"
      }
info: Microsoft.Azure.WebJobs.Hosting.JobHostService[0]
      Starting JobHost
info: Host.Startup[401]
      Starting Host (HostId=c8cdf3a0c1a6-2137340777, InstanceId=c64a8e95-4ded-4a90-ac41-461d9223ed24, Version=3.0.15417.0, ProcessId=1, AppDomainId=1, InDebugMode=False, InDiagnosticMode=False, FunctionsExtensionVersion=(null))
info: Host.Startup[314]
      Loading functions metadata
info: Host.Startup[315]
      1 functions loaded
info: Host.Startup[0]
      Generating 1 job function(s)
info: Host.Startup[0]
      Found the following functions:
      Host.Functions.BadFunc
      
info: Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostHttpRoutesManager[0]
      Initializing function HTTP routes
      No HTTP routes mapped
      
info: Host.Startup[412]
      Host initialized (107ms)
fail: Host.Startup[0]
      The listener for function 'Functions.BadFunc' was unable to start.
Microsoft.Azure.WebJobs.Host.Listeners.FunctionListenerException: The listener for function 'Functions.BadFunc' was unable to start.
 ---> System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString')
   at Microsoft.Azure.Storage.CloudStorageAccount.Parse(String connectionString)
   at Microsoft.Azure.WebJobs.Extensions.Timers.StorageScheduleMonitor.get_TimerStatusDirectory() in C:\azure-webjobs-sdk-extensions\src\WebJobs.Extensions\Extensions\Timers\Scheduling\StorageScheduleMonitor.cs:line 77
   at Microsoft.Azure.WebJobs.Extensions.Timers.StorageScheduleMonitor.GetStatusBlobReference(String timerName) in C:\azure-webjobs-sdk-extensions\src\WebJobs.Extensions\Extensions\Timers\Scheduling\StorageScheduleMonitor.cs:line 144
   at Microsoft.Azure.WebJobs.Extensions.Timers.StorageScheduleMonitor.GetStatusAsync(String timerName)
   at Microsoft.Azure.WebJobs.Extensions.Timers.Listeners.TimerListener.StartAsync(CancellationToken cancellationToken) in C:\azure-webjobs-sdk-extensions\src\WebJobs.Extensions\Extensions\Timers\Listener\TimerListener.cs:line 99
   at Microsoft.Azure.WebJobs.Host.Listeners.SingletonListener.StartAsync(CancellationToken cancellationToken) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Singleton\SingletonListener.cs:line 72
   at Microsoft.Azure.WebJobs.Host.Listeners.FunctionListener.StartAsync(CancellationToken cancellationToken, Boolean allowRetry) in C:\projects\azure-webjobs-sdk-rqm4t\src\Microsoft.Azure.WebJobs.Host\Listeners\FunctionListener.cs:line 69
   --- End of inner exception stack trace ---
info: Host.Startup[413]
      Host started (154ms)
info: Host.Startup[0]
      Job host started
Hosting environment: Production
Content root path: /
Now listening on: http://[::]:80
Application started. Press Ctrl+C to shut down.
info: Microsoft.Azure.WebJobs.Script.Workers.Rpc.RpcFunctionInvocationDispatcher[0]
      Worker process started and initialized.
info: Host.Startup[0]
      Retrying to start listener for function 'Functions.BadFunc' (Attempt 1)
info: Host.Startup[0]
      Listener successfully started for function 'Functions.BadFunc' after 1 retries.
info: Host.General[316]
      Host lock lease acquired by instance ID '000000000000000000000000F28FAECC'.

So it looks like the container is running after one failed start-up. Great. But why is nothing happening? I'm supposed to get Slack notifications if it runs correctly or fails. The Dockerfile is as follows:

# FROM mcr.microsoft.com/azure-functions/python:3.0-python3.6-appservice
FROM mcr.microsoft.com/azure-functions/python:3.0-python3.6

ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true

# install python dependencies
RUN apt-get update \
    && apt-get install -y \
        build-essential \
        cmake \
        git \
        wget \
        unzip \
    && rm -rf /var/lib/apt/lists/*

# chrome install
#ARG CHROME_VERSION="google-chrome-stable"
RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - \
  && echo "deb http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google-chrome.list \
  && apt-get update -qqy \
  && apt-get -qqy install \
   # ${CHROME_VERSION:-google-chrome-stable} \
  && rm /etc/apt/sources.list.d/google-chrome.list \
  && rm -rf /var/lib/apt/lists/* /var/cache/apt/*

# install chromedriver used by Selenium
RUN LATEST=$(wget -q -O - http://chromedriver.storage.googleapis.com/LATEST_RELEASE) && \
    wget http://chromedriver.storage.googleapis.com/$LATEST/chromedriver_linux64.zip && \
    unzip chromedriver_linux64.zip && ln -s $PWD/chromedriver /usr/local/bin/chromedriver

ENV PATH="/usr/local/bin/chromedriver:${PATH}"

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

COPY . /home/site/wwwroot

I use docker build --tag <DOCKER_ID>/azurefunctionsimage:v1.0.0 . to build the image, and I run it from Docker Desktop clicking "run."

I've closely followed this tutorial on getting selenium working in a container. I have pointed my scraping function to the chromedriver, but I don't think that's the issue. Here is my function.json file:

{
  "scriptFile": "__init__.py",
  "bindings": [
    {
      "name": "mytimer",
      "type": "timerTrigger",
      "direction": "in",
      "schedule": "0 * * * * *"
    }
  ]
}

And local.settings.json file:

{
  "IsEncrypted": false,
  "Values": {
    "FUNCTIONS_WORKER_RUNTIME": "python",
    "AzureWebJobsStorage": "UseDevelopmentStorage=true;"
  }
}

File structure in VSCode:

FunctionDirectory
    |_ BadFunc
        | __init__.py
        | custom_mod1.py
        | custom_mod2.py
          ...
        | function.json
    |_ local.settings.json
       Dockerfile
       requirements.txt
       etc..

Am I missing something obvious on why I'm getting no results, when running the container locally?



from Azure Function runs locally, but doesn't do anything after Docker container is built and run locally

No comments:

Post a Comment