容器化 Azure 函数 - 从 Dockerfile 更改 AzureWebJobsScriptRoot 变量

bga*_*ial 12 python azure docker azure-functions

我有一个具有特定业务逻辑的 python Azure 函数。在 中Dockerfile,我想以非 root 用户身份运行容器,因此我执行了以下操作:

FROM mcr.microsoft.com/azure-functions/python:3.0-python3.8
.
.
.

RUN useradd -u 1001 -m fem-downloader
RUN chown -R 1001:1001 /home/

# I Changed the AzureWebJobsScriptRoot value to this new user path
ENV AzureWebJobsScriptRoot=/home/fem-downloader/wwwroot \
  AzureFunctionsJobHost__Logging__Console__IsEnabled=true

USER fem-downloader
COPY --chown=fem-downloader:fem-downloader requirements.txt requirements.txt

RUN pip install -r requirements.txt
COPY --chown=fem-downloader:fem-downloader .  /home/fem-downloader/wwwroot

WORKDIR /home/fem-downloader/wwwroot/HttpTrigger/

ENV PATH="/home/fem-downloader/.local/bin:/home/.local/bin:${PATH}"

RUN pip install pytest && python3 -m pytest --verbose
Run Code Online (Sandbox Code Playgroud)

当我在本地运行 Azure 函数时,它可以工作:

docker run -ti -p 8001:80 --name my-azure-function my-azure-function:nonroot

info: Host.Startup[0]
      Found the following functions:
      Host.Functions.HttpTrigger

info: Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostHttpRoutesManager[0]
      Initializing function HTTP routes
      Mapped function route 'api/HttpTrigger' [post] to 'HttpTrigger'

info: Host.Startup[412]
      Host initialized (202ms)
info: Host.Startup[413]
      Host started (211ms)
info: Host.Startup[0]
      Job host started
Hosting environment: Production
Content root path: /home/my-project/wwwroot/HttpTrigger
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.General[316]
      Host lock lease acquired by instance ID '00000000000000000000000043EEAD9A'.

Run Code Online (Sandbox Code Playgroud)

即使我通过发送它期望的参数来测试它:

> curl -X POST http://localhost:8001/ -d "stream_id=XXXX&file_type=SCIA&server_url=https://aaaa.bbbbb.cccccc.digital"
<!DOCTYPE html>
<html>
<head>
    <title>Your Azure Function App is up and running.</title>
    <style type="text/css">
        @font-face {
            font-family: 'SegoeLight';
            src: url(//:) format('no404'), url(data:font/woff;charset=utf-8;base64,d09GRgABAAAAAFbcABAAAAAAjewAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAABGRlRNAAABbAAAABsAAAAcWqtaPUdERUYAAAGIAAAAHQAAACABGAADT1MvMgAAAagAAABYAAAAYGrqcLZjbWFwAAACAAAAAaIAAAIKczqUA2N2dCAAAAOkAAAATAAAAEwOEAwRZnBnbQAAA/AAAAGxAAACZQ+0L6dnYXNwAAAFpAAAAAwAAAAMAAMAB2dseWYAAAWwAABJAAAAe3CDYeDNaGVhZAAATrAAAAAxAAAANv

Run Code Online (Sandbox Code Playgroud)

但是当我在 Azure 上部署它时,我检查了日志:

2021-02-12T21:42:12.204812448Z warn: Host.Startup[0]
2021-02-12T21:42:12.205484355Z       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.).
2021-02-12T21:42:12.212736520Z info: Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostHttpRoutesManager[0]
2021-02-12T21:42:12.212758420Z       Initializing function HTTP routes
2021-02-12T21:42:12.212763520Z       No HTTP routes mapped
2021-02-12T21:42:12.204812448Z warn: Host.Startup[0]
2021-02-12T21:42:12.205484355Z       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.).
2021-02-12T21:42:12.212736520Z info: Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostHttpRoutesManager[0]
2021-02-12T21:42:12.212758420Z       Initializing function HTTP routes
2021-02-12T21:42:12.212763520Z       No HTTP routes mapped
Run Code Online (Sandbox Code Playgroud)

那个套接字地址错误是因为容器无法初始化,由于AzureWebJobsScriptRoot我提供的配置值,我的意思是路由的更改。

ENV AzureWebJobsScriptRoot=/home/fem-downloader/wwwroot \
  AzureFunctionsJobHost__Logging__Console__IsEnabled=true
Run Code Online (Sandbox Code Playgroud)

继续阅读,我发现了这个问题

Azure 似乎并不尊重 AzureWebJobsScriptRoot 设置。如果我将其设置为 D:\home\site\wwwroot\foo 之类的内容,它仍会从 D:\home\site\wwwroot 加载函数(即使我在 D:\home\site 下有 host.json 和函数文件夹) \wwwroot\foo)。

该设置在本地环境中似乎可以正常工作,但在 Azure 上却无法正常工作。

查看azure函数宿主项目,默认WebHostScriptPath是这样配置的: Data[WebHostScriptPathProperty] = Path.Combine(home, "site", "wwwroot");

配置设置也确认。

正如他们在问题中所讨论的那样,Azure 似乎有充分的理由不允许更改此AzureWebJobsScriptRoot值。


更新

即使我尝试将此路径设置为默认值,另一方面,与非 root 用户一起工作,/home/site/wwwroot以这种方式授予它对该路径 ( ) 的权限,但没有成功:

