Skip to content

Commit f49b081

Browse files
committed
First try?
1 parent 223b3cf commit f49b081

15 files changed

+629
-0
lines changed

.dockerignore

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
**/__pycache__
2+
**/.venv
3+
**/.classpath
4+
**/.dockerignore
5+
**/.env
6+
**/.git
7+
**/.gitignore
8+
**/.project
9+
**/.settings
10+
**/.toolstarget
11+
**/.vs
12+
**/.vscode
13+
**/*.*proj.user
14+
**/*.dbmdl
15+
**/*.jfm
16+
**/bin
17+
**/charts
18+
**/docker-compose*
19+
**/compose*
20+
**/Dockerfile*
21+
**/node_modules
22+
**/npm-debug.log
23+
**/obj
24+
**/secrets.dev.yaml
25+
**/values.dev.yaml
26+
LICENSE
27+
README.md

.github/workflows/infra.yml

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
name: Deploy Infrastructure
2+
3+
on:
4+
workflow_dispatch:
5+
pull_request:
6+
branches:
7+
- main
8+
push:
9+
branches:
10+
- 'main'
11+
12+
env:
13+
14+
DOCKER_REGISTRY_SERVER_URL: tmesalles.azurecr.io
15+
KEY_VAULT_NAME: tmesalles-kv
16+
IMAGE_NAME: tmesalles-dockerimg
17+
APP_SERVICE_NAME: tmesalles-appservice
18+
19+
RESOURCE_GROUP_DEV: BCSAI2024-DEVOPS-STUDENTS-B-DEV
20+
SUBSCRIPTION_ID_DEV: e0b9cada-61bc-4b5a-bd7a-52c606726b3b
21+
22+
USER_ALIAS: tmesalles
23+
24+
jobs:
25+
build-exericse:
26+
runs-on: ubuntu-latest
27+
steps:
28+
# Checkout code
29+
- uses: actions/checkout@main
30+
# Lint Bicep code
31+
- name: Run Bicep linter
32+
run: az bicep build --file ./main.bicep
33+
34+
- name: Upload Bicep build artifact
35+
uses: actions/upload-artifact@v3
36+
with:
37+
name: bicep-build
38+
path: ./main.bicep
39+
40+
# Checkout the repository to the runner.
41+
- name: Checkout
42+
uses: actions/checkout@v3
43+
44+
45+
deploy:
46+
runs-on: ubuntu-latest
47+
needs: build-exericse
48+
49+
steps:
50+
51+
- uses: actions/checkout@main
52+
53+
- name: Download Bicep build artifact
54+
uses: actions/download-artifact@v3
55+
with:
56+
name: bicep-build
57+
58+
# Log into Azure
59+
- uses: azure/login@v2
60+
with:
61+
creds: ${{ secrets.AZURE_CREDENTIALS }}
62+
63+
- name: deploy
64+
uses: azure/arm-deploy@v2
65+
with:
66+
subscriptionId: ${{ env.SUBSCRIPTION_ID_DEV }}
67+
resourceGroupName: ${{ env.RESOURCE_GROUP_DEV }}
68+
template: ./main.bicep
69+
parameters: >
70+
./infra/parameters.bicepparam
71+
build-push-image:
72+
runs-on: ubuntu-latest
73+
needs: deploy
74+
outputs:
75+
image-version: ${{ steps.image-version.outputs.version }}
76+
77+
78+
steps:
79+
- uses: actions/checkout@v4
80+
81+
- name: "Log in to azure"
82+
uses: azure/login@v2
83+
with:
84+
creds: ${{ secrets.AZURE_CREDENTIALS }}
85+
86+
- name: "Get container registry credentials from vault"
87+
run: |
88+
REGISTRY_USERNAME=$(az keyvault secret show --name tmesalles-cr-username --vault-name ${{ env.KEY_VAULT_NAME }} --query value -o tsv)
89+
REGISTRY_PASSWORD=$(az keyvault secret show --name tmesalles-cr-password0 --vault-name ${{ env.KEY_VAULT_NAME }} --query value -o tsv)
90+
echo "REGISTRY_USERNAME=${REGISTRY_USERNAME}" >> $GITHUB_ENV
91+
echo "REGISTRY_PASSWORD=${REGISTRY_PASSWORD}" >> $GITHUB_ENV
92+
- name: "Set image version"
93+
id: image-version
94+
run: |
95+
echo "version=$(date +'%Y.%m.%d.%H.%M')" >> $GITHUB_OUTPUT
96+
- name: "Print images"
97+
run: |
98+
echo "Images"
99+
docker images
100+
- name: "Docker build and push image"
101+
run: |
102+
docker build -t ${{ env.DOCKER_REGISTRY_SERVER_URL }}/${{ env.IMAGE_NAME}}:${{ steps.image-version.outputs.version}} .
103+
docker login ${{ env.DOCKER_REGISTRY_SERVER_URL }} -u ${{ env.REGISTRY_USERNAME }} -p ${{ env.REGISTRY_PASSWORD }}
104+
docker push ${{ env.DOCKER_REGISTRY_SERVER_URL }}/${{ env.IMAGE_NAME}}:${{ steps.image-version.outputs.version}}
105+
deploy-container:
106+
runs-on: ubuntu-latest
107+
needs: build-push-image
108+
steps:
109+
- name: Login to Azure
110+
uses: azure/login@v1
111+
with:
112+
creds: ${{ secrets.AZURE_CREDENTIALS }}
113+
114+
- name: Deploy Docker Image to Azure Web App
115+
uses: azure/webapps-deploy@v3
116+
with:
117+
app-name: ${{ env.APP_SERVICE_NAME }}
118+
images: |
119+
${{ env.DOCKER_REGISTRY_SERVER_URL }}/${{ env.IMAGE_NAME }}:${{ needs.build-push-image.outputs.image-version }}

