DevOps 和 Azure 应用服务中的环境变量

Posted

技术标签:

【中文标题】DevOps 和 Azure 应用服务中的环境变量【英文标题】:Environment Variables in DevOps and Azure App Service 【发布时间】:2021-08-21 02:25:43 【问题描述】:

我目前正在努力通过我的 DevOps 部署管道将环境变量持久化到 Azure 应用服务。

我正在使用 Docker 容器和 Azure 的容器注册表在 Azure 应用服务上部署一个 Django 应用。这些容器基于 Azure DevOps 构建,并通过发布管道推送到注册表。我需要对一些环境变量保密,因为该应用程序将连接到我们的 Azure Cosmos DB,我通过使用标记化的 .env 文件来做到这一点。这些变量是保密的,并在构建期间与管道变量和Replace Tokens DevOps 任务一起添加到我的“.env-prod”文件中。

这是我的“.env-prod”文件的样子:

PRODUCTION_KEY=#PRODUCTION_KEY#
AZURE_DB=#AZURE_DB#
AZURE_CONNECT=#AZURE_CONNECT#
...

在 DevOps 上构建期间,令牌被正确替换,并且构建执行时没有错误,将容器推送到我们的 Azure 容器注册表。

现在,当我通过也用于构建容器的 docker compose 脚本在应用服务上启动应用程序时,就会出现问题。这是我的 compose 文件中构建和运行 Django 应用程序的后端服务:

backend-service:
  env_file: backend_folder/.env-prod
  build: backend_folder
  # Container registry name in Azure
  image: **.azurecr.io/**:0.1.1
  volumes:
    - static:/app/static
  command: gunicorn django_proj.wsgi:application --chdir django_proj --bind 0.0.0.0:8001
  expose:
    - 8001

静态文件是通过我的 Docker 文件中的CMD python manage.py collectstatic --no-input 命令创建的。还有一个 nginx 和一个前端服务来服务我们的网站,但它们不引用 .env 文件。

当我启动我的应用服务时,启动应用时变量似乎没有加载到后端服务。我还在应用服务的应用程序设置中添加了相同的变量,但我仍然遇到错误,提示我未设置变量。

这是我的容器日志流中描述错误的快照:

2021-06-02 INFO - 来自后端服务的容器日志 = 2021-06-02 [2021-06-02] [INFO] 启动 gunicorn 20.1.0 2021-06-02 [2021-06-02] [INFO] 收听:http://0.0.0.0:8001 (1) 2021-06-02T2 [2021-06-02] [6] [错误] 工作进程中的异常 2021-06-02 Traceback(最近一次通话最后一次):

...

2021-06-02 文件“/app/django_proj/settings.py”,第 116 行,在

2021-06-02 connect(os.environ['AZURE_DB'], host=os.environ['AZURE_CONNECT'])

...

2021-06-02 pymongo.errors.InvalidURI:无效的 URI 方案:URI 必须以“mongodb://”或“mongodb+srv://”开头

似乎我的AZURE_CONNECT 变量没有在我们正在运行的应用服务后端容器中设置。

    如何在我的撰写脚本中安全地保留秘密环境变量,以便它们在 Azure DevOps 中的构建步骤和 Azure 应用服务中的运行步骤中都存在? 是否有另一种方法通过 gunicorn 提供静态文件,以便仅在构建步骤而不是在启动应用服务时引用环境变量?

Here is the closest related question 我发现了我的问题,但我们的不同之处在于我们在 Azure 应用服务上使用多个环境变量,而不是 Heroku。此外,如果我使用没有令牌的私有 .env 文件,我在本地计算机上运行该站点也没有问题。

【问题讨论】:

如果根本没有设置AZURE_CONNECT,那么你会得到一个KeyError,是吗?似乎它被设置为 something。在调试消息中打印值。 你的直觉是正确的。奇怪的是,该变量似乎已设置但未正确完成。当我记录该值时,我看到“Settings.py:我的 AZURE_CONNECT 的秘密变量值是:'mongodb://***'”,但我仍然收到错误“pymongo.errors.InvalidURI:无效的 URI 方案:URI必须以 'mongodb://' 或 'mongodb+srv://' 开头”。我将研究为什么这个变量的格式可能不正确。 单引号实际上是值的一部分吗? 我不应该添加单引号。删除成功部署的这些引号,并且环境变量已正确加载到我的实例中。谢谢您的帮助!我会总结并回答问题。 【参考方案1】:

感谢 Josh Gordon 的帮助,我了解到我不应该使用引号格式化 Azure 应用服务应用程序设置 - 原始文本作为字符串加载到环境中,不需要预期引号。

在我的问题中,我也在寻找一种通过管道持久化环境变量的方法。我想这可以通过在管道和应用程序服务的应用程序设置中设置相同的变量来完成,但我也能够通过替换 Dockerfile 中的行来避免在部署管道中使用环境变量

RUN python manage.py collectstatic --no-input

CMD python manage.py collectstatic --no-input

现在构建和推送步骤不需要加载环境变量,我在应用服务中正确加载了环境变量。再次感谢乔希。

【讨论】:

以上是关于DevOps 和 Azure 应用服务中的环境变量的主要内容,如果未能解决你的问题,请参考以下文章

Azure Devops角环境变量

通过Azure DevOps部署Service Fabric并在Octopus中管理环境变量

Azure DevOps 如何在发布时替换服务结构项目的 Cloud.xml 参数中的值,这些值作为变量保存

Azure DevOps 发布管道的动态变量组

如何将变量传递给 azure devops 管道中的 SqlAzureDacpacDeployment@1 任务

Azure Devops - 将 YAML 脚本中的变量设置为日期时间