|
1 |
| -# Deploy a Python (Flask) web app to Azure App Service - Sample Application |
| 1 | +# Python Flask Web Application Deployment to Azure |
2 | 2 |
|
3 |
| -This project demonstrates how to deploy a containerized Python Flask application to Azure using Infrastructure as Code (IaC) with Bicep and GitHub Actions for CI/CD. |
| 3 | +This project demonstrates how to containerize a Python Flask application and deploy it to Azure using Infrastructure as Code (Bicep) and GitHub Actions. |
4 | 4 |
|
5 |
| -## Infrastructure Components |
| 5 | +## Development Process Steps |
6 | 6 |
|
7 |
| -The solution consists of three main Azure resources: |
| 7 | +### 1. Container Development and Local Testing |
8 | 8 |
|
9 |
| -1. **Azure Key Vault** - Securely stores credentials |
10 |
| -2. **Azure Container Registry (ACR)** - Hosts the application container images |
11 |
| -3. **Azure Web App** - Runs the containerized application |
| 9 | +First, I developed and tested the application locally: |
12 | 10 |
|
13 |
| -## Project Structure |
| 11 | +```bash |
| 12 | +# Build the container |
| 13 | +docker build -t myapp . |
14 | 14 |
|
15 |
| -``` |
16 |
| -├── .github/workflows/ |
17 |
| -│ └── workflow.yaml # GitHub Actions CI/CD pipeline |
18 |
| -├── modules/ |
19 |
| -│ ├── key-vault.bicep # Key Vault infrastructure |
20 |
| -│ ├── container-registry.bicep # ACR infrastructure |
21 |
| -│ └── web-app.bicep # Web App infrastructure |
22 |
| -├── main.bicep # Main infrastructure template |
23 |
| -├── main.parameters.json # Infrastructure parameters |
24 |
| -└── Dockerfile # Container image definition |
| 15 | +# Run and test locally |
| 16 | +docker run -p 5000:5000 myapp |
| 17 | + |
| 18 | +# Test in browser: http://localhost:5000 |
25 | 19 | ```
|
26 | 20 |
|
27 |
| -## Getting Started |
| 21 | +### 2. Infrastructure Development |
28 | 22 |
|
29 |
| -### 1. Customize Parameters |
| 23 | +After confirming the container works, I built the infrastructure in steps: |
30 | 24 |
|
31 |
| -Before deploying, modify `main.parameters.json` to replace existing names with your own: |
| 25 | +1. Created `main.bicep` with basic resource structure: |
32 | 26 |
|
33 |
| -- Replace all instances of `dkumlin` with your identifier |
34 |
| -- Example changes: |
35 |
| - ```json |
36 |
| - { |
37 |
| - "keyVaultName": { "value": "yourname-kv" }, |
38 |
| - "containerRegistryName": { "value": "yournamecr" }, |
39 |
| - "webAppName": { "value": "yourname-webapp" } |
40 |
| - } |
41 |
| - ``` |
| 27 | + - Key Vault |
| 28 | + - Container Registry |
| 29 | + - Web App |
42 | 30 |
|
43 |
| -### 2. Update GitHub Workflow |
| 31 | +2. Developed individual module files in `/modules`: |
| 32 | + - `key-vault.bicep`: Stores ACR credentials securely |
| 33 | + - `container-registry.bicep`: Hosts our container images |
| 34 | + - `web-app.bicep`: Runs our containerized application |
44 | 35 |
|
45 |
| -Modify `.github/workflows/workflow.yaml` environment variables: |
| 36 | +### 3. GitHub Actions Workflow |
46 | 37 |
|
47 |
| -```yaml |
48 |
| -env: |
49 |
| - KEY_VAULT_NAME_DEV: "yourname-kv" |
50 |
| - CONTAINER_REGISTRY_SERVER_URL_DEV: "yournamecr.azurecr.io" |
51 |
| - IMAGE_NAME_DEV: "yourname-app" |
52 |
| - WEB_APP: "yourname-webapp" |
53 |
| -``` |
| 38 | +Created `.github/workflows/workflow.yaml` with three main stages: |
| 39 | + |
| 40 | +1. **Infrastructure Deployment Stage** |
54 | 41 |
|
55 |
| -### 3. Configure GitHub Secrets |
| 42 | + - Deploys all Bicep templates |
| 43 | + - Creates/updates Azure resources |
| 44 | + - Sets up RBAC permissions |
56 | 45 |
|
57 |
| -Set up required GitHub repository secrets: |
| 46 | +2. **Container Build & Push Stage** |
58 | 47 |
|
59 |
| -- `AZURE_CREDENTIALS`: Service principal credentials |
60 |
| -- `AZURE_SUBSCRIPTION`: Subscription ID (For the resource subsciption) |
| 48 | + - Builds the Docker image |
| 49 | + - Tags with git SHA |
| 50 | + - Pushes to Azure Container Registry |
61 | 51 |
|
62 |
| -## How the Infrastructure Works |
| 52 | +3. **Web App Deployment Stage** |
| 53 | + - Pulls latest image from ACR |
| 54 | + - Deploys to Azure Web App |
| 55 | + - Updates container configuration |
63 | 56 |
|
64 |
| -### Deployment Flow |
| 57 | +## How to Use This Project |
65 | 58 |
|
66 |
| -1. **Infrastructure Deployment** |
| 59 | +### Prerequisites |
67 | 60 |
|
68 |
| - - Bicep templates create/update Azure resources |
69 |
| - - RBAC permissions are configured automatically |
70 |
| - - Resources are created in the specified order: |
71 |
| - 1. Key Vault |
72 |
| - 2. Container Registry |
73 |
| - 3. Web App |
| 61 | +- Azure Subscription |
| 62 | +- GitHub Account |
| 63 | +- Docker Desktop |
| 64 | +- Azure CLI |
74 | 65 |
|
75 |
| -2. **Application Deployment** |
76 |
| - - GitHub Actions workflow: |
77 |
| - 1. Builds container image |
78 |
| - 2. Retrieves ACR credentials from Key Vault |
79 |
| - 3. Pushes image to ACR |
80 |
| - 4. Deploys to Web App |
| 66 | +### Deployment Steps |
81 | 67 |
|
82 |
| -### Customizing the Infrastructure |
| 68 | +1. **Fork/Clone the Repository** |
83 | 69 |
|
84 |
| -#### Modify Key Vault (modules/key-vault.bicep) |
| 70 | +2. **Update Parameters** |
| 71 | + Replace all instances of `dkumlin` with your identifier in: |
85 | 72 |
|
86 |
| -- Change SKU tier |
87 |
| -- Add/modify role assignments |
88 |
| -- Adjust network access rules |
| 73 | + ```json |
| 74 | + // main.parameters.json |
| 75 | + { |
| 76 | + "keyVaultName": { "value": "yourname-kv" }, |
| 77 | + "containerRegistryName": { "value": "yourname-cr" }, |
| 78 | + "webAppName": { "value": "yourname-webapp" } |
| 79 | + } |
| 80 | + ``` |
89 | 81 |
|
90 |
| -```bicep |
91 |
| -resource keyVault 'Microsoft.KeyVault/vaults@2022-07-01' = { |
92 |
| - properties: { |
93 |
| - sku: { |
94 |
| - family: 'A' |
95 |
| - name: 'standard' // Change to 'premium' if needed |
96 |
| - } |
97 |
| - // Add network rules here |
98 |
| - } |
99 |
| -} |
100 |
| -``` |
| 82 | +3. **Configure GitHub Secrets** |
| 83 | + Add to your repository: |
101 | 84 |
|
102 |
| -#### Customize Container Registry (modules/container-registry.bicep) |
| 85 | + - `AZURE_CREDENTIALS` |
| 86 | + - `AZURE_SUBSCRIPTION` |
103 | 87 |
|
104 |
| -- Change SKU |
105 |
| -- Enable/disable features |
106 |
| -- Configure geo-replication |
| 88 | +4. **Update Workflow Variables** |
| 89 | + In `.github/workflows/workflow.yaml`: |
107 | 90 |
|
108 |
| -```bicep |
109 |
| -resource acr 'Microsoft.ContainerRegistry/registries@2023-01-01-preview' = { |
110 |
| - sku: { |
111 |
| - name: 'Basic' // Change to 'Standard' or 'Premium' |
112 |
| - } |
113 |
| -} |
114 |
| -``` |
| 91 | + ```yaml |
| 92 | + env: |
| 93 | + KEY_VAULT_NAME_DEV: "yourname-kv" |
| 94 | + CONTAINER_REGISTRY_SERVER_URL_DEV: "yournamecr.azurecr.io" |
| 95 | + IMAGE_NAME_DEV: "yourname-app" |
| 96 | + WEB_APP: "yourname-webapp" |
| 97 | + ``` |
115 | 98 |
|
116 |
| -#### Modify Web App (modules/web-app.bicep) |
117 |
| - |
118 |
| -- Change pricing tier |
119 |
| -- Adjust app settings |
120 |
| -- Configure scaling |
121 |
| - |
122 |
| -```bicep |
123 |
| -resource webApp 'Microsoft.Web/sites@2022-03-01' = { |
124 |
| - properties: { |
125 |
| - siteConfig: { |
126 |
| - linuxFxVersion: 'DOCKER|${containerImage}' |
127 |
| - // Add custom app settings |
128 |
| - appSettings: [] |
129 |
| - } |
130 |
| - } |
131 |
| -} |
| 99 | +5. **Deploy** |
| 100 | + - Push to main branch |
| 101 | + - GitHub Actions will handle the deployment |
| 102 | +
|
| 103 | +## Project Structure |
| 104 | +
|
| 105 | +``` |
| 106 | +├── .github/workflows/ |
| 107 | +│ └── workflow.yaml # CI/CD pipeline |
| 108 | +├── modules/ |
| 109 | +│ ├── key-vault.bicep # Key Vault infrastructure |
| 110 | +│ ├── container-registry.bicep # ACR infrastructure |
| 111 | +│ └── web-app.bicep # Web App infrastructure |
| 112 | +├── main.bicep # Main infrastructure template |
| 113 | +├── main.parameters.json # Infrastructure parameters |
| 114 | +└── Dockerfile # Container image definition |
132 | 115 | ```
|
133 | 116 |
|
134 | 117 | ## Troubleshooting
|
135 | 118 |
|
136 |
| -Common issues and solutions: |
| 119 | +### Common Issues |
137 | 120 |
|
138 |
| -1. **Deployment Failures** |
| 121 | +1. **Resource Name Conflicts** |
139 | 122 |
|
140 |
| - - Check resource name uniqueness |
141 |
| - - Verify service principal permissions |
142 |
| - - Review deployment logs in Azure Portal |
| 123 | + - Ensure all resource names are unique |
| 124 | + - Update parameters with your unique identifiers |
143 | 125 |
|
144 |
| -2. **Container Issues** |
| 126 | +2. **Container Registry Access** |
145 | 127 |
|
146 |
| - - Verify ACR credentials in Key Vault |
147 |
| - - Check container logs in Web App |
148 |
| - - Ensure container image exists in ACR |
| 128 | + - Verify Key Vault contains correct ACR credentials |
| 129 | + - Check service principal has proper permissions |
149 | 130 |
|
150 |
| -3. **Access Issues** |
151 |
| - - Check RBAC role assignments |
152 |
| - - Verify service principal hasn't expired |
153 |
| - - Confirm Key Vault access policies |
| 131 | +3. **Web App Deployment** |
| 132 | + - Check container logs in Azure Portal |
| 133 | + - Verify container image exists in ACR |
| 134 | + - Confirm Web App configuration matches container |
154 | 135 |
|
155 |
| -## Prerequisites |
| 136 | +### Useful Commands |
156 | 137 |
|
157 |
| -- Azure Subscription |
158 |
| -- GitHub Account |
159 |
| -- Azure CLI (for local testing) |
160 |
| -- Docker (for local testing) |
| 138 | +```bash |
| 139 | +# Check container locally |
| 140 | +docker build -t myapp . |
| 141 | +docker run -p 5000:5000 myapp |
| 142 | + |
| 143 | +``` |
0 commit comments