.vscode/launch.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"configurations": [
3+
{
4+
"name": "Docker: Python - Flask",
5+
"type": "docker",
6+
"request": "launch",
7+
"preLaunchTask": "docker-run: debug",
8+
"python": {
9+
"pathMappings": [
10+
{
11+
"localRoot": "${workspaceFolder}",
12+
"remoteRoot": "/app"
13+
}
14+
],
15+
"projectType": "flask"
16+
}
17+
}
18+
]
19+
}

.vscode/tasks.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"version": "2.0.0",
3+
"tasks": [
4+
{
5+
"type": "docker-build",
6+
"label": "docker-build",
7+
"platform": "python",
8+
"dockerBuild": {
9+
"tag": "msdocspythonflaskwebappquickstart:latest",
10+
"dockerfile": "${workspaceFolder}/Dockerfile",
11+
"context": "${workspaceFolder}",
12+
"pull": true
13+
}
14+
},
15+
{
16+
"type": "docker-run",
17+
"label": "docker-run: debug",
18+
"dependsOn": [
19+
"docker-build"
20+
],
21+
"dockerRun": {
22+
"env": {
23+
"FLASK_APP": "app.py"
24+
}
25+
},
26+
"python": {
27+
"args": [
28+
"run",
29+
"--no-debugger",
30+
"--no-reload",
31+
"--host",
32+
"0.0.0.0",
33+
"--port",
34+
"5002"
35+
],
36+
"module": "flask"
37+
}
38+
}
39+
]
40+
}

docker-compose.debug.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
version: '3.4'
2+
3+
services:
4+
msdocspythonflaskwebappquickstart:
5+
image: msdocspythonflaskwebappquickstart
6+
build:
7+
context: .
8+
dockerfile: ./Dockerfile
9+
command: ["sh", "-c", "pip install debugpy -t /tmp && python /tmp/debugpy --wait-for-client --listen 0.0.0.0:5678 -m flask run --no-debugger --no-reload --host 0.0.0.0 --port 5002"]
10+
ports:
11+
- 5002:5002
12+
- 5678:5678
13+
environment:
14+
- FLASK_APP=app.py

docker-compose.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
version: '3.4'
2+
3+
services:
4+
msdocspythonflaskwebappquickstart:
5+
image: msdocspythonflaskwebappquickstart
6+
build:
7+
context: .
8+
dockerfile: ./Dockerfile
9+
ports:
10+
- 5002:5002

dockerfile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# For more information, please refer to https://aka.ms/vscode-docker-python
2+
FROM python:3-slim
3+
4+
EXPOSE 5002
5+
6+
# Keeps Python from generating .pyc files in the container
7+
ENV PYTHONDONTWRITEBYTECODE=1
8+
9+
# Turns off buffering for easier container logging
10+
ENV PYTHONUNBUFFERED=1
11+
12+
# Install pip requirements
13+
COPY requirements.txt .
14+
RUN python -m pip install -r requirements.txt
15+
16+
WORKDIR /app
17+
COPY . /app
18+
19+
# Creates a non-root user with an explicit UID and adds permission to access the /app folder
20+
# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers
21+
RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
22+
USER appuser
23+
24+
# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
25+
CMD ["gunicorn", "--bind", "0.0.0.0:5002", "app:app"]

