slimtoolkit / slim

Slim(toolkit): Don't change anything in your container image and minify it by up to 30x (and for compiled languages even more) making it secure too! (free and open source)
Apache License 2.0
18.85k stars 702 forks source link

Azure Functions docker image - Docker slim fails #614

Open sudharsan2020 opened 7 months ago

sudharsan2020 commented 7 months ago

Expected Behavior

We are trying to reduce the Docker image size of Azure functions using slim https://github.com/Azure/azure-functions-docker However, the generated slim docker image is failing.

Base docker image chosen: https://github.com/Azure/azure-functions-docker/blob/dev/host/4/bullseye/amd64/python/python311/python311-slim.Dockerfile

Our docker image

FROM mcr.microsoft.com/azure-functions/python:4-python3.11

EXPOSE 8080

# If we don't set WEBSITE_HOSTNAME Azure Function triggers other than HttpTrigger won't run. (FunctionInvocationException: Webhooks are not configured)
# I've created a pull request to add this variable to the original dockerfile: https://github.com/Azure/azure-webjobs-sdk-script/pull/2285
# Set the function app environment variables and append the non-root user Python package installation path to the PATH environment variable
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
    AzureWebJobsFeatureFlags=EnableWorkerIndexing \
    WEBSITE_HOSTNAME=localhost:8080 \
    ASPNETCORE_URLS=localhost:8080 \
    PIP_USER=true \
    PYTHONUSERBASE=/home/appuser/.local \
    FUNCTION_APP_FOLDER=${AzureWebJobsScriptRoot}/my_azure_function \
    PATH="${PATH}:${PYTHONUSERBASE}/bin"

# Run the docker image as a non-root user
RUN groupadd appuser && \
    useradd -r -g appuser -m -d /home/appuser appuser && \
    mkdir -p /home/appuser/.local && \
    chown -R appuser:appuser /home/appuser/.local && \
    mkdir -p ${FUNCTION_APP_FOLDER}

# Switch to the user
USER appuser

# Copy the required source files
COPY my_azure_function ${FUNCTION_APP_FOLDER}
COPY ./requirements.txt ./function_app.py ./host.json /home/site/wwwroot/

# Install the dependencies
RUN pip install --upgrade pip && \
    pip install --no-cache-dir --upgrade -r /home/site/wwwroot/requirements.txt

Original and Trimmed docker image sizes:

REPOSITORY TAG IMAGE ID CREATED SIZE
demo.slim latest 228f317874ed 12 minutes ago 3.25GB
demo v1.0 24cafeeac38b 2 days ago 6.61GB

Actual Behavior

The trimmed version of the Docker instance fails to load the function with the error message 0 functions loaded

> sudo docker run -it -u 0  --env-file ~/env.list -p 15000:80  demo.slim:latest
info: Host.Triggers.Warmup[0]
      Initializing Warmup Extension.
fail: Host.Function.Console[0]
      Error processing line 3 of /home/appuser/.local/lib/python3.11/site-packages/googleapis_common_protos-1.61.0-py3.9-nspkg.pth:
info: Host.Function.Console[0]
info: Host.Function.Console[0]
        Traceback (most recent call last):
info: Host.Function.Console[0]
          File "<frozen site>", line 186, in addpackage
info: Host.Function.Console[0]
          File "<string>", line 1, in <module>
info: Host.Function.Console[0]
          File "<frozen importlib._bootstrap>", line 570, in module_from_spec
fail: Host.Function.Console[0]
        AttributeError: 'NoneType' object has no attribute 'loader'
info: Host.Function.Console[0]
info: Host.Function.Console[0]
      Remainder of file ignored
info: Microsoft.Azure.WebJobs.Hosting.OptionsLoggingService[0]
      LoggerFilterOptions
      {
        "MinLevel": "None",
        "Rules": [
          {
            "ProviderName": null,
            "CategoryName": null,
            "LogLevel": null,
            "Filter": "<AddFilter>b__0"
          },
          {
            "ProviderName": null,
            "CategoryName": "Host.Function.ToolingConsoleLog",
            "LogLevel": "Information",
            "Filter": null
          },
          {
            "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]
      ConcurrencyOptions
      {
        "DynamicConcurrencyEnabled": false,
        "MaximumFunctionConcurrency": 500,
        "CPUThreshold": 0.8,
        "SnapshotPersistenceEnabled": true
      }
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]
      ScaleOptions
      {
        "ScaleMetricsMaxAge": "00:02:00",
        "ScaleMetricsSampleInterval": "00:00:10",
        "MetricsPurgeEnabled": true,
        "IsTargetScalingEnabled": true,
        "IsRuntimeScalingEnabled": false
      }
info: Microsoft.Azure.WebJobs.Hosting.JobHostService[0]
      Starting JobHost
info: Host.Startup[401]
      Starting Host (HostId=61b8ffd5ddfc-2137340777, InstanceId=123801f3-6995-4da9-b787-45e31918a386, Version=4.27.3.3, 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.).
info: Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostHttpRoutesManager[0]
      Initializing function HTTP routes
      No HTTP routes mapped

info: Microsoft.Azure.WebJobs.Hosting.OptionsLoggingService[0]
      HttpOptions
      {
        "DynamicThrottlesEnabled": false,
        "EnableChunkedRequestBinding": false,
        "MaxConcurrentRequests": -1,
        "MaxOutstandingRequests": -1,
        "RoutePrefix": "api"
      }
info: Host.Startup[412]
      Host initialized (34ms)
info: Host.Startup[413]
      Host started (42ms)
info: Host.Startup[0]
      Job host started
Hosting environment: Production
Content root path: /azure-functions-host
Now listening on: http://[::]:8080
Application started. Press Ctrl+C to shut down.
info: Host.General[337]
      Host lock lease acquired by instance ID '000000000000000000000000A54C3676'.

Steps to Reproduce the Problem

1.build --target demo:v1


Specifications

kcq commented 6 months ago

Thank you for opening the issue and providing so much information! Going through it and I'll share my comments soon. We'll try to use the existing flags to make it work. One of the most basic flags to use is the --include-path flag and point at your app directory. There are a lot of others including flags to provide custom env vars, which some apps need or custom http probes, which some languages need...