I have built a Python Dash web application which has the following .env, .env.development, and .env.production files. And this file is currently deployed in an Azure App Service through a build&deploy.yml file CICD through Azure DevOps. But I want to implement such that when the web app is deployed to the DEV environment, it uses the .env.development file and if to PROD env, uses the .env.production file. Furthermore, is there a way to run locally and the app picks up the values from the .env.development and .env file?
A React programmer here, in React that is the way I used to code in terms of environment handling. Any tips for Python web application development in terms of environment handling? And how do I fix the problem I stated above? Any help or suggestions would be really helpful, thanks!
My .env file looks like this:
REACT_VERSION=18.2.0
AS I am using Dash Mantine Components (package from Dash), they require to create a .env file with the following value.
.env.development:
ENVIRONMENT="dev"
.env.production:
ENVIRONMENT="prod"
And this is the file that fetches the values of the dev or prod (env.py):
from dotenv import load_dotenv
import os
load_dotenv()
environment = os.getenv('ENVIRONMENT')
print("ENV: ", environment)
Currently when I run this locally, it prints: ENV: None
And this is my build&deploy.yml file:
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'
2
Answers
Since you are deploying the same artifacts into different web apps, you may consider directly using
os.getenv
to get the environment variables value from each app settings instead of from each.env
file in your repo.Here is my sample code snippet for your reference.
env.html
YAML pipeline for deployment
As another benefit, we can pass secret variable values during pipeline deployment without disclosing such values in our code.
By default,
load_dotenv()
will read the.env
file in your project.Yes. You can use the following python code:
env.py
Result:
To meet your requirement, you can set the app settings in the Web App environment variables(As Alvin shared in the answer) to let the python script to decide which .env file to load.
Here is an example:
env.py
You can manually set the ENV variable app settings in Web App-> Environment variables -> App settings.
Or you can set it in Pipeline Azure Web APP task.
For example:
YAML Sample:
When the ENV value is set to dev in We APP app settings, the env.py script will read the
.env.development
file. Or it will read the.env.production
file.