gunicorn.conf.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Gunicorn configuration file
2+
import multiprocessing
3+
4+
max_requests = 1000
5+
max_requests_jitter = 50
6+
7+
log_file = "-"
8+
9+
bind = "0.0.0.0:50505"
10+
11+
workers = (multiprocessing.cpu_count() * 2) + 1
12+
threads = workers
13+
14+
timeout = 120

infra/azure-app-service.bicep

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
param name string
2+
param location string = resourceGroup().location
3+
param appServicePlanId string
4+
5+
param registryName string
6+
@secure()
7+
param registryServerUserName string
8+
@secure()
9+
param registryServerPassword string
10+
param registryImageName string
11+
param registryImageVersion string
12+
param appSettings array = []
13+
var dockerAppSettings = [
14+
{ name: 'WEBSITES_ENABLE_APP_SERVICE_STORAGE', value: 'false' }
15+
{ name: 'DOCKER_REGISTRY_SERVER_URL', value: 'https://${registryName}.azurecr.io' }
16+
{ name: 'DOCKER_REGISTRY_SERVER_USERNAME', value: registryServerUserName }
17+
{ name: 'DOCKER_REGISTRY_SERVER_PASSWORD', value: registryServerPassword }
18+
]
19+
20+
resource containerAppService 'Microsoft.Web/sites@2022-03-01' = {
21+
name: name
22+
location: location
23+
kind: 'app'
24+
properties: {
25+
serverFarmId: appServicePlanId
26+
siteConfig: {
27+
linuxFxVersion: 'DOCKER|${registryName}.azurecr.io/${registryImageName}:${registryImageVersion}'
28+
appCommandLine: ''
29+
appSettings: union(appSettings, dockerAppSettings)
30+
}
31+
}
32+
}

infra/azure-service-plan.bicep

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
param location string
2+
param name string
3+
param sku string
4+
5+
resource appServicePlan 'Microsoft.Web/serverFarms@2022-03-01' = {
6+
name: name
7+
location: location
8+
sku: {
9+
name: sku
10+
capacity: 1
11+
family: 'B'
12+
size: 'B1'
13+
tier: 'Basic'
14+
}
15+
kind: 'linux'
16+
properties: {
17+
reserved: true
18+
}
19+
}
20+
21+
output id string = appServicePlan.id
22+
output name string = appServicePlan.name

infra/container-registry.bicep

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
param name string
2+
param location string = resourceGroup().location
3+
param sku string = 'Basic'
4+
param adminUserEnabled bool = true
5+
#disable-next-line secure-secrets-in-params
6+
7+
param keyVaultResourceId string
8+
param usernameSecretName string
9+
#disable-next-line secure-secrets-in-params
10+
param password0SecretName string
11+
#disable-next-line secure-secrets-in-params
12+
param password1SecretName string
13+
14+
// Creating container registry
15+
resource containerRegistry 'Microsoft.ContainerRegistry/registries@2023-07-01' = {
16+
name: name
17+
location: location
18+
sku: {
19+
name: sku
20+
}
21+
properties: {
22+
adminUserEnabled: adminUserEnabled
23+
}
24+
}
25+
26+
// Reference the existing Key Vault
27+
resource adminCredentialsKeyVault 'Microsoft.KeyVault/vaults@2022-07-01' existing = {
28+
name: last(split(keyVaultResourceId, '/')) // Extract the name from the resource ID
29+
}
30+
31+
// Store the admin username in Key Vault
32+
resource secretAdminUserName 'Microsoft.KeyVault/vaults/secrets@2023-02-01' = {
33+
name: usernameSecretName
34+
parent: adminCredentialsKeyVault
35+
properties: {
36+
value: containerRegistry.listCredentials().username
37+
}
38+
}
39+
40+
// Store the first admin password in Key Vault
41+
resource secretAdminUserPassword0 'Microsoft.KeyVault/vaults/secrets@2023-02-01' = {
42+
name: password0SecretName
43+
parent: adminCredentialsKeyVault
44+
properties: {
45+
value: containerRegistry.listCredentials().passwords[0].value
46+
}
47+
}
48+
49+
// Store the second admin password in Key Vault
50+
resource secretAdminUserPassword1 'Microsoft.KeyVault/vaults/secrets@2023-02-01' = {
51+
name: password1SecretName
52+
parent: adminCredentialsKeyVault
53+
properties: {
54+
value: containerRegistry.listCredentials().passwords[1].value
55+
}
56+
}
57+
58+
// Output values for verification
59+
output containerRegistryName string = containerRegistry.name
60+
output containerRegistryLoginServer string = containerRegistry.properties.loginServer

0 commit comments

Comments
 (0)