FROM mcr.microsoft.com/azure-functions/python:3.0-python3.8

RUN useradd -u 1001 -m fem-downloader

RUN chown -R 1001:1001 /home/
# ENV AzureWebJobsScriptRoot=/home/fem-downloader/wwwroot \
  # AzureFunctionsJobHost__Logging__Console__IsEnabled=true
ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
    AzureFunctionsJobHost__Logging__Console__IsEnabled=true
USER fem-downloader
COPY --chown=fem-downloader:fem-downloader requirements.txt requirements.txt

RUN pip install -r requirements.txt
# COPY --chown=fem-downloader:fem-downloader .  /home/fem-downloader/wwwroot
COPY --chown=fem-downloader:fem-downloader .  /home/site/wwwroot
# WORKDIR /home/fem-downloader/wwwroot/HttpTrigger/
WORKDIR /home/site/wwwroot/HttpTrigger/
# ENV PATH="/home/fem-downloader/.local/bin:/home/.local/bin:${PATH}"
ENV PATH="/home/site/.local/bin:/home/.local/bin:${PATH}"
RUN pip install pytest && python3 -m pytest --verbose
Run Code Online (Sandbox Code Playgroud)

在 Azure 上部署该函数时,我得到了相同的结果。

很有可能这个主题可以用权限管理,所以我决定通过访问创建的容器来检查目录上的现有权限,我们得到 755了用户、执行和读取组和其他人的所有权限:

fem-downloader@cdf0ec64f1ce:~$ pwd
/home
fem-downloader@cdf0ec64f1ce:~$ ls -all
total 48
drwxr-xr-x 1 fem-downloader fem-downloader 4096 Feb 15 12:36 .
drwxr-xr-x 1 root           root           4096 Feb 15 12:36 ..
drwxr-xr-x 3 fem-downloader fem-downloader 4096 Feb 15 12:36 .aspnet
drwxr-xr-x 1 fem-downloader fem-downloader 4096 Feb 15 10:46 .cache
drwx------ 1 fem-downloader fem-downloader 4096 Feb 15 10:47 .local
drwxr-xr-x 3 fem-downloader fem-downloader 4096 Feb 15 12:36 LogFiles
drwxr-xr-x 1 fem-downloader fem-downloader 4096 Feb 12 20:25 fem-downloader

# /home/site directory
drwxr-xr-x 1 fem-downloader fem-downloader 4096 Feb 15 10:47 site
fem-downloader@cdf0ec64f1ce:~$
Run Code Online (Sandbox Code Playgroud)

检查/home/site/目录的权限特权:

fem-downloader@cdf0ec64f1ce:~$ stat -c "%a %A" site
755 drwxr-xr-x
fem-downloader@cdf0ec64f1ce:~$
Run Code Online (Sandbox Code Playgroud)

检查/home/site/wwwroot/目录的权限特权:

fem-downloader@cdf0ec64f1ce:~/site$ stat -c "%a %A" wwwroot/
755 drwxr-xr-x
fem-downloader@cdf0ec64f1ce:~/site$
Run Code Online (Sandbox Code Playgroud)

我设法在 azure 上成功部署该功能的唯一方法是以 root 用户身份运行我的容器:

# Intermediate stage when installing pip packages and other requirements
.
.
FROM mcr.microsoft.com/azure-functions/python:3.0-python3.8

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

COPY --from=intermediate /usr/local/lib/python3.8/site-packages/ /usr/local/lib/python3.8/site-packages/

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

ADD . /home/site/wwwroot

WORKDIR /home/site/wwwroot/HttpTrigger/
RUN pip install pytest && pytest --verbose
Run Code Online (Sandbox Code Playgroud)

然后该函数设法联系存储帐户以下载我们在上面完成的请求中指示的资源:

***"container": "xxxx", "file_name": "PNd5efdCf-SCIA-xxxxxxx.zip", "sas_url": "abc0spec0test0xxxdwblob0.blob.core.windows.net/xxx/PNd5efdCf-SCIA-xxxxxxx.zip?sv=2018-03-28&ss=b&srt=co&sp=r&se=2021-02-12T19%3A45%3A28Z&st=2021-02-12T18%3A40%3A28Z&spr=https&sig=xxxxxxxxxxxxxxxxxx
Run Code Online (Sandbox Code Playgroud)

我只是想把尽可能多的细节放在这里,看看是否有人经历过同样的事情。

不确定从一个Dockerfile角度来看我是否可以做些事情来欺骗 Azure 配置设置,看起来不是,但问题是我不想以 root 用户身份运行我的容器 更改AzureWebJobsScriptRoot变量似乎没有任何关系?

小智 1

您是否在 ASE(应用服务环境)中运行?Path.Combine(home, "site", "wwwroot")看起来该值仅在您在 ASE 中执行时才设置为。如果您不在 ASE 中,则应从变量中读取值

GetEnvironmentVariable(EnvironmentSettingNames.AzureWebJobsScriptRoot);
Run Code Online (Sandbox Code Playgroud)

话虽如此,这似乎是目前正在调查(或至少记录)的问题。

解决该问题的一种方法(尽管我知道这不是最佳方法)是通过设置函数访问级别来处理函数外部的身份验证问题。在这种情况下(当 Azure 完成安全检查时),该函数可以在不创建非 root 用户(该用户已经为您工作)作为 Azure 使用的默认用户的情况下运行。