Infrastructure as Code (IaC) is a method of provisioning and managing infrastructure using code and automation tools, rather than manual configuration. The goal of IaC is to make it easy to provision, update, and manage infrastructure, while also providing a way to version control and audit changes.
With IaC, infrastructure is defined in a code file, such as a YAML or JSON, and then provisioned using a tool such as Terraform. This code file acts as a single source of truth for the infrastructure, and can be version controlled, meaning that the history of changes to the infrastructure can be tracked, and rollback to a previous version can be done easily.
But, for this tutorial, I am going to use Pulumi, an open-source tool that allows you to define your infrastructure as code and automate the deployment of it on Azure. Pulumi enables you to use your preferred programming language to define your infrastructure, making it easy to understand and manage for developers than working with YAMLs. I will be using Python to deploy a simple Dockerized Flask app here.
Prerequisites
Before you begin, you should have the following things set up:
A Microsoft Azure account. You can sign up for a free account at azure.com. If you are a student, you can create a free Azure account and get a free $100 credit even without a credit card. For more details: azure.microsoft.com/en-in/free/students
The Azure CLI installed on your computer. You can install the Azure CLI by following the instructions at learn.microsoft.com/en-us/cli/azure/install-azure-cli.
Pulumi CLI installed on your machine. You can install it using: pulumi.com/docs/get-started/install
Docker installed on your machine in order to build and push the Docker image of your application. You can install it from here docs.docker.com/get-docker
Dockerfile: You will need to have a Dockerfile for your application that you intend to deploy.
I would recommend everyone to go through the Pulumi Docs to understand the API, on how to communicate with various services.
Writing the Code:
Before going to the code, ensure that you are logged in to Azure and Pulumi.
You can login to Azure by entering the following command in your terminal
az login
Similarly, login to Pulumi by entering:
pulumi login
You can initialize a new Pulumi project in python by entering:
pulumi new python
Follow the prompts in creating a stack.
Now let's go through the __main__.py
file. It contains the entire logic that is needed for pulumi to provision infrastructure. Remove the given boilerplate code with the one below. We shall go line by line in writing it.
import pulumi
import pulumi_docker as docker
import pulumi_azure_native.resources as resources
import pulumi_azure_native.web as web
Importing the necessary libraries: The first few lines of the code contains the import statements for the necessary libraries of the script, i.e, pulumi
, pulumi_docker
, pulumi_azure_native.resources
, and pulumi_azure_native.web
. These libraries are required for interacting with Azure and Docker using Pulumi.
You need to add pulumi_docker
and pulumi_azure_native
to your virtual environment which Pulumi has created in the venv
folder. Now activate the virtual environment and install those packages:
source venv/bin/activate # For Linux/Mac
# venv\Scripts\activate # For Windows
pip install pulumi_docker pulumi_azure_native
config = pulumi.Config()
dockerHubUserName = config.require("username")
dockerHubPassword = config.require("password")
Configuring the necessary parameters: The config variable is used to read the username and password from the Pulumi configuration, which will be used later to authenticate to the Docker registry.
You can add those secrets to your Pulumi configuration by entering the following lines in your terminal:
pulumi config set --secret username YOUR_DOCKERHUB_USERNAME
pulumi config set --secret password YOUR_DOCKERHUB_ACCESS_TOKEN
You can generate an access token for your Docker Hub account on hub.docker.com/settings/security
imageName = "flask_azure_pulumi"
imageTag = "v1.0.0" # Change to whatever version you are creating
azureResourceLocation = (
"UAE North" # Change to the region that is closest to your end users
)
The imageName variable is set to flask_azure_pulumi
and imageTag variable is set to v1.0.0
, you can change it to the version you are creating. The azureResourceLocation variable is set to UAE North, but you can change it to the region that is closest to your end users. I have chosen UAE North because it is the closest location to me having an F1 tier.
flaskAzureImage = docker.Image(
imageName,
build=docker.DockerBuild(context="app"),
image_name=f"{dockerHubUserName}/{imageName}:{imageTag}",
registry=docker.ImageRegistry(
server="docker.io", username=dockerHubUserName, password=dockerHubPassword
),
)
Building the Docker image: The flaskAzureImage variable is used to create an instance of the docker.Image
class. The context for the DockerBuild is set to app
, which specifies the path of the folder containing the Dockerfile that will be used to build the image.
The image_name
parameter is set dynamically to dockerHubUserName/imageName:imageTag
which specifies the name and tag of the image that will be pushed to the Docker registry. The ImageRegistry server is set to docker.io with the corresponding login details.
resource_group = resources.ResourceGroup(
"pulumi_flask_app", location=azureResourceLocation
)
Creating a Resource Group: The resource_group
variable is used to create an instance of the resources.ResourceGroup
class. The name is set to pulumi_flask_app
and the location parameter is set to azureResourceLocation
which is defined earlier. It specifies the Azure region where the resource group will be created.
plan = web.AppServicePlan(
"pulumi",
resource_group_name=resource_group.name,
kind="Linux",
location=azureResourceLocation,
reserved=True,
sku=web.SkuDescriptionArgs(
name="F1",
tier="Free",
),
)
Creating an App Service Plan: The plan variable is used to create an instance of the web.AppServicePlan
class. I have selected a Linux-based Web App using the kind
and reserved
parameters. The sku
parameter is set to web.SkuDescriptionArgs(name="F1", tier="Free")
which specifies that the plan will use the "F1" (Free) tier. Change the tier as per your needs.
flask_alpine = web.WebApp(
"flask-azure-pulumi",
resource_group_name=resource_group.name,
server_farm_id=plan.id,
site_config=web.SiteConfigArgs(
app_settings=[
web.NameValuePairArgs(
name="WEBSITES_ENABLE_APP_SERVICE_STORAGE", value="false"
)
],
linux_fx_version=f"DOCKER|{dockerHubUserName}/{imageName}:{imageTag}",
),
https_only=True,
)
Creating a Web App: The flask_alpine variable
is used to create an instance of the web.WebApp
class. The server_farm_id
parameter is set to plan.id
which specifies the App Service Plan that the Web App will be associated with. The site_config
specifies the configuration of the Web App by providing it with the Docker Image link as specified in linux_fx_version
. The https_only
parameter is set to True
which enforces that the Web App can only be accessed via HTTPS.
There are more variables that you can adjust and fine tune as per your app requirements and I have just scratched the surface. So, feel free to refer to the docs while creating.
pulumi.export(
"websiteURL",
flask_alpine.default_host_name.apply(
lambda default_host_name: f"https://{default_host_name}"
),
)
Exporting the Website URL: The pulumi.export function is used to export the URL of the website. This exported value can be accessed later using the pulumi stack output
command.
Complete code
You can check out my Github Repo for the complete merged code.
Overall, this code uses the Pulumi library to automate the deployment of the infrastructure, using Azure and Docker. The script creates a resource group, an App Service Plan, a Web App and pushes the Docker image to the Docker registry. The script also exports the website URL which can be accessed later. The URL for the app that I have created is flask-azure-pulumic4668d36.azurewebsites.net
Conclusion
In this blog post, we have discussed how to use Pulumi to deploy a simple Dockerized application on Azure. We have explained the benefits of using IaC and how Pulumi simplifies the deployment process. By using Pulumi, we can define our infrastructure as code, automate the deployment process, and version control the changes. Additionally, by using Azure App Service and Web App, we can easily host and scale our application in a secure and reliable environment. Pulumi is a powerful tool that enables developers to manage their infrastructure in a programmatic and automated way, saving time and effort while improving consistency and reproducibility.
I hope this tutorial was helpful in showing you how to use Pulumi in setting up Infrastructure effortlessly. Let me know if you have any questions or suggestions for improvement.
In case if you still have any questions regarding this post or want to discuss something with me feel free to connect on LinkedIn or Twitter.
If you run an organization and want me to write for you, please connect with me on my Socials 🙃
Top comments (0)