Deploying a Docker-Based Python Web Application to Azure App Service

Deploying a Docker-Based Python Web Application to Azure App Service

In today’s fast-paced development world, containerization with Docker has become a game-changer. It allows developers to package applications with their dependencies, ensuring consistency across environments. Pair that with Azure App Service—a fully managed platform for hosting web apps—and you’ve got a recipe for scalable, hassle-free deployment. Whether you’re running a Node.js app, a Python Flask server, or a custom .NET Core project, Azure App Service makes it easy to deploy your Docker containers without managing virtual machines or Kubernetes clusters.

Why go this route? Docker ensures your app runs the same way locally as it does in the cloud, while Azure App Service handles scaling, load balancing, and monitoring out of the box. Plus, with built-in CI/CD integration, you can push updates effortlessly. In this post, we’ll walk through deploying a simple Docker-based web app to Azure App Service. By the end, you’ll have a live, containerized application running in the cloud.

Let’s dive into the process, from creating a basic app to seeing it live on Azure!

Detailed Step-by-Step Guide: Deploying a Docker-Based Web Application to Azure App Service

Prerequisites

Before starting, ensure you have:

  • Azure Account: Sign up at portal.azure.com.

  • Docker: Install Docker Desktop (download here) and verify with docker --version.

  • Azure CLI: Install from here and check with az --version.

  • Git: Optional for version control; install from git-scm.com.

  • Text Editor: Use VS Code, PyCharm, or any editor for coding.


Step 1: Create and Test the Web Application Locally

We’ll build a simple Python Flask app as our example.

  1. Set Up Project Directory:

    • Open a terminal (e.g., Command Prompt, PowerShell, or Bash).

    • Create and navigate to a new directory:

      bash

        mkdir flask-azure-app
        cd flask-azure-app
      
  2. Create the Flask App (app.py):

    • Create a file named app.py and add:

      python

        from flask import Flask
        app = Flask(__name__)
      
        @app.route('/')
        def hello():
            return "Hello from Azure App Service via Docker created by isaac divine!"
      
        @app.route('/health')
        def health():
            return "App is healthy!", 200
      
        if __name__ == "__main__":
            app.run(host="0.0.0.0", port=8000, debug=True)
      
    • Note: Added a /health endpoint for testing later

  3. Create a Requirements File (requirements.txt):

    • Create requirements.txt and add:

        Flask==2.3.2
      
    • This specifies the Flask version for consistency

  4. Test Locally Without Docker:

    • Install dependencies:

      bash

        pip install -r requirements.txt
      

    • Run the app:

      bash

        python app.py
      
    • Open localhost:8000 in a browser. Verify you see the "Hello" message. Check localhost:8000/health too

Step 2: Containerize the Application with Docker

Now, we’ll package the app into a Docker container.

  1. Create a Dockerfile:

    • In the flask-azure-app directory, create a file named Dockerfile (no extension) with:

      dockerfile

        # Use a lightweight Python base image
        FROM python:3.9-slim
      
        # Set working directory inside the container
        WORKDIR /app
      
        # Copy requirements file first (optimizes caching)
        COPY requirements.txt .
      
        # Install dependenciesz
        RUN pip install --no-cache-dir -r requirements.txt
      
        # Copy the entire app code
        COPY . .
      
        # Expose the port the app will run on
        EXPOSE 8000
      
        # Define the command to start the app
        CMD ["python", "app.py"]
      
    • Details:

      • FROM python:3.9-slim: Uses a slim Python image to reduce size.

      • EXPOSE 8000: Declares the port (though not strictly enforced).

      • CMD: Runs the app without debug mode for production

  2. Create a .dockerignore File (Optional but Recommended) **:

    • Create .dockerignore to exclude unnecessary files:

        __pycache__
        *.pyc
        *.pyo
        *.pyd
        .Python
        env/
        venv/
        *.log
      
    • This reduces image size and build time

  3. Build the Docker Image:

    • Run:

      bash

        docker build -t flask-azure-app:latest .
      
    • -t tags the image.

    • . specifies the build context (current directory).

    • Watch the output for errors (e.g., missing files)

  4. Run and Test the Container Locally:

    • Start the container:

      bash

        docker run -p 8000:8000 flask-azure-app:latest
      
    • -p 8000:8000 maps port 8000 on your machine to 8000 in the container.

    • Open localhost:8000 and localhost:8000/health in a browser

    • Stop the container with Ctrl+C.

Step 3: Push the Docker Image to a Container Registry

Azure App Service needs the image in a registry. We’ll use Docker Hub (public) for simplicity.

  1. Sign Up/Log In to Docker Hub:

    • If you don’t have an account, create one at hub.docker.com.

    • Log in via terminal:

      bash

        docker login
      
    • Enter your Docker Hub username and password

  2. Tag the Image:

    • Replace <your-dockerhub-username> with your actual username:

      bash

        docker tag flask-azure-app:latest <your-dockerhub-username>/flask-azure-app:latest
      
    • Verify with docker images to see the tagged image.

  3. Push the Image to Docker Hub:

    • Run:

      bash

        docker push <your-dockerhub-username>/flask-azure-app:latest
      
    • Check Docker Hub online to confirm the image appears under your repositories.

  4. Troubleshooting:

    • If the push fails, ensure you’re logged in (docker login) and the tag matches your username

