Table of contents
- Step 1: Create and Test the Web Application Locally
- Step 2: Containerize the Application with Docker
- Step 3: Push the Docker Image to a Container Registry
- Step 4: Deploy to Azure App Service
- Step 5: Verify and Test the Deployment
- Step 6: (Optional) Enable Continuous Deployment
- Step 7: Monitor and Scale
- Troubleshooting
- Conclusion
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.
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
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
Create a Requirements File (requirements.txt):
Create requirements.txt and add:
Flask==2.3.2
This specifies the Flask version for consistency
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.
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
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
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)
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.
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
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.
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.
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.
Log in to Azure CLI:
Run:
bash
az login
A browser window will open; sign in to your Azure account
.
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>"
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)
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
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
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>
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
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
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!"
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.
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.
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
Monitoring:
In the Azure Portal, go to your Web App > "Log Stream" or "Metrics".
Check CPU, memory, and request counts.
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.