我构建了一个 Python Dash Web 应用程序,其中包含以下 .env、.env.development 和 .env.Production 文件。此文件当前通过 Azure DevOps 通过 build&deploy.yml 文件 CICD 部署在 Azure 应用服务中。但我想实现这样的情况:当将 Web 应用程序部署到 DEV 环境时,它使用 .env.development 文件,如果要 PROD env,则使用 .env.Production 文件。此外,有没有办法在本地运行并且应用程序从 .env.development 和 .env 文件中获取值?
这里是一个 React 程序员,在 React 中,这就是我在环境处理方面编码的方式。 Python Web 应用程序开发在环境处理方面有什么建议吗?我该如何解决我上面提到的问题?任何帮助或建议都会非常有帮助,谢谢!
我的 .env 文件如下所示:
REACT_VERSION=18.2.0
由于我正在使用 Dash Mantine 组件(来自 Dash 的软件包),它们需要创建一个具有以下值的 .env 文件。
.env.开发:
ENVIRONMENT="dev"
.env.生产:
ENVIRONMENT="prod"
这是获取 dev 或 prod (env.py) 值的文件:
from dotenv import load_dotenv
import os
load_dotenv()
environment = os.getenv('ENVIRONMENT')
print("ENV: ", environment)
目前,当我在本地运行它时,它会打印:
ENV: None
这是我的 build&deploy.yml 文件:
trigger:
branches:
include:
- main
pr:
autoCancel: false
branches:
include:
- develop
pool:
vmImage: 'vm-pool-image'
variables:
pythonVersion: '3.12'
stages:
- stage: ArchiveArtifact
jobs:
- job:
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(pythonVersion)'
addToPath: true
- script: |
sed 's/\${GITHUB_TOKEN}/'"$(GitHubToken)"'/' requirements.txt > temp_requirements.txt
mv temp_requirements.txt requirements.txt
displayName: 'Replace GitHub token in requirements.txt'
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(Build.SourcesDirectory)'
includeRootFolder: false
archiveType: 'zip'
archiveFile: '$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip'
replaceExistingArchive: true
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'drop'
publishLocation: 'Container'
- stage: DeployDev
displayName: 'Deploy to Dev'
dependsOn: ArchiveArtifact
jobs:
- deployment: DevDeploy
pool: 'dev-agent-pool'
environment: 'dev'
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
inputs:
azureSubscription: 'subscription'
appType: 'webAppLinux'
appName: 'web-app-dev-name'
package: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'
deploymentMethod: 'auto'
- stage: DeployProd
displayName: 'Deploy to Prod'
dependsOn: DeployDev
condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/main') , eq(variables['Build.SourceBranch'], 'refs/heads/release/*')))
jobs:
- deployment: ProdDeploy
pool: 'agent-pool'
environment: 'prod'
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
inputs:
azureSubscription: 'prod_subscription'
appType: 'webAppLinux'
appName: 'web-app-prod-name'
package: '$(Pipeline.Workspace)/drop/$(Build.BuildId).zip'
deploymentMethod: 'auto'
由于您要将相同的工件部署到不同的 Web 应用程序中,因此您可以考虑直接使用
os.getenv
从每个 应用程序设置 获取环境变量值,而不是从存储库中的每个 .env
文件获取环境变量值。
这是我的示例代码片段供您参考。
@app.route("/env/")
def env():
env = os.getenv('env', 'default_env')
build = os.getenv('build', 'default_build')
return render_template(
"env.html",
env=env,
build=build
)
env.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flask App</title>
</head>
<body>
<h1>Welcome to the Flask App</h1>
<p>Environment: {{ env }}</br>Build: {{ build }}</p>
</body>
</html>
用于部署的 YAML 管道
- stage: CD
jobs:
- deployment: Deploy
environment: E-Dev
strategy:
runOnce:
deploy:
steps:
- task: AzureRmWebAppDeployment@4
inputs:
ConnectionType: 'AzureRM'
azureSubscription: 'ARMSvcCnnSub0'
appType: 'webAppLinux'
WebAppName: '$(WebAppDev)'
packageForLinux: '$(Pipeline.Workspace)/**/*.zip'
AppSettings: >
-env "dev"
-build "$(Build.BuildId)"
-PWD "$(SecretVar)"
另一个好处是,我们可以在管道部署期间传递秘密变量值,而无需在代码中公开这些值。