Deploy a Django app with SQL Database using Infrastructure-As-Code

10 mins read

Learn how to use Azure Bicep to deploy a Django app with SQL DB.

Deploy a Django app with SQL Database using Infrastructure-As-Code

This article will show how you can deploy a simple Django application on an Ubuntu VM.

Solution OverviewPrerequisitesDeployment Steps

1. Solution Overview

We will leverage Infrastructure-as-Code using Azure Bicep, a Domain Specific Language (DSL) for deploying Azure resources declaratively.

We will utilize the Azure Linux CustomScript extension to silently install Python and Apache. The Bicep file will also create a SQL Database with some sample data.

The solution will include the following files:

📄 main.bicep: This is the Bicep template📄 azuredeploy.parameters.json: This parameter file contains the values to use for deploying your Bicep template.📁artifacts: This folder will contain a script named ‘install_django.sh’.

This template also provisions a storage account, virtual network, a public IP address, a network interface, and the SQL Server and SQL database required by the installation.

Django deployment

2. Prerequisites

An Active Azure account: You can create an account for free.Azure Bicep installed in your local machine.Azure PowerShell. See: Install Azure PowerShell.A resource group in your Azure subscription

Let’s get started!

3. Deployment Steps

3.1. Create SSH Key Pair

The first step is to create an SSH key pair; you can check the following article on how to create an SSH key pair for Linux VMs in Azure — https://docs.microsoft.com/en-us/azure/virtual-machines/linux/mac-create-ssh-keys

In this case, we will create an SSH key pair using the Azure Bash console. In the Azure Portal, request a new console as shown in the below image:

Cloud Shell — Azure Portal

Then we will generate an SSH Key using the command below:

ssh-keygen
-m PEM
-t rsa
-b 4096
-C “django”
-f ~/.ssh/django-key
-N yourpasshphrase

This will generate the Key under the SSH directory in your file share.

If you’re not familiar with the format of an SSH public key, you can display your public key with the following cat command, replace ‘~/.ssh/id_rsa.pub’ with the path and filename of your own public key file if needed:

cat ~/.ssh/django-key.pub

The above command will show the SSH public key in the console. We will need it during deployment time so have it at hand.

Cool! Now we have the SSH key pair. We will pass the value of this SSH Key in the parameters file.

3.2. Azure Bicep Template — parameters

Create a new file in your working directory and name it ‘main.bicep’. We will define the following parameters:

@description(‘Name of the Storage Account’)
param newStorageAccountName string@description(‘Username for the Administrator of the VM’)
param adminUsername string@description(‘Image Publisher’)
param imagePublisher string = ‘Canonical’@description(‘Image Offer’)
param imageOffer string = ‘UbuntuServer’@description(‘Image SKU’)
param imageSKU string = ‘18.04-LTS’@description(‘DNS Name for the Public IP. Must be lowercase.’)
param vmDnsName string@description(‘Admin username for SQL Database’)
param administratorLogin string@description(‘Admin password for SQL Database’)
@secure()
param administratorLoginPassword string@description(‘SQL Collation’)
param collation string = ‘SQL_Latin1_General_CP1_CI_AS’@description(‘Name of your SQL Database’)
param databaseName string@description(‘Max DB size in bytes’)
param maxSizeBytes int = 268435456000@description(‘Requested Service Objective ID’)
param requestedServiceObjectiveId string = ‘f1173c43-91bd-4aaa-973c-54e79e15235b’@description(‘Unique name of your SQL Server’)
param serverName string@description(‘Start IP for your firewall rule, for example 0.0.0.0’)
param firewallStartIP string = ‘0.0.0.0’@description(‘End IP for your firewall rule, for example 255.255.255.255’)
param firewallEndIP string = ‘0.0.0.0’@description(‘SQL Version’)
param version string = ‘12.0’@description(‘Location for all resources.’)
param location string = resourceGroup().location@allowed([
‘sshPublicKey’
‘password’
])
@description(‘Type of authentication to use on the Virtual Machine. SSH key is recommended.’)
param authenticationType string = ‘sshPublicKey’@description(‘SSH Key or password for the Virtual Machine. SSH key is recommended.’)
@secure()
param adminPasswordOrKey string@description(‘Default VM Size’)
param vmSize string = ‘Standard_B1s’

3. Azure Bicep Template — variables

We will define the following variables:

var nicName_var = ‘myVMNic’
var addressPrefix = ‘10.0.0.0/16’
var subnetName = ‘Subnet-1’
var subnetPrefix = ‘10.0.0.0/24’
var storageAccountType = ‘Standard_LRS’
var publicIPAddressName_var = ‘myPublicIP’
var publicIPAddressType = ‘Dynamic’
var vmName_var = vmDnsName
var virtualNetworkName_var = ‘MyVNET’
var subnetRef = resourceId(‘Microsoft.Network/virtualNetworks/subnets’, virtualNetworkName_var, subnetName)
var linuxConfiguration = {
disablePasswordAuthentication: true
ssh: {
publicKeys: [
{
path: ‘/home/${adminUsername}/.ssh/authorized_keys’
keyData: adminPasswordOrKey
}
]
}
}

4. Azure Bicep Template — resources

We will define the following resources:

