I'm encountering an issue with deploying my Python web application to Azure App Service using CI/CD with GitHub Actions. The goal is for the application to connect to an Azure SQL backend for querying, but the deployment is not working as expected.
I am attempting to deploy it from my GitHub directory via Actions, and I have added a secret secrets.AZURE_WEBAPP_PUBLISH_PROFILE with the content from the Azure App Service publish profile file.
The structure of my GitHub repository is as follows:
/python-app$
.
├── app
│ ├── app.py
│ ├── requirements.txt
│ ├── static
│ │ └── styles.css
│ └── templates
│ ├── index.html
│ └── welcome.html
├── terraform-infra
Here is the pipeline I have created
name: Build and Deploy Python App to Azure Web App
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python version
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install unixodbc
run: sudo apt-get install -y unixodbc
- name: Create and activate virtual environment
run: |
python -m venv venv
source venv/bin/activate
- name: Install dependencies
run: pip install -r app/requirements.txt
- name: Compress artifact for deployment
run: zip release.zip ./app/* -r
- name: Upload artifact for deployment jobs
uses: actions/upload-artifact@v4
with:
name: python-app
path: |
release.zip
!venv/
deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: 'Production'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
steps:
- name: Download artifact from build job
uses: actions/download-artifact@v4
with:
name: python-app
- name: Unzip artifact for deployment
run: |
unzip release.zip
mv app/* .
- name: 'Deploy to Azure Web App'
uses: azure/webapps-deploy@v3
id: deploy-to-webapp
with:
app-name: 'python-app-mario'
slot-name: 'production'
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
requirements.txt
bcrypt==4.2.0
blinker==1.8.2
click==8.1.7
Flask==3.0.3
itsdangerous==2.2.0
Jinja2==3.1.4
MarkupSafe==2.1.5
pyodbc==5.1.0
Werkzeug==3.0.4
app.py
database = os.getenv("database")
password = os.getenv("password")
server = os.getenv("server")
user = os.getenv("user")
driver= '{ODBC Driver 17 for SQL Server}'
# Connecting to SQL server
conexion = pyodbc.connect(f"DRIVER={driver};SERVER={server};DATABASE={database};UID={user};PWD={password}")
After deploying the pipeline, when I try to access the application, I see the following error message:
: ( Application Error If you are the application administrator, you can access the diagnostic resources.
Additionally, the logs show the following error, indicating that the pyodbc module is not found. However, I have added it to the requirements.txt file and installed its dependencies as per the file.
ModuleNotFoundError: No module named 'pyodbc'
I have been searching for information about this issue but am unsure how to resolve it.
Thank you very much for your time!
As mentioned in the previous message, I tried installing the pyodbc module and the unixodbc dependency, but I am still encountering the same error.
I also tried using the pipelines provided by Azure, but they also failed. I have been searching for information on this error and how to resolve it in official documentation, but I have not been able to fix the issue.
UPDATE 1:
In the end, I managed to deploy the web application thanks to your help and the official Azure documentation. What I did was add:
pip install --target="./.python_packages/lib/site-packages" -r requirements.txt
working-directory: ./app
This installs the dependencies in a specific folder within the app's directory, ensuring that the deployment package includes the necessary Python packages for the app to run in Azure.
I also set the variable SCM_DO_BUILD_DURING_DEPLOYMENT = 1
in the Terraform infrastructure configuration file. This setting ensures that the build process runs during deployment in Azure App Service.
The error indicates that the dependency is not found. This is most likely due to the zip file missing the dependencies, you can validate this by unpacking your zip file locally.
What you should do to fix this issue is providing the --target / -t <dir>
flag when installing everything in your requirements.txt file. So that the dependencies will be installed in your project root before zipping. Here is an example modelled after the official documentation:
- name: Create and start virtual environment
run: |
python -m venv venv
source venv/bin/activate
- name: Install dependencies
run: |
pip install -r requirements.txt \
--target=".python_packages/lib/site-packages"
working-directory: ./app
- name: Compress files
run: zip -r release.zip .
working-directory: ./app
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: python-app
path: app/release.zip
- name: Deploy web app
uses: azure/webapps-deploy@v3
with:
app-name: python-app-mario
slot: production
package: app/release.zip
publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }}
Additionally, if you do a Zip deployment, it is recommended that you set SCM_DO_BUILD_DURING_DEPLOYMENT
to true in the app settings of the web app.
resource "azurerm_linux_web_app" "web_app" {
...
app_settings = {
SCM_DO_BUILD_DURING_DEPLOYMENT = 1
}
}