From CLI to Cloud: Building a Simple WordPress Lab on Azure with Container Instances and MySQL
From CLI to Cloud: Building a Simple WordPress Lab on Azure with Container Instances and MySQL
One of the best ways to learn Azure is to build something small, practical, and a little bit messy on purpose. That is exactly what this lab does.
In this walkthrough, I used the Azure CLI to create a simple WordPress environment using:
- Azure Resource Group
- Azure Virtual Network (VNet)
- Multiple subnets
- Azure Database for MySQL Flexible Server
- Azure Container Instances (ACI)
- A Windows jumpbox VM
- A Network Security Group (NSG)
The goal was not to create the perfect production-grade WordPress platform. The goal was to understand the building blocks of Azure cloud fundamentals by actually deploying something end to end.
This article explains the journey in tutorial style, breaking down each command, what Azure service it touches, and why that service matters.
Why this lab is useful for learning Azure fundamentals
If you are a student or someone early in cloud learning, this kind of lab is great because it introduces several core Azure concepts at once:
- Resource organization with Resource Groups
- Network segmentation with VNets and subnets
- Platform services like Azure Database for MySQL
- Containers with Azure Container Instances
- Compute with Azure Virtual Machines
- Access control and filtering with NSGs
You are not just deploying WordPress. You are learning how cloud services connect together.
The architecture at a high level
The setup looks like this:
- A Resource Group named
GGHomeLabcontains everything - A Virtual Network named
wp-vnetprovides private IP space - Separate subnets are created for:
- the WordPress container
- the MySQL database
- a future Application Gateway
- a Windows VM jumpbox
- A MySQL Flexible Server hosts the WordPress database
- A WordPress container runs inside Azure Container Instances
- A Windows Server VM acts as a jumpbox for administration
- An NSG allows RDP access to the jumpbox
This is already enough to teach several important lessons: separation of concerns, service boundaries, and how Azure resources depend on each other.
Step 1: Defining variables
# Variables
RESOURCE_GROUP="GGHomeLab"
LOCATION="australiaeast"
VNET_NAME="wp-vnet"
ACI_SUBNET="aci-subnet"
DB_SUBNET="db-subnet"
APPGW_SUBNET="appgw-subnet"
Before creating resources, variables are defined in the shell.
This is not an Azure service by itself, but it is a very important automation habit. Instead of typing the same values again and again, variables make scripts:
- easier to read
- easier to reuse
- less error-prone
For example, if you want to deploy the same lab in another region later, you can just change:
LOCATION="australiasoutheast"
and reuse the rest of the script.
Azure concept introduced: Region
australiaeast is the Azure region where resources will be deployed. Azure regions are geographic locations containing Microsoft datacenters.
Choosing a region affects:
- latency
- available services
- pricing
- compliance requirements
In a lab, the main idea is simply to pick a region close to you or one that supports the services you want.
Step 2: Creating a Resource Group
az group create --name $RESOURCE_GROUP --location $LOCATION
What this command does
This creates an Azure Resource Group named GGHomeLab in australiaeast.
What is a Resource Group?
A Resource Group is a logical container for Azure resources. It helps you organize related components of a solution.
In this case, the Resource Group will contain:
- network resources
- the MySQL server
- the WordPress container
- the virtual machine
- security resources
Why it matters
Resource Groups are one of the first Azure fundamentals students should understand. They make it easier to:
- manage a project as one unit
- apply permissions
- track costs
- delete everything together when the lab is finished
For a home lab, this is especially useful because cleanup becomes simple.
Step 3: Creating a Virtual Network and first subnet
az network vnet create \
--resource-group $RESOURCE_GROUP \
--name $VNET_NAME \
--address-prefix 10.0.0.0/16 \
--subnet-name $ACI_SUBNET \
--subnet-prefix 10.0.1.0/24
What this command does
This creates:
- a Virtual Network called
wp-vnet - an address space of
10.0.0.0/16 - an initial subnet called
aci-subnet - a subnet range of
10.0.1.0/24
What is a Virtual Network?
An Azure VNet is your private network in the cloud. It is similar to defining a private network in an on-premises environment.
It allows Azure resources to communicate privately with each other.
What is a subnet?
A subnet is a smaller network carved out of the VNet. Subnets help separate workloads.
In this lab, the first subnet is for the Azure Container Instance that will run WordPress.
Why this matters for students
This teaches one of the biggest cloud fundamentals: network isolation.
Instead of putting everything in one flat network, we divide the environment into pieces. This improves:
- organization
- security
- traffic control
- future scalability
Step 4: Adding a database subnet
az network vnet subnet create \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name $DB_SUBNET \
--address-prefix 10.0.2.0/24
What this command does
This adds a second subnet named db-subnet to the VNet.
Why create a separate database subnet?
Databases should usually be separated from application workloads. In this lab:
- WordPress runs in one subnet
- MySQL runs in another subnet
This is a good design habit because it allows tighter control over who can access the database.
Azure concept introduced: workload segmentation
Azure networking encourages you to separate tiers of an application:
- web tier
- app tier
- data tier
Even in a simple WordPress deployment, that pattern starts to appear.
Step 5: Adding a subnet for Application Gateway
az network vnet subnet create \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name $APPGW_SUBNET \
--address-prefixes 10.0.3.0/24
What this command does
This creates another subnet called appgw-subnet.
Why is this interesting?
Even though the script does not yet deploy an Application Gateway, the subnet is being reserved for one.
That is a nice lesson in planning ahead. Some Azure services, such as Azure Application Gateway, are commonly deployed in dedicated subnets.
What is Azure Application Gateway?
Application Gateway is a Layer 7 load balancer for web applications. It can provide:
- HTTP and HTTPS routing
- SSL termination
- cookie-based session affinity
- Web Application Firewall features
In this lab, the subnet is a placeholder showing how infrastructure can be designed for future expansion.
Step 6: Defining MySQL variables
MYSQL_NAME="wp-mysql-flex"
MYSQL_ADMIN="mysqladmin"
MYSQL_PASS="YourStrong&Password1"
SKU="Standard_B1ms" # Burstable for dev/test
MYSQL_DB="wordpressdb"
These variables define configuration for the Azure MySQL server.
What each variable means
MYSQL_NAME: name of the MySQL serverMYSQL_ADMIN: admin usernameMYSQL_PASS: admin passwordSKU: server size and performance levelMYSQL_DB: database name for WordPress
Azure concept introduced: SKU
Azure services often require a SKU, which defines the pricing and performance tier.
Standard_B1ms is a small burstable option, which is suitable for a lab or lightweight testing.
For students, this is a good reminder that cloud design is not just technical. It also includes cost choices.
Step 7: Creating Azure Database for MySQL Flexible Server
az mysql flexible-server create \
--name $MYSQL_NAME \
--resource-group $RESOURCE_GROUP \
--location $LOCATION \
--admin-user $MYSQL_ADMIN \
--admin-password $MYSQL_PASS \
--sku-name $SKU \
--tier Burstable \
--vnet $VNET_NAME \
--subnet $DB_SUBNET \
--yes
What this command does
This creates an Azure Database for MySQL Flexible Server named wp-mysql-flex and places it into the VNet using the db-subnet.
What is Azure Database for MySQL Flexible Server?
This is a managed database service. Instead of installing MySQL yourself on a VM, Azure runs and maintains the database platform for you.
Microsoft handles much of the underlying operational work such as:
- service management
- patching platform components
- high availability options
- backups
- maintenance features
Why use it here?
WordPress needs a MySQL-compatible database. Rather than running MySQL manually in another VM or container, a managed service keeps the database layer simpler and more cloud-native.
Important parameters explained
--name: server name--resource-group: where the server lives--location: deployment region--admin-userand--admin-password: credentials--sku-name: compute size--tier Burstable: cost-effective option for dev/test--vnetand--subnet: integrate the server into the private network--yes: skip prompts
Azure concept introduced: managed service
This is a major cloud principle. Instead of managing everything yourself, you consume managed services that reduce operational burden.
For beginners, this helps answer a common question:
Why cloud, instead of just VMs everywhere?
Because managed services let you focus more on the application and less on infrastructure maintenance.
Step 8: Creating the WordPress database
az mysql flexible-server db create \
--resource-group $RESOURCE_GROUP \
--server-name $MYSQL_NAME \
--database-name $MYSQL_DB
What this command does
This creates a database called wordpressdb inside the MySQL Flexible Server.
Why do we need it?
The MySQL server is the database platform, but WordPress needs an actual database schema location to store:
- posts
- users
- settings
- themes and plugin metadata
This step prepares that database container for the application.
Azure concept introduced: server vs database
Students often confuse these two ideas:
- server = the MySQL service instance
- database = the actual logical database inside that server
This command shows that both layers exist.
Step 9: Defining container variables
ACI_NAME="wp-container"
IMAGE="wordpress:latest"
MYSQL_HOST="wp-mysql-flex.mysql.database.azure.com"
These variables prepare the container deployment.
What they mean
ACI_NAME: the name of the container groupIMAGE: the Docker image to runMYSQL_HOST: the MySQL server FQDN
Azure concept introduced: container image
wordpress:latest is a public container image, typically pulled from Docker Hub.
A container image packages the application and its dependencies. Instead of installing WordPress manually on a server, the image already contains the software needed to run it.
This is one reason containers are so popular in modern cloud environments.
Step 10: Creating the WordPress container in Azure Container Instances
az container create \
--resource-group $RESOURCE_GROUP \
--name $ACI_NAME \
--os-type="Linux" \
--image $IMAGE \
--vnet $VNET_NAME \
--subnet $ACI_SUBNET \
--ports 80 \
--cpu 1 \
--memory 1.5 \
--environment-variables \
WORDPRESS_DB_HOST=$MYSQL_HOST \
WORDPRESS_DB_NAME=$MYSQL_DB \
WORDPRESS_DB_USER=$MYSQL_ADMIN \
WORDPRESS_DB_PASSWORD=$MYSQL_PASS \
--restart-policy Always
What this command does
This deploys a Linux container running WordPress into Azure Container Instances and connects it to the VNet subnet created earlier.
What is Azure Container Instances?
ACI is a service for running containers without managing servers or orchestrators.
It is useful when you want to run a container quickly without:
- building a Kubernetes cluster
- managing a VM host
- dealing with complex orchestration
Why ACI is good for a learning lab
For students, ACI is a nice middle ground:
- more modern than deploying everything on a VM
- simpler than learning AKS on day one
- fast to provision
- suitable for experiments and small workloads
Key parameters explained
--os-type="Linux": the container runs on Linux--image $IMAGE: use the WordPress container image--vnetand--subnet: attach the container to the private network--ports 80: expose HTTP--cpu 1: allocate 1 vCPU--memory 1.5: allocate 1.5 GB RAM--environment-variables: pass database settings to WordPress--restart-policy Always: restart the container if it stops
Why the environment variables matter
WordPress needs to know how to reach its database. These values tell it:
- where the database server is
- which database to use
- what username and password to connect with
This is how the application tier gets connected to the data tier.
A practical note
In a real design, storing passwords directly in the CLI command is not ideal. It works for a lab, but production would use a secrets solution such as Azure Key Vault.
Step 11: Defining variables for the jumpbox VM
ADMIN_USER="azureuser"
ADMIN_PASS="YourStrong&Password123" # Must meet complexity rules
IMAGE="Win2022Datacenter" # Use latest Windows Server
VM_NAME="wp-jumpbox"
VM_SUBNET="vm-subnet"
These variables prepare a Windows virtual machine deployment.
What is a jumpbox?
A jumpbox, sometimes called a bastion host, is an administrative VM used to access resources in a private network.
In this lab, the jumpbox can be used to:
- log in remotely
- test connectivity
- administer resources from inside the network
Azure concept introduced: Infrastructure as a Service
Unlike ACI or MySQL Flexible Server, a VM is more traditional IaaS. You get an operating system to manage yourself.
This is useful for learning because it contrasts nicely with managed services.
Step 12: Looking up a subnet ID
# Get subnet ID
SUBNET_ID=$(az network vnet subnet show \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name $ACI_SUBNET \
--query id -o tsv)
What this command does
This retrieves the Azure resource ID of the aci-subnet and stores it in a shell variable called SUBNET_ID.
Why this is useful
Many Azure commands can work with either:
- names
- full resource IDs
A resource ID is the full unique path of an Azure resource.
Even though this variable is not used later in the script, it is still a useful example because students often encounter resource IDs in automation, ARM templates, Bicep, Terraform, and CLI scripting.
Azure concept introduced: resource ID
Azure resources have unique IDs that describe where they live in the subscription hierarchy.
These IDs become very important in larger automation workflows.
Step 13: Creating a subnet for the virtual machine
az network vnet subnet create \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name $VM_SUBNET \
--address-prefix 10.0.4.0/24
What this command does
This adds another subnet named vm-subnet for the jumpbox VM.
Why separate the VM?
Again, this is about segmentation and good design habits.
Having a dedicated subnet for admin systems makes it easier later to:
- apply NSGs
- control access rules
- monitor admin traffic separately
Even in a small lab, practicing separation helps build production thinking.
Step 14: Creating a Network Interface Card for the VM
az network nic create \
--resource-group $RESOURCE_GROUP \
--name ${VM_NAME}-nic \
--vnet-name $VNET_NAME \
--subnet $VM_SUBNET
What this command does
This creates a Network Interface Card (NIC) for the VM in the vm-subnet.
What is a NIC in Azure?
Just like a physical or virtual network adapter in traditional environments, an Azure NIC connects a VM to a network.
It can hold:
- private IP settings
- public IP association
- NSG association
- IP forwarding settings
Why create it separately?
Creating the NIC separately gives you more control. You can attach security settings and manage networking independently from the VM creation process.
This is a valuable lesson because cloud resources are often modular.
Step 15: Creating the Windows virtual machine
az vm create \
--resource-group $RESOURCE_GROUP \
--name $VM_NAME \
--image $IMAGE \
--admin-username $ADMIN_USER \
--admin-password $ADMIN_PASS \
--nics ${VM_NAME}-nic \
--size "Standard_D2as_v5"
What this command does
This creates a Windows Server 2022 VM named wp-jumpbox using the NIC created earlier.
Azure service involved
This uses Azure Virtual Machines, one of the core compute services in Azure.
Key parameters explained
--image $IMAGE: deploy Windows Server 2022 Datacenter--admin-usernameand--admin-password: local VM credentials--nics: attach the pre-created NIC--size "Standard_D2as_v5": VM size and performance characteristics
Why this matters in cloud fundamentals
Students should understand that Azure offers different compute models:
- VMs for full control
- Containers for lightweight packaged apps
- Managed PaaS services for reduced operational overhead
This lab includes all three styles in one solution, which makes it a great teaching exercise.
Step 16: Creating a Network Security Group
NSG_NAME="wp-jumpbox-nsg"
RULE_NAME="Allow-RDP"
SOURCE_PORT_PREFIX="0.0.0.0/0"
# Create NSG
az network nsg create \
--resource-group $RESOURCE_GROUP \
--name $NSG_NAME
What this command does
This creates a Network Security Group called wp-jumpbox-nsg.
What is an NSG?
An NSG is a packet filtering firewall for Azure network traffic. It can be associated with:
- a subnet
- a NIC
NSGs contain rules that allow or deny inbound and outbound traffic.
Why it matters
Security groups are a core Azure networking concept. They let you control who can talk to what.
In this case, the NSG will be used to allow Remote Desktop access to the jumpbox VM.
Step 17: Adding an inbound RDP rule
az network nsg rule create \
--resource-group $RESOURCE_GROUP \
--nsg-name $NSG_NAME \
--name $RULE_NAME \
--protocol Tcp \
--direction Inbound \
--priority 1000 \
--source-address-prefixes $SOURCE_PORT_PREFIX \
--source-port-ranges "*" \
--destination-address-prefixes "*" \
--destination-port-ranges 3389 \
--access Allow
What this command does
This adds an NSG rule that allows inbound TCP traffic on port 3389, which is the default port for RDP.
What each important parameter means
--protocol Tcp: RDP uses TCP--direction Inbound: this rule applies to incoming traffic--priority 1000: lower number means higher priority--source-address-prefixes: defines who can connect--destination-port-ranges 3389: target RDP port--access Allow: permit the traffic
Important learning point
The variable name SOURCE_PORT_PREFIX is a little misleading here because the value 0.0.0.0/0 is actually used as a source address range, not a source port. That CIDR means any IP address.
So effectively, this rule allows RDP from anywhere on the internet.
Security warning
This may be acceptable in a temporary lab, but it is not recommended for real environments.
Better choices would include:
- restricting RDP to your own public IP
- using Azure Bastion
- using Just-In-Time VM access
- avoiding direct exposure altogether
Small script note
There is also an extra space after the line continuation on:
--source-address-prefixes $SOURCE_PORT_PREFIX \
In a shell script, that stray space after the backslash can cause problems. It is better written as:
--source-address-prefixes $SOURCE_PORT_PREFIX \
This is a nice reminder that cloud automation depends not only on architecture knowledge, but also on careful scripting.
Step 18: Associating the NSG with the VM NIC
NIC_NAME="${VM_NAME}-nic"
az network nic update \
--resource-group $RESOURCE_GROUP \
--name $NIC_NAME \
--network-security-group $NSG_NAME
What this command does
This attaches the NSG to the VM's NIC.
Why this matters
Once attached, the NIC now follows the NSG rules, including the RDP allow rule.
This means the VM's network access is being controlled by the NSG.
Azure concept introduced: scope of security controls
NSGs can be attached at different levels:
- subnet level
- NIC level
In this script, the NSG is attached at the NIC level, which gives control over this specific VM.
What this lab teaches overall
By the end of this setup, a student is exposed to several major Azure concepts:
1. Resource organization
The Resource Group keeps all related resources together.
2. Cloud networking
The VNet and subnets model a private cloud network.
3. Segmentation
Different subnets are used for app, database, future gateway, and admin access.
4. Managed database services
Azure Database for MySQL Flexible Server reduces infrastructure management effort.
5. Container-based app hosting
Azure Container Instances runs WordPress without needing a full VM.
6. Traditional VM administration
The jumpbox VM shows the IaaS model and remote administration pattern.
7. Security controls
NSGs demonstrate basic network traffic filtering.
That is a lot of cloud fundamentals from one small WordPress project.
What could be improved even in a lab
This setup works as a learning exercise, but there are some things worth calling out:
- passwords are written directly in the script
- the WordPress image uses
latest, which is not ideal for repeatable deployments - RDP is open from anywhere
- no TLS or HTTPS is configured
- no persistent shared storage is configured for WordPress content
- no backup or disaster recovery story is defined for the application tier
- no monitoring or logging is configured in a serious way
These are not failures. They are actually useful discussion points for students because they show the difference between lab design and production design.
For a real production environment, what else would we add?
This lab is fine for a home lab, student exercise, or a very small proof of concept. But in a real production environment, we would usually incorporate more Azure services to improve security, availability, scalability, and operations.
Here are some of the most important ones and why they would matter in this scenario.
Azure Key Vault
We would use Azure Key Vault to store secrets such as:
- MySQL passwords
- admin credentials
- TLS certificates
- API keys
This avoids hardcoding sensitive values in scripts or environment variables.
Azure Application Gateway
We would use Azure Application Gateway in front of WordPress to provide:
- Layer 7 load balancing
- HTTPS termination
- smarter routing
- better control of web traffic
Since an appgw-subnet was already planned, this is a natural next step.
Web Application Firewall (WAF)
We would enable WAF, typically with Application Gateway, to protect the WordPress site from common web attacks such as:
- SQL injection attempts
- cross-site scripting
- malicious request patterns
WordPress is a common internet-facing target, so this becomes very important.
Azure Bastion
Instead of exposing RDP to the internet, we would use Azure Bastion for secure browser-based administration of the VM without opening port 3389 publicly.
This greatly reduces attack surface.
Azure Monitor and Log Analytics
We would use Azure Monitor and Log Analytics to collect:
- metrics
- logs
- alerts
- performance data
In production, visibility is essential. You need to know when the app is slow, when the database is stressed, or when login attempts look suspicious.
Azure Container Registry
Instead of pulling wordpress:latest from a public registry, we would often use Azure Container Registry (ACR) to store trusted, versioned images.
This provides:
- more control
- better supply chain hygiene
- version stability
- easier integration with CI/CD pipelines
Azure Files or Azure NetApp Files
WordPress often needs persistent storage for uploads and media. In production, we would use a persistent storage solution rather than relying on ephemeral container storage.
This helps preserve user content across restarts or redeployments.
Azure Backup
Although MySQL Flexible Server has backup capabilities, we would also think carefully about backup and recovery strategy for the full application.
Production systems need documented recovery plans, not just hope.
Azure Front Door
For public-facing global applications, Azure Front Door can provide:
- global entry point
- performance optimization
- SSL offload
- DDoS-aware edge routing
- failover across regions
This is especially useful if the site must be reachable quickly and reliably from multiple geographic locations.
DDoS Protection
For internet-facing workloads, Azure DDoS Protection may be added to strengthen resilience against denial-of-service attacks.
Azure Policy
We would use Azure Policy to enforce governance rules, such as:
- only approved regions
- required tags
- encrypted resources
- disallowing public IPs on sensitive workloads
This helps keep environments consistent and compliant.
Microsoft Defender for Cloud
We would use Microsoft Defender for Cloud to improve security posture, detect weak configurations, and provide recommendations across the environment.
Availability and scale services
If this became a serious application, we would likely rethink the hosting layer too.
Instead of ACI alone, we might move to:
- Azure Kubernetes Service (AKS) for orchestration
- Azure App Service for Containers for managed web hosting
- multiple instances behind a load balancer for high availability
ACI is simple and good for labs, but it is not usually the final answer for production-scale WordPress hosting.
Final thoughts
I like this lab because it tells a real cloud story.
It starts simply: create a resource group, define a network, deploy a database, run a container, add a jumpbox, and open remote access. But inside those steps are many of the most important Azure cloud fundamentals.
You learn that cloud is not just about creating a server. It is about thinking in layers:
- organization
- networking
- security
- compute
- managed services
- future scalability
And that is exactly why hands-on labs matter.
A small WordPress deployment may not look glamorous, but it is a great teaching platform. It exposes the difference between something that merely works and something that is designed well.
For a student, that is the real win.
Full command reference used in this lab
For convenience, here is the original flow in logical order:
# Variables
RESOURCE_GROUP="GGHomeLab"
LOCATION="australiaeast"
VNET_NAME="wp-vnet"
ACI_SUBNET="aci-subnet"
DB_SUBNET="db-subnet"
APPGW_SUBNET="appgw-subnet"
# Create resource group
az group create --name $RESOURCE_GROUP --location $LOCATION
# Create VNet with first subnet
az network vnet create \
--resource-group $RESOURCE_GROUP \
--name $VNET_NAME \
--address-prefix 10.0.0.0/16 \
--subnet-name $ACI_SUBNET \
--subnet-prefix 10.0.1.0/24
# Add DB subnet
az network vnet subnet create \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name $DB_SUBNET \
--address-prefix 10.0.2.0/24
# Add subnet reserved for Application Gateway
az network vnet subnet create \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name $APPGW_SUBNET \
--address-prefixes 10.0.3.0/24
MYSQL_NAME="wp-mysql-flex"
MYSQL_ADMIN="mysqladmin"
MYSQL_PASS="YourStrong&Password1"
SKU="Standard_B1ms"
MYSQL_DB="wordpressdb"
az mysql flexible-server create \
--name $MYSQL_NAME \
--resource-group $RESOURCE_GROUP \
--location $LOCATION \
--admin-user $MYSQL_ADMIN \
--admin-password $MYSQL_PASS \
--sku-name $SKU \
--tier Burstable \
--vnet $VNET_NAME \
--subnet $DB_SUBNET \
--yes
az mysql flexible-server db create \
--resource-group $RESOURCE_GROUP \
--server-name $MYSQL_NAME \
--database-name $MYSQL_DB
ACI_NAME="wp-container"
IMAGE="wordpress:latest"
MYSQL_HOST="wp-mysql-flex.mysql.database.azure.com"
az container create \
--resource-group $RESOURCE_GROUP \
--name $ACI_NAME \
--os-type="Linux" \
--image $IMAGE \
--vnet $VNET_NAME \
--subnet $ACI_SUBNET \
--ports 80 \
--cpu 1 \
--memory 1.5 \
--environment-variables \
WORDPRESS_DB_HOST=$MYSQL_HOST \
WORDPRESS_DB_NAME=$MYSQL_DB \
WORDPRESS_DB_USER=$MYSQL_ADMIN \
WORDPRESS_DB_PASSWORD=$MYSQL_PASS \
--restart-policy Always
ADMIN_USER="azureuser"
ADMIN_PASS="YourStrong&Password123"
IMAGE="Win2022Datacenter"
VM_NAME="wp-jumpbox"
VM_SUBNET="vm-subnet"
SUBNET_ID=$(az network vnet subnet show \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name $ACI_SUBNET \
--query id -o tsv)
az network vnet subnet create \
--resource-group $RESOURCE_GROUP \
--vnet-name $VNET_NAME \
--name $VM_SUBNET \
--address-prefix 10.0.4.0/24
az network nic create \
--resource-group $RESOURCE_GROUP \
--name ${VM_NAME}-nic \
--vnet-name $VNET_NAME \
--subnet $VM_SUBNET
az vm create \
--resource-group $RESOURCE_GROUP \
--name $VM_NAME \
--image $IMAGE \
--admin-username $ADMIN_USER \
--admin-password $ADMIN_PASS \
--nics ${VM_NAME}-nic \
--size "Standard_D2as_v5"
NSG_NAME="wp-jumpbox-nsg"
RULE_NAME="Allow-RDP"
SOURCE_PORT_PREFIX="0.0.0.0/0"
az network nsg create \
--resource-group $RESOURCE_GROUP \
--name $NSG_NAME
az network nsg rule create \
--resource-group $RESOURCE_GROUP \
--nsg-name $NSG_NAME \
--name $RULE_NAME \
--protocol Tcp \
--direction Inbound \
--priority 1000 \
--source-address-prefixes $SOURCE_PORT_PREFIX \
--source-port-ranges "*" \
--destination-address-prefixes "*" \
--destination-port-ranges 3389 \
--access Allow
NIC_NAME="${VM_NAME}-nic"
az network nic update \
--resource-group $RESOURCE_GROUP \
--name $NIC_NAME \
--network-security-group $NSG_NAME
Happy lab building.