Different DevOps approaches to deploying an app — and — How to Deploy an App using a Self-Hosted Agent in Azure

How can I run my first job on a self-hosted agent?

GABRIEL OKOM
9 min readJan 14, 2024

In this project; Firstly, I would like to explore the several ways to deploy an App. The aim for this, is targetted at beginners who are yet to understand the concepts behind deploying applications, such as deploying the app locally, dockerizing the app, quickly spin the app to the cloud for testing, and finally using CICD pipeline to deploy the app. This is because it is also important and beneficial to learn how to deploy apps locally before migrating to the cloud.

In the last section, in the CICD Pipeline process; we deployed the App using the Self-Hosted Agent configured earlier in the previous project. You can find the previous project here.

Step 1: Deploy the App locally

Deploying an app locally before deployment in the cloud is an essential step in the development process that can help to save time, reduce costs, improve performance, and ensure security and compliance.

a. Open the vscode: Open the “Terminal” by using the shortcut Ctrl + `.

b. Navigate to Your Project Directory: Use the cd command to navigate to your project directory. In my own case, I will be working on the ./Downloads directory.

cd ./Downloads

c. Clone the original project:

git clone https://github.com/Azure-Samples/msdocs-python-flask-webapp-quickstart.git

Optional: If you’d like to checkout my github repo too, this is it here > https://github.com/ougabriel/pipeline-hello1.git

d. Navigate to the git directory

cd msdocs-python-flask-webapp-quickstart.git

As seen in the code below. Here I changed the section app.run() to enable the app run on a specified port which is 5000. You can do same or leave it as default.

import os

from flask import (Flask, redirect, render_template, request,
send_from_directory, url_for)

app = Flask(__name__)


@app.route('/')
def index():
print('Request for index page received')
return render_template('index.html')

@app.route('/favicon.ico')
def favicon():
return send_from_directory(os.path.join(app.root_path , 'static'),
'favicon.ico', mimetype='image/vnd.microsoft.icon')

@app.route('/hello', methods=['POST'])
def hello():
name = request.form.get('name')

if name:
print('Request for hello page received with name=%s' % name)
return render_template('hello.html', name = name)
else:
print('Request for hello page received with no name or blank name -- redirecting')
return redirect(url_for('index'))


if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)

e. Create and Activate the Virtual Environment

python -m venv venv
.\venv\Scripts\Activate

f. Install the required dependencies using pip

pip install -r requirements.txt

g. Run the Flask application: This should start the development server, and you should see output indicating that the server is running.

python app.py

h. Access the App: Open a web browser and go to http://127.0.0.1:5000/ or http://localhost:5000/ to view the running application.

That’s it! You’ve cloned and deployed an app

Step 2: Deploy the App using Azure CLI

In this section, we are going to test its deployment to Azure App Service using a single line command.

Install the AZ CLI tool

a. Install the Azure CLI Tools in your vscode as shown above.

b. Login to Azure, a pop window will open. Input your login credentials to allow access to your azure portal.

az login

c. Run the command below

az webapp up --name gab-py-webapp --sku B1 --resource-group gab-rg1 --runtime "PYTHON|3.9" --logs

The command may take a few minutes to complete. While the command is running, it provides messages about creating the resource group, the App Service plan, and the app resource, configuring logging, and doing ZIP deployment. It then gives the message, “You can launch the app at http://gab-py-webapp.azurewebsites.net”, which is the app’s URL on Azure.

d. Browse the deployed application in your web browser at the URL http://gab-py-webapp.azurewebsites.net. From the image below; You can also access the app in your Azure Portal > App Service > gab-py-webapp

Thats it !! You have successfully deployed an App to Azure App Service with just a single line of code.

Step 3: Dockerize and deploy the App locally

Docker provides a consistent environment, making it easy to share and deploy applications across different environments (both local and the cloud)

We already cloned the App in the previous deployment, In this section we will need to add an additional file which will enable us build the docker image needed for this app to function. The name of the file is Dockerfile

a. Add a Dockerfile: Copy and paste the following script into it.

# Use an official Python runtime as a base image
FROM python:3.9

# Set the working directory inside the container
WORKDIR /app

# Copy the current directory contents into the container at /app
COPY . /app

# Install any needed packages specified in requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Make port 80 available to the world outside this container
EXPOSE 80

# Define environment variable
ENV NAME World

# Run app.py when the container launches
CMD ["python", "app.py"]

This Dockerfile sets up a Python environment, copies the application files into the container, installs dependencies, exposes port 80, sets an environment variable, and runs app.py.

b. Build the Docker Image: Open a terminal in the same directory as your Dockerfile and run the following command to build the Docker image. Replace gab-app with a name for your Docker image:

docker build -t gab-app .

c. Run the Docker Container: After the image is built, run the following command to start a Docker container:

docker run -d -p 80:5000 gab-app

This maps port 80 from your local machine to port 5000 in the container.

d. Access the Deployed App: Open a web browser and go to http://127.0.0.1:80/ or http://localhost:80/ to view your Flask app running inside the Docker container.

That’s it! You’ve Dockerized and deployed your Flask app locally.

Step 4: Deploy the App using Azure Devops CICD Pipeline

Here the steps needed to deploy to the app in azure using azure app service and azure devops. In more simple terms; Push the app to github > create ACR > Retrieve the App and push it to ACR as an image > Create a Webapp to browse it > Create a CICD Pipeline Release for the App

a. Push the App to GitHub : From the project folder run the following to initialize git > add the folder files > commit the files > add your github url > push to github

b. Create ACR (Azure Container Registry)

The name of my Azure Container Registry is hello0acr you can use same name or any other name thats convenient for you.

Before you can build the pipeline image, we must first create the ACR (the ACR has a repository, this is where the image is stored).

Creating an ACR is simple, it has been created in the Step 1 of a previous project and you can find it HERE.

Make sure the Access keys for Admin User is checked as shown below;

c. Retrieve the App from github and push the Pipeline Image to ACR

NOTE: I used the self-hosted agent for the build process as mentioned earlier.

If you’d like to know how to create a self-hosted agent, click HERE.

How to use the self-hosted agent?

Using the Self-Hosted Agent is very simple, this is done by specyfing the name of the agent in the pipeline script or by simply changing the default agent to the name of your self-hosted agent, in my case the name of my self-hosted agent is Ubuntu-Agent-Pool

a. From the left menu, click pipeline , in the open page you have to click Create pipeline

b. CONNECT, the GitHub repo. Click on GitHub (yaml) from the list

c. SELECT, the repo from the list. In my case I selected the repo ougabriel/pipeline-hello1 .

d. CONFIGURE, select from the list with the details Docker (Build and push image to azure container registry)

> Select your subscription, click Continue

> From the drop-down menu, select your container registry which was created earlier. | The image name will be automatically populated or you can give it your own name. | Leave Dockerfile section as default

> Click Validate and configure ( the yaml file will be configured)

e. REVIEW, leave the azure-pipelines.yml file as default. We won’t be changing anything here. Click Save and run

NOTE: After the build, go to the azure portal > open the ACR created earlier > Scroll down to repositories to see the new docker image.

Go to your GitHub repo page to see the azure-pipelines.yml file which has been added.

b. Create an Azure WebApp

Since, we have already deployed our docker image. Next, we will attached this image to an Azure WebApp. When this is attached, the image is deployed into it and then we can browse the python app

a. Navigate to App Services:

  • In the Azure portal, click on Create a resource, and choose “Web App.”

b. Configure Web App Basics:

In the “Basics” tab of the Web App creation wizard:

Choose a unique App name. > Select your subscription. > Create or select a Resource Group. > Choose an Operating System (Linux). > Choose a Region. > Select a Runtime Stack (e.g., Node.js, Python, .NET Core). > Choose the Docker Containeroption under Publish.

c. Configure Container:

  • In the “Container” section of the wizard > Choose Single container >Provide the Image Source (choose the ACR where your image is located).

d. Configure App Service Plan:

In the “App Service Plan” section:

  • Create a new App Service Plan or select an existing one. > Choose the SKU (size) of the plan based on your requirements.

e. Configure Monitoring and Management: (Leave as default)

f. Review your configurations, and click on the “Review + create” button.

Go to configuration > Add New Application setting by clicking the plus sign as shown in the images below

c. Deploying the App using CICD release

a. From the menu Click “Pipelines” section and select “Releases” from the sub-menu.

b. Create a New Release Pipeline >

c. In the pop window. We can either choose empty job but for the sake of this project, select Azure App Service deployment (we already created the webapp for this purpose)

d. Add Artifacts: Link the artifacts produced by build pipeline which we did earlier to the release pipeline. Click on “Add an artifact” and select the source type.

Enable Continuous deployment trigger

  • Click on the thunderbolt and enable Continuous deployment trigger (this will ensure any changes made on the code will automatically be triggered)

e. Add Stage configuration.

Click on the 1job 1task as shown in the image above. > Select your subscription > for app type select WebApp for Containers (Linux) > for app service name select the name of your WebApp which was created earlier. > for registry name copy and paste the url of your ACR. > for the repo go back to the azure portal on the left menu, select the repo and paste the name on the given field

f. Click Save and then click Create release > Once the deployment is done, you can view the logs. and other details as shown above.

Weldone !! You have successfully deployed an APP in four different ways.

#docker #selfhosted #container #python #cicd #GabrielOkom #kubernetes #dockerimage #appservice #webapp #devops #devopsprojects #azure #azuredevops

--

--

GABRIEL OKOM

MSc Cyber Security and Computer Forensics | Certified DevOps Engineer