# 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](https://portal.azure.com/).
    
* **Docker**: Install Docker Desktop ([download here](https://www.docker.com/products/docker-desktop/)) and verify with docker --version.
    
* **Azure CLI**: Install from [here](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli) and check with az --version.
    
* **Git**: Optional for version control; install from [git-scm.com](https://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
        
        ```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
        
        ```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
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741246170281/85672f35-da71-4525-b6fb-d0a863f1db01.png align="center")
        
3. **Create a Requirements File (requirements.txt)**:
    
    * Create requirements.txt and add:
        
        ```text
        Flask==2.3.2
        ```
        
    * This specifies the Flask version for consistency
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741246353099/71119f03-d5a8-4ed6-b8f1-d7fd1a755fdc.png align="center")
        
4. **Test Locally Without Docker**:
    
    * Install dependencies:
        
        bash
        
        ```bash
        pip install -r requirements.txt
        ```
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741246488554/62dc9683-8823-43d0-b87c-6adc31db3a78.png align="center")
        
    * Run the app:
        
        bash
        
        ```bash
        python app.py
        ```
        
    * ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741246626884/2a2ab0dd-cb42-473c-a8ff-6939de50732e.png align="center")
        
    * Open http://localhost:8000 in a browser. Verify you see the "Hello" message. Check http://localhost:8000/health too
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741246749906/4f3a6a83-936c-4289-9a27-66452914f5cb.png align="center")
        

### **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
        
        ```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
            
            ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741246989105/f8fc6197-adc1-40a0-abdc-0ee62b6f146c.png align="center")
            
2. **Create a .dockerignore File** (Optional but Recommended) \*\*:
    
    * Create .dockerignore to exclude unnecessary files:
        
        ```text
        __pycache__
        *.pyc
        *.pyo
        *.pyd
        .Python
        env/
        venv/
        *.log
        ```
        
    * This reduces image size and build time
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741247170225/1aa25ff8-26e9-454e-b00d-471602888c59.png align="center")
        
3. **Build the Docker Image**:
    
    * Run:
        
        bash
        
        ```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)
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741247433504/904da339-2d31-4f33-968e-49d86946e8af.png align="center")
        
4. **Run and Test the Container Locally**:
    
    * Start the container:
        
        bash
        
        ```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 http://localhost:8000 and http://localhost:8000/health in a browser
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741247875693/b8322b6e-d9d8-4906-8c91-a5f38289733e.png align="center")
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741247970073/893f7598-0d8f-4090-af07-4074537fc02b.png align="center")
        
    * 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](https://hub.docker.com/).
        
    * Log in via terminal:
        
        bash
        
        ```bash
        docker login
        ```
        
    * Enter your Docker Hub username and password
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741248190576/a688a848-43ea-4774-a541-6741cc899312.png align="center")
        
2. **Tag the Image**:
    
    * Replace &lt;your-dockerhub-username&gt; with your actual username:
        
        bash
        
        ```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
        
        ```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
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741249208873/5cde8d88-b0e9-4a93-bedf-6d9b0ad690e8.png align="center")
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741249350404/8a58f4ec-3cb3-4dfe-b27e-be5bb0a0a930.png align="center")
        

### **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
        
        ```bash
        az login
        ```
        
    * A browser window will open; sign in to your Azure account
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741249523004/53279647-6e56-48f6-ba6b-c5a385218ec0.png align="center")
        
        .
        
2. **Set Default Subscription (if multiple exist)**:
    
    * List subscriptions:
        
        bash
        
        ```bash
        az account list --output table
        ```
        
    * Set the active subscription:
        
        bash
        
        ```bash
        az account set --subscription "<subscription-id>"
        ```
        
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741249628472/6edba3c0-b1bd-4f0b-a03a-abde1b377939.png align="center")
    
3. **Create a Resource Group**:
    
    * A resource group organizes Azure resources:
        
        bash
        
        ```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)
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741249889323/22ee9a14-c1c2-42fb-bcc8-f4bf28a14300.png align="center")
        
4. **Create an App Service Plan**:
    
    * App Service Plans define the compute resources. For Docker, use a Linux plan:
        
        bash
        
        ```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
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741250347549/3f052427-d087-442d-91fb-1a0b07270ed8.png align="center")
        
5. **Create a Web App**:
    
    * Replace &lt;your-app-name&gt; with a globally unique name (e.g., flaskapp-mazi):
        
        bash
        
        ```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
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741250932225/d75d06dc-94f7-4e95-b1ac-12d0ec605c7b.png align="center")
        
6. **Configure the Container Port**:
    
    * Azure needs to know which port your app uses (8000 in this case):
        
        bash
        
        ```bash
        az webapp config appsettings set --resource-group FlaskAppResourceGroup1 --name <your-app-name> --settings WEBSITES_PORT=8000
        ```
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741251098582/1458ae87-7345-4047-8eab-e5be30517dd4.png align="center")
        
    * Verify settings:
        
        bash
        
        ```bash
        az webapp config appsettings list --resource-group FlaskAppResourceGroup1 --name <your-app-name>
        ```
        
    
    ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741251267827/a57e09bc-47ea-49d5-8606-0a711a713811.png align="center")
    
7. **Restart the Web App** (if needed)\*\*:
    
    * Ensure changes take effect:
        
        bash
        
        ```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
        
        ```bash
        az webapp show --resource-group FlaskAppResourceGroup1 --name <your-app-name> --query "defaultHostName" --output tsv
        ```
        
    * Output looks like https://&lt;your-app-name&gt;.azurewebsites.net
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741251434869/0d237925-4646-4362-a4df-c48a8da5ff14.png align="center")
        
2. **Test in Browser**:
    
    * Open the URL (e.g., https://flaskapp-mazi.azurewebsites.net).
        
    * Check / and /health endpoints. Expect "Hello from Azure App Service via Docker created by isaac divine!" and "App is healthy!"
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741251604816/4d8818c0-e78d-4916-8a0f-0f75b4af8969.png align="center")
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741251747633/4624f544-6efa-4f32-850b-9cdc4d5243ea.png align="center")
        
3. **View Logs (if Issues Arise)**:
    
    * Stream logs:
        
        bash
        
        ```bash
        az webapp log tail --resource-group FlaskAppResourceGroup1 --name <your-app-name>
        ```
        
    * Look for errors like port misconfiguration or image pull failures
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741252288129/31ef9684-40f5-4fa2-95a7-65df1248817b.png align="center")
        

### **Step 6: (Optional) Enable Continuous Deployment**

Automate updates when you push new Docker images.

1. **Via Azure Portal**:
    
    * Go to [portal.azure.com](https://portal.azure.com/) &gt; Your Web App &gt; "Deployment Center".
        
    * Select "Docker Hub" &gt; Enter your image name (&lt;your-dockerhub-username&gt;/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
        
        ```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 &gt; "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 &gt; 70%)
        
        ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1741252717899/4c32a7fd-9f39-45db-9d02-a46bf148a630.png align="center")
        

### **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.