Step 4: Deploy to Azure App Service

Let’s set up Azure resources and deploy the container.

  1. Log in to Azure CLI:

    • Run:

      bash

        az login
      
    • A browser window will open; sign in to your Azure account

      .

  2. Set Default Subscription (if multiple exist):

    • List subscriptions:

      bash

        az account list --output table
      
    • Set the active subscription:

      bash

        az account set --subscription "<subscription-id>"
      

  1. Create a Resource Group:

    • A resource group organizes Azure resources:

      bash

        az group create --name FlaskAppResourceGroup1 --location westeurope
      
    • --location westeurope uses the west Europe region (choose a region closer to you if needed; list with az account list-locations)

  2. Create an App Service Plan:

    • App Service Plans define the compute resources. For Docker, use a Linux plan:

      bash

        az appservice plan create --name FlaskAppPlan --resource-group FlaskAppResourceGroup1 --sku B1 --is-linux
      
    • --sku B1: Basic tier (free-tier eligible, 1.75 GB RAM). Upgrade to S1 or higher for production.

    • --is-linux: Required for Docker containers

  3. Create a Web App:

    • Replace <your-app-name> with a globally unique name (e.g., flaskapp-mazi):

      bash

        az webapp create --resource-group FlaskAppResourceGroup1 --plan FlaskAppPlan --name <your-app-name> --deployment-container-image-name <your-dockerhub-username>/flask-azure-app:latest
      
    • --deployment-container-image-name: Specifies the Docker image to pull

  4. Configure the Container Port:

    • Azure needs to know which port your app uses (8000 in this case):

      bash

        az webapp config appsettings set --resource-group FlaskAppResourceGroup1 --name <your-app-name> --settings WEBSITES_PORT=8000
      

    • Verify settings:

      bash

        az webapp config appsettings list --resource-group FlaskAppResourceGroup1 --name <your-app-name>
      

  1. Restart the Web App (if needed)**:

    • Ensure changes take effect:

      bash

        az webapp restart --resource-group FlaskAppResourceGroup1 --name <your-app-name>
      

Step 5: Verify and Test the Deployment

  1. Get the Web App URL:

    • Run:

      bash

        az webapp show --resource-group FlaskAppResourceGroup1 --name <your-app-name> --query "defaultHostName" --output tsv
      
    • Output looks like https://<your-app-name>.azurewebsites.net

  2. Test in Browser:

    • Open the URL (e.g., flaskapp-mazi.azurewebsites.net).

    • Check / and /health endpoints. Expect "Hello from Azure App Service via Docker created by isaac divine!" and "App is healthy!"

  3. View Logs (if Issues Arise):

    • Stream logs:

      bash

        az webapp log tail --resource-group FlaskAppResourceGroup1 --name <your-app-name>
      
    • Look for errors like port misconfiguration or image pull failures

Step 6: (Optional) Enable Continuous Deployment

Automate updates when you push new Docker images.

  1. Via Azure Portal:

    • Go to portal.azure.com > Your Web App > "Deployment Center".

    • Select "Docker Hub" > Enter your image name (<your-dockerhub-username>/flask-azure-app:latest).

    • Enable "Continuous Deployment" and save.

  2. Test CI/CD:

    • Update app.py (e.g., change the message), rebuild, and push the Docker image:

      bash

        docker build -t <your-dockerhub-username>/flask-azure-app:latest .
        docker push <your-dockerhub-username>/flask-azure-app:latest
      
    • Wait a few minutes and refresh your app URL to see the update.


Step 7: Monitor and Scale

  1. Monitoring:

    • In the Azure Portal, go to your Web App > "Log Stream" or "Metrics".

    • Check CPU, memory, and request counts.

  2. Scaling:

    • Manually scale: az appservice plan update --sku S1 --name FlaskAppPlan --resource-group FlaskAppResourceGroup.

    • Auto-scale: In the Portal, under "Scale out (App Service Plan)," add rules (e.g., scale on CPU > 70%)

Troubleshooting

  • App Not Starting: Check logs (az webapp log tail). Ensure WEBSITES_PORT matches your app’s port.

  • Image Pull Fails: Verify the image name and ensure its public on Docker Hub (or configure credentials in the Portal under "Container Settings").

  • 404 Errors: Confirm the app runs on the root path (/) and the port is correct.

Conclusion

With these detailed steps, you’ve deployed a Docker-based Flask app to Azure App Service! You’ve covered local development, containerization, registry management, and cloud deployment—all while leveraging Azure’s managed infrastructure.