如何从单仓部署Python Azure Function应用并配置入口及依赖?
问题描述
我拥有一个包含Flask API及多个Azure Function应用的单仓(mono-repo),现尝试通过Azure DevOps流水线将其中一个Function应用部署至Azure。
Python代码结构如下:
./backend ./backend/domain/ - 包含领域逻辑的.py文件 ./backend/entrypoints/api - 包含Flask应用文件 ./backend/entrypoints/my-func - 我的新Function应用目录 ./backend/... - 其他被导入的层级文件夹
已配置AzureFunctionApp@2任务将项目压缩包推送至存储账户,但在Azure门户中看不到已注册的函数,流水线任务代码如下:
- task: ArchiveFiles@2 displayName: Package Function Apps inputs: rootFolderOrFile: $(Build.SourcesDirectory) archiveType: 'zip' archiveFile: '$(Build.ArtifactStagingDirectory)/nightly-import-$(Build.BuildId).zip' verbose: true - task: AzureFunctionApp@2 displayName: Deploy Nightly Importer inputs: azureSubscription: ${{parameters.azureServiceConnection}} appType: functionAppLinux appName: nightly-import-${{parameters.environmentMoniker}}-uks-01 package: '$(Pipeline.Workspace)/FuncAppsPackage/nightly-import-$(Build.BuildId).zip' deploymentMethod: auto verbose: true
需要解决:如何从单仓中发布Function应用,确保包含所有依赖(包括venv中的pip包及Function应用文件夹外的backend/domain等内部Python模块),并告知Azure应用入口点?
解决方案
1. 调整归档范围与目录结构
当前归档整个源码目录会导致Azure Function无法识别正确的Function根目录,需要先整理文件结构再归档:
- 将目标Function的目录作为根目录,同时把整个
backend目录复制到该根目录下,确保内部模块能被正常导入 - 通过CopyFiles任务先完成文件整理,再执行归档
修改流水线任务如下:
# 复制共享的backend模块到临时Function目录 - task: CopyFiles@2 displayName: Copy Shared Backend Modules inputs: SourceFolder: $(Build.SourcesDirectory)/backend TargetFolder: $(Build.ArtifactStagingDirectory)/my-func/backend CleanTargetFolder: true # 复制Function应用自身的文件到临时根目录 - task: CopyFiles@2 displayName: Copy Function App Files inputs: SourceFolder: $(Build.SourcesDirectory)/backend/entrypoints/my-func TargetFolder: $(Build.ArtifactStagingDirectory)/my-func CleanTargetFolder: false # 归档整理好的Function目录 - task: ArchiveFiles@2 displayName: Package Function App inputs: rootFolderOrFile: $(Build.ArtifactStagingDirectory)/my-func archiveType: 'zip' archiveFile: '$(Build.ArtifactStagingDirectory)/nightly-import-$(Build.BuildId).zip' verbose: true
2. 安装依赖到归档目录
Linux环境的Azure Function需要把依赖包放在指定路径,推荐通过requirements.txt安装到临时Function目录:
# 指定与Azure Function匹配的Python版本 - task: UsePythonVersion@0 inputs: versionSpec: '3.10' addToPath: true # 安装依赖到Function目录的指定路径 - script: | python -m pip install --upgrade pip pip install -r $(Build.SourcesDirectory)/backend/entrypoints/my-func/requirements.txt -t $(Build.ArtifactStagingDirectory)/my-func/.python_packages/lib/site-packages displayName: Install Function Dependencies
注意:内部模块(如
backend/domain)不需要在requirements.txt中声明,只要目录结构正确就能被Python识别导入。
3. 配置Function入口点
确保Azure Function能识别触发器位置:
- 检查Function目录下的
function.json,确认scriptFile路径正确,示例:
{ "scriptFile": "__init__.py", "bindings": [ // 你的触发器配置 ] }
- 如果使用
function_app.py作为入口文件,需要在Azure门户的应用设置中添加以下配置:FUNCTIONS_WORKER_RUNTIME_VERSION=3.10(匹配Python版本)FUNCTIONS_EXTENSION_VERSION=~4AzureWebJobsScriptRoot=__app__
4. 修正部署任务配置
明确指定部署方式和运行时栈,避免自动检测的不确定性:
# 先下载之前归档的工件(如果有发布步骤的话) - task: DownloadBuildArtifacts@0 inputs: buildType: 'current' downloadType: 'single' artifactName: 'FuncAppsPackage' downloadPath: '$(Pipeline.Workspace)' # 部署到Azure Function - task: AzureFunctionApp@2 displayName: Deploy Nightly Importer inputs: azureSubscription: ${{parameters.azureServiceConnection}} appType: functionAppLinux appName: nightly-import-${{parameters.environmentMoniker}}-uks-01 package: '$(Pipeline.Workspace)/FuncAppsPackage/nightly-import-$(Build.BuildId).zip' deploymentMethod: 'zipDeploy' runtimeStack: 'PYTHON|3.10' verbose: true
5. 验证内部模块导入
在Function代码中使用正确的导入路径,示例:
from backend.domain import your_domain_logic
因为我们已经将backend目录放在Function根目录下,Python会自动识别这个模块。
内容的提问来源于stack exchange,提问作者Greg B
相关产品推荐
相关产品推荐