resource serverName_resource ‘Microsoft.Sql/servers@2020-11-01-preview’ = {
location: location
name: serverName
properties: {
administratorLogin: administratorLogin
administratorLoginPassword: administratorLoginPassword
version: version
}
}resource serverName_databaseName ‘Microsoft.Sql/servers/databases@2020-11-01-preview’ = {
parent: serverName_resource
location: location
name: databaseName
properties: {
collation: collation
maxSizeBytes: maxSizeBytes
recoveryServicesRecoveryPointId: requestedServiceObjectiveId
}
}resource serverName_FirewallRule1 ‘Microsoft.Sql/servers/firewallrules@2020-11-01-preview’ = {
parent: serverName_resource
name: ‘FirewallRule1’
properties: {
endIpAddress: firewallEndIP
startIpAddress: firewallStartIP
}
}resource newStorageAccountName_resource ‘Microsoft.Storage/storageAccounts@2021-02-01’ = {
name: newStorageAccountName
location: location
sku: {
name: storageAccountType
}
kind: ‘StorageV2’
}resource publicIPAddressName ‘Microsoft.Network/publicIPAddresses@2020-07-01’ = {
name: publicIPAddressName_var
location: location
properties: {
publicIPAllocationMethod: publicIPAddressType
dnsSettings: {
domainNameLabel: vmDnsName
}
}
}resource virtualNetworkName ‘Microsoft.Network/virtualNetworks@2020-07-01’ = {
name: virtualNetworkName_var
location: location
properties: {
addressSpace: {
addressPrefixes: [
addressPrefix
]
}
subnets: [
{
name: subnetName
properties: {
addressPrefix: subnetPrefix
}
}
]
}
}resource nicName ‘Microsoft.Network/networkInterfaces@2020-07-01’ = {
name: nicName_var
location: location
properties: {
ipConfigurations: [
{
name: ‘ipconfig1’
properties: {
privateIPAllocationMethod: ‘Dynamic’
publicIPAddress: {
id: publicIPAddressName.id
}
subnet: {
id: subnetRef
}
}
}
]
}
dependsOn: [
virtualNetworkName
]
}resource vmName ‘Microsoft.Compute/virtualMachines@2020-12-01’ = {
name: vmName_var
location: location
properties: {
hardwareProfile: {
vmSize: vmSize
}
osProfile: {
computerName: vmName_var
adminUsername: adminUsername
adminPassword: adminPasswordOrKey
linuxConfiguration: ((authenticationType == ‘password’) ? json(‘null’) : linuxConfiguration)
}
storageProfile: {
imageReference: {
publisher: imagePublisher
offer: imageOffer
sku: imageSKU
version: ‘latest’
}
osDisk: {
name: ‘${vmName_var}_OSDisk’
caching: ‘ReadWrite’
createOption: ‘FromImage’
}
}
networkProfile: {
networkInterfaces: [
{
id: nicName.id
}
]
}
}
dependsOn: [
newStorageAccountName_resource
]
}resource vmName_django ‘Microsoft.Compute/virtualMachines/extensions@2020-12-01’ = {
parent: vmName
name: ‘django’
location: location
properties: {
publisher: ‘Microsoft.Azure.Extensions’
type: ‘CustomScript’
typeHandlerVersion: ‘2.0’
autoUpgradeMinorVersion: true
settings: {
fileUris: [
https://gist.githubusercontent.com/daveRendon/bf68e2b419a5907eb639e6265be70cda/raw/818c370103e09ea61c5cd4d573ee8e9d77d6fc09/install_django.sh’
]
}
protectedSettings: {
commandToExecute: ‘sh install_django.sh ${vmDnsName} ${serverName} ${administratorLogin} ${administratorLoginPassword} ${databaseName}’
}
}
}

Note we use an Azure Linux CustomScript extension to install Django. This script should be publicly accessible during deployment time. Therefore, you can either store it on a storage account and pass on the SAS token and the URL where the file is located.

Another option is to host the script in a public repository: https://gist.githubusercontent.com/daveRendon/bf68e2b419a5907eb639e6265be70cda/raw/818c370103e09ea61c5cd4d573ee8e9d77d6fc09/install_django.sh

5. Parameters file

Create a new file named ‘azuredeploy.parameters.json’. The code below shows the definition of the parameters file:

{
“$schema”: “https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#“,
“contentVersion”: “1.0.0.0”,
“parameters”: {
“newStorageAccountName”: {
“value”: “YOUR-STORAGE-ACCOUNT-NAME”
},
“adminUsername”: {
“value”: “YOUR-ADMIN-USERNAME”
},
“vmDnsName”: {
“value”: “YOUR-VM-DNS-NAME”
},
“administratorLogin”: {
“value”: “YOUR-ADMIN-LOGIN”
},
“administratorLoginPassword”: {
“value”: “YOUR-ADMIN-PASS”
},
“databaseName”: {
“value”: “YOUR-DATABASE-NAME”
},
“serverName”: {
“value”: “YOUR-SERVER-NAME”
},
“firewallStartIP”: {
“value”: “0.0.0.0”
},
“firewallEndIP”: {
“value”: “255.255.255.255”
},
“adminPasswordOrKey”: {
“value”: “YOUR-SSH-KEY”
}
}
}

6. Azure Bicep Template — Deployment

We will use the command below to deploy our Bicep template:

$date = Get-Date -Format “MM-dd-yyyy”
$deploymentName = “AzInsiderDeployment”+”$date”New-AzResourceGroupDeployment -Name $deploymentName -ResourceGroupName azinsider_demo -TemplateFile .main.bicep -TemplateParameterFile .azuredeploy.parameters.json -c

The image below shows the deployment output:

Deployment output

Once the deployment is complete — usually takes a few mins — you can go and grab the Public IP address or the FQDN and access using your browser. You will see the app running as shown below:

Django with SQL database in Azure using Bicep

You can find the code of this solution in the following URL, feel free to contribute!

azinsider/application-workloads/django-with-sql-db at main · daveRendon/azinsider

👉 Join the AzInsider email list here.

-Dave R.

💪Deploy a Django app with SQL Database using Infrastructure-As-Code was originally published in CodeX on Medium, where people are continuing the conversation by highlighting and responding to this story.

Leave a Reply

Your email address will not be published.

Follow Us