Search code examples
pythonazureazure-web-app-servicegithub-actionspyodbc

Deploying a Python App to Azure App Service with Github Actions


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.


Solution

  • 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
      }
    }