<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Droid Ek</title>
    <description>The latest articles on DEV Community by Droid Ek (@sudlo2014).</description>
    <link>https://dev.to/sudlo2014</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3599667%2Fac6dff5e-6aec-4583-b1a8-fd64bb4c0e13.jpg</url>
      <title>DEV Community: Droid Ek</title>
      <link>https://dev.to/sudlo2014</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sudlo2014"/>
    <language>en</language>
    <item>
      <title>Configure AntiGravity</title>
      <dc:creator>Droid Ek</dc:creator>
      <pubDate>Mon, 30 Mar 2026 22:38:57 +0000</pubDate>
      <link>https://dev.to/sudlo2014/configure-antigravity-1pa</link>
      <guid>https://dev.to/sudlo2014/configure-antigravity-1pa</guid>
      <description>&lt;p&gt;Note: I am not very good in writing so i did take help from chatgpt. &lt;/p&gt;

</description>
      <category>ai</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Docker Labs: From Beginner to Advanced on Azure</title>
      <dc:creator>Droid Ek</dc:creator>
      <pubDate>Thu, 06 Nov 2025 19:09:55 +0000</pubDate>
      <link>https://dev.to/sudlo2014/docker-labs-from-beginner-to-advanced-on-azure-54om</link>
      <guid>https://dev.to/sudlo2014/docker-labs-from-beginner-to-advanced-on-azure-54om</guid>
      <description>&lt;p&gt;Docker Labs: From Beginner to Advanced on Azure&lt;br&gt;
Note: Thanks for reading, here in this segment i will be talking about docker labs some of this is my own thoughts. I revising what i have learned most of you guys can join me&lt;/p&gt;

&lt;p&gt;Lab 1: Initial Azure Setup and Docker Installation&lt;/p&gt;

&lt;p&gt;Step 1: Create Azure VM with Docker&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create resource group&lt;/span&gt;
az group create &lt;span class="nt"&gt;--name&lt;/span&gt; DockerLabs &lt;span class="nt"&gt;--location&lt;/span&gt; eastus

&lt;span class="c"&gt;# Create Ubuntu VM with Docker&lt;/span&gt;
az vm create &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--resource-group&lt;/span&gt; DockerLabs &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; DockerVM &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; Ubuntu2204 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--admin-username&lt;/span&gt; azureuser &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--generate-ssh-keys&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--size&lt;/span&gt; Standard_B2s &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--custom-data&lt;/span&gt; cloud-init-docker.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;cloud-init-docker.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;#cloud-config&lt;/span&gt;
&lt;span class="na"&gt;package_upgrade&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apt-transport-https&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ca-certificates&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gnupg&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;lsb-release&lt;/span&gt;
&lt;span class="na"&gt;runcmd&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apt-get update&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;apt-get install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;usermod -aG docker azureuser&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;systemctl enable docker&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Connect and Verify&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# SSH to your VM&lt;/span&gt;
ssh azureuser@&amp;lt;your-vm-ip&amp;gt;

&lt;span class="c"&gt;# Verify Docker installation&lt;/span&gt;
docker &lt;span class="nt"&gt;--version&lt;/span&gt;
docker-compose &lt;span class="nt"&gt;--version&lt;/span&gt;
docker system info

&lt;span class="c"&gt;# Test with hello-world&lt;/span&gt;
docker run hello-world
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lab 2: Basic Docker Operations&lt;/p&gt;

&lt;p&gt;Step 1: Container Lifecycle Management&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Pull an image&lt;/span&gt;
docker pull nginx:alpine

&lt;span class="c"&gt;# Run a container&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; web-server &lt;span class="nt"&gt;-p&lt;/span&gt; 80:80 nginx:alpine

&lt;span class="c"&gt;# Check running containers&lt;/span&gt;
docker ps

&lt;span class="c"&gt;# View container logs&lt;/span&gt;
docker logs web-server

&lt;span class="c"&gt;# Execute commands in running container&lt;/span&gt;
docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; web-server sh

&lt;span class="c"&gt;# Stop and remove container&lt;/span&gt;
docker stop web-server
docker &lt;span class="nb"&gt;rm &lt;/span&gt;web-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Container Networking Basics&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a custom network&lt;/span&gt;
docker network create my-network

&lt;span class="c"&gt;# Run containers on the same network&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; web1 &lt;span class="nt"&gt;--network&lt;/span&gt; my-network nginx:alpine
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; web2 &lt;span class="nt"&gt;--network&lt;/span&gt; my-network nginx:alpine

&lt;span class="c"&gt;# Test connectivity between containers&lt;/span&gt;
docker &lt;span class="nb"&gt;exec &lt;/span&gt;web1 ping web2

&lt;span class="c"&gt;# Inspect network&lt;/span&gt;
docker network inspect my-network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lab 3: Building Custom Images&lt;/p&gt;

&lt;p&gt;Step 1: Create a Simple Web Application&lt;br&gt;
Create project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;my-webapp &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;my-webapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;app.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    &amp;lt;html&amp;gt;
        &amp;lt;body&amp;gt;
            &amp;lt;h1&amp;gt;Hello from Docker!&amp;lt;/h1&amp;gt;
            &amp;lt;p&amp;gt;Hostname: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;HOSTNAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Unknown&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/p&amp;gt;
            &amp;lt;p&amp;gt;Visit count: &amp;lt;!-- will be implemented later --&amp;gt;&amp;lt;/p&amp;gt;
        &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;requirements.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Flask==2.3.3
Redis==4.6.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Create Dockerfile&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Use official Python runtime&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.9-slim&lt;/span&gt;

&lt;span class="c"&gt;# Set working directory&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Copy requirements and install dependencies&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--no-cache-dir&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Copy application code&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Expose port&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 5000&lt;/span&gt;

&lt;span class="c"&gt;# Set environment variables&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; FLASK_ENV=production&lt;/span&gt;

&lt;span class="c"&gt;# Run the application&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3: Build and Run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build the image&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; my-webapp &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Run the container&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; my-app &lt;span class="nt"&gt;-p&lt;/span&gt; 5000:5000 my-webapp

&lt;span class="c"&gt;# Test the application&lt;/span&gt;
curl http://localhost:5000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lab 4: Docker Compose - Multi-Container Application&lt;/p&gt;

&lt;p&gt;Step 1: Create Redis Counter Application&lt;br&gt;
Update &lt;code&gt;app.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;flask&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Flask&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Flask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;redis_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;redis&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decode_responses&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;redis_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;incr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;visit_count&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    &amp;lt;html&amp;gt;
        &amp;lt;body&amp;gt;
            &amp;lt;h1&amp;gt;Hello from Docker Compose!&amp;lt;/h1&amp;gt;
            &amp;lt;p&amp;gt;Hostname: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;HOSTNAME&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Unknown&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/p&amp;gt;
            &amp;lt;p&amp;gt;Visit count: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;/p&amp;gt;
        &amp;lt;/body&amp;gt;
    &amp;lt;/html&amp;gt;
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.0.0.0&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Create docker-compose.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5000:5000"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;FLASK_ENV=production&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis:7-alpine&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis-data:/data&lt;/span&gt;

  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:alpine&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx.conf:/etc/nginx/nginx.conf&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;web&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app-network&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;redis-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3: Create Nginx Configuration&lt;br&gt;
Create &lt;code&gt;nginx.conf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;events&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;worker_connections&lt;/span&gt; &lt;span class="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;http&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;webapp&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="nf"&gt;web&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://webapp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 4: Deploy with Compose&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Start all services&lt;/span&gt;
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt;

&lt;span class="c"&gt;# Check status&lt;/span&gt;
docker compose ps

&lt;span class="c"&gt;# View logs&lt;/span&gt;
docker compose logs &lt;span class="nt"&gt;-f&lt;/span&gt;

&lt;span class="c"&gt;# Scale web service&lt;/span&gt;
docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--scale&lt;/span&gt; &lt;span class="nv"&gt;web&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lab 5: Data Management and Volumes&lt;/p&gt;

&lt;p&gt;Step 1: Persistent Data with Volumes&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create named volume&lt;/span&gt;
docker volume create app-data

&lt;span class="c"&gt;# Run container with volume&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; app-data:/var/lib/mysql &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret &lt;span class="se"&gt;\&lt;/span&gt;
  mysql:8.0

&lt;span class="c"&gt;# Inspect volume&lt;/span&gt;
docker volume inspect app-data

&lt;span class="c"&gt;# Backup volume&lt;/span&gt;
docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; app-data:/source &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/backup &lt;span class="se"&gt;\&lt;/span&gt;
  alpine &lt;span class="nb"&gt;tar &lt;/span&gt;czf /backup/backup.tar.gz &lt;span class="nt"&gt;-C&lt;/span&gt; /source &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Bind Mounts for Development&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Development with bind mount&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; dev-app &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 5001:5000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/app &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-w&lt;/span&gt; /app &lt;span class="se"&gt;\&lt;/span&gt;
  python:3.9-slim &lt;span class="se"&gt;\&lt;/span&gt;
  sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"pip install -r requirements.txt &amp;amp;&amp;amp; python app.py"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lab 6: Advanced Dockerfile Techniques&lt;/p&gt;

&lt;p&gt;Step 1: Multi-Stage Build&lt;br&gt;
Create advanced &lt;code&gt;Dockerfile.advanced&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;python:3.9-slim&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /build&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; requirements.txt .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt

&lt;span class="c"&gt;# Runtime stage&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.9-slim&lt;/span&gt;

&lt;span class="c"&gt;# Install security updates&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    apt-get upgrade &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="c"&gt;# Create non-root user&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;groupadd &lt;span class="nt"&gt;-r&lt;/span&gt; appuser &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; useradd &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; appuser appuser

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;

&lt;span class="c"&gt;# Copy installed packages from builder&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /root/.local /home/appuser/.local&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --chown=appuser:appuser . .&lt;/span&gt;

&lt;span class="c"&gt;# Switch to non-root user&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; appuser&lt;/span&gt;

&lt;span class="c"&gt;# Add user's local bin to PATH&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; PATH=/home/appuser/.local/bin:$PATH&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 5000&lt;/span&gt;

&lt;span class="k"&gt;HEALTHCHECK&lt;/span&gt;&lt;span class="s"&gt; --interval=30s --timeout=3s \&lt;/span&gt;
  CMD curl -f http://localhost:5000/ || exit 1

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["python", "app.py"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Build and Test Advanced Image&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Build with advanced Dockerfile&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; my-webapp:secure &lt;span class="nt"&gt;-f&lt;/span&gt; Dockerfile.advanced &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Run with security context&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; secure-app &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 5002:5000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--read-only&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--tmpfs&lt;/span&gt; /tmp &lt;span class="se"&gt;\&lt;/span&gt;
  my-webapp:secure

&lt;span class="c"&gt;# Check health status&lt;/span&gt;
docker inspect &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{{.State.Health.Status}}'&lt;/span&gt; secure-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lab 7: Container Orchestration with Docker Swarm&lt;/p&gt;

&lt;p&gt;Step 1: Initialize Swarm Mode&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize swarm (on manager node)&lt;/span&gt;
docker swarm init

&lt;span class="c"&gt;# Create overlay network&lt;/span&gt;
docker network create &lt;span class="nt"&gt;-d&lt;/span&gt; overlay app-overlay

&lt;span class="c"&gt;# Deploy stack&lt;/span&gt;
docker stack deploy &lt;span class="nt"&gt;-c&lt;/span&gt; docker-compose.swarm.yml myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Create Swarm Compose File&lt;br&gt;
Create &lt;code&gt;docker-compose.swarm.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-webapp:secure&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5000:5000"&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
      &lt;span class="na"&gt;update_config&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;parallelism&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
        &lt;span class="na"&gt;delay&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
      &lt;span class="na"&gt;restart_policy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;on-failure&lt;/span&gt;
      &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;limits&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;256M&lt;/span&gt;
        &lt;span class="na"&gt;reservations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;memory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;128M&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-overlay&lt;/span&gt;

  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis:7-alpine&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="na"&gt;placement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;constraints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node.role == manager&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis-data:/data&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-overlay&lt;/span&gt;

  &lt;span class="na"&gt;visualizer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dockersamples/visualizer:stable&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:8080"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;placement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;constraints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node.role == manager&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-overlay&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app-overlay&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;external&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;redis-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Manage Swarm Services
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check service status&lt;/span&gt;
docker service &lt;span class="nb"&gt;ls&lt;/span&gt;

&lt;span class="c"&gt;# Scale services&lt;/span&gt;
docker service scale &lt;span class="nv"&gt;myapp_web&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5

&lt;span class="c"&gt;# View service logs&lt;/span&gt;
docker service logs myapp_web

&lt;span class="c"&gt;# Update service&lt;/span&gt;
docker service update &lt;span class="nt"&gt;--image&lt;/span&gt; my-webapp:new-version myapp_web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lab 8: Monitoring and Logging&lt;/p&gt;

&lt;p&gt;Step 1: Set up Monitoring Stack&lt;br&gt;
Create &lt;code&gt;monitoring/docker-compose.monitoring.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;prometheus&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prom/prometheus:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;9090:9090"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./prometheus.yml:/etc/prometheus/prometheus.yml&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;prom_data:/prometheus&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--config.file=/etc/prometheus/prometheus.yml'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--storage.tsdb.path=/prometheus'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--web.console.libraries=/etc/prometheus/console_libraries'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--web.console.templates=/etc/prometheus/consoles'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--storage.tsdb.retention.time=200h'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--web.enable-lifecycle'&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;monitoring&lt;/span&gt;

  &lt;span class="na"&gt;grafana&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grafana/grafana:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3000:3000"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;GF_SECURITY_ADMIN_PASSWORD=admin&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;grafana_data:/var/lib/grafana&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;monitoring&lt;/span&gt;

  &lt;span class="na"&gt;node-exporter&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prom/node-exporter:latest&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/proc:/host/proc:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/sys:/host/sys:ro&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/:/rootfs:ro&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--path.procfs=/host/proc'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--path.rootfs=/rootfs'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--path.sysfs=/host/sys'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;monitoring&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;monitoring&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;prom_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;grafana_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Prometheus Configuration&lt;br&gt;
Create &lt;code&gt;monitoring/prometheus.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;scrape_interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15s&lt;/span&gt;

&lt;span class="na"&gt;scrape_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;prometheus'&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost:9090'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;node-exporter'&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;node-exporter:9100'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cadvisor'&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;cadvisor:8080'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;job_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;docker-containers'&lt;/span&gt;
    &lt;span class="na"&gt;static_configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;localhost:9323'&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lab 9: Security Best Practices&lt;/p&gt;

&lt;p&gt;Step 1: Security Scanning&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install Docker Scout (if not available, use Trivy)&lt;/span&gt;
curl &lt;span class="nt"&gt;-sSfL&lt;/span&gt; https://raw.githubusercontent.com/anchore/grype/main/install.sh | sh &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;-b&lt;/span&gt; /usr/local/bin

&lt;span class="c"&gt;# Scan image for vulnerabilities&lt;/span&gt;
grype my-webapp:secure

&lt;span class="c"&gt;# Use Docker Bench Security&lt;/span&gt;
docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--net&lt;/span&gt; host &lt;span class="nt"&gt;--pid&lt;/span&gt; host &lt;span class="nt"&gt;--userns&lt;/span&gt; host &lt;span class="nt"&gt;--cap-add&lt;/span&gt; audit_control &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;DOCKER_CONTENT_TRUST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /var/lib:/var/lib &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /var/run/docker.sock:/var/run/docker.sock &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /etc:/etc &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--label&lt;/span&gt; docker_bench_security &lt;span class="se"&gt;\&lt;/span&gt;
  docker/docker-bench-security
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Content Trust and Signing&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Enable Docker Content Trust&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DOCKER_CONTENT_TRUST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1

&lt;span class="c"&gt;# Build and push with signing&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; myregistry.azurecr.io/my-webapp:1.0 &lt;span class="nb"&gt;.&lt;/span&gt;
docker push myregistry.azurecr.io/my-webapp:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lab 10: Azure Container Registry Integration&lt;/p&gt;

&lt;p&gt;Step 1: Create and Configure ACR&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create Azure Container Registry&lt;/span&gt;
az acr create &lt;span class="nt"&gt;--resource-group&lt;/span&gt; DockerLabs &lt;span class="nt"&gt;--name&lt;/span&gt; myDockerRegistry &lt;span class="nt"&gt;--sku&lt;/span&gt; Basic

&lt;span class="c"&gt;# Login to ACR&lt;/span&gt;
az acr login &lt;span class="nt"&gt;--name&lt;/span&gt; myDockerRegistry

&lt;span class="c"&gt;# Tag and push images&lt;/span&gt;
docker tag my-webapp:secure mydockerregistry.azurecr.io/my-webapp:1.0
docker push mydockerregistry.azurecr.io/my-webapp:1.0

&lt;span class="c"&gt;# Pull from ACR&lt;/span&gt;
docker pull mydockerregistry.azurecr.io/my-webapp:1.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Automated Builds with ACR Tasks&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create ACR build task&lt;/span&gt;
az acr build &lt;span class="nt"&gt;--registry&lt;/span&gt; myDockerRegistry &lt;span class="nt"&gt;--image&lt;/span&gt; my-webapp:latest &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Set up automated build on Git commit&lt;/span&gt;
az acr task create &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--registry&lt;/span&gt; myDockerRegistry &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; buildwebapp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--image&lt;/span&gt; my-webapp:&lt;span class="o"&gt;{{&lt;/span&gt;.Run.ID&lt;span class="o"&gt;}}&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--context&lt;/span&gt; https://github.com/yourusername/my-webapp.git &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--file&lt;/span&gt; Dockerfile &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--branch&lt;/span&gt; main &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--git-access-token&lt;/span&gt; &amp;lt;your-token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Final Project: Complete Microservices Application&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;final-project/docker-compose.prod.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydockerregistry.azurecr.io/my-webapp:1.0&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;REDIS_HOST=redis&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;

  &lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydockerregistry.azurecr.io/api-service:1.0&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DATABASE_URL=postgresql://user:pass@db:5432/app&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;

  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis:7-alpine&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;placement&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;constraints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;node.role == manager&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis-data:/data&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:13&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_DB=app&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_USER=user&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;POSTGRES_PASSWORD=pass&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres-data:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;

  &lt;span class="na"&gt;traefik&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;traefik:v2.9&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;443:443"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;/var/run/docker.sock:/var/run/docker.sock&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./traefik.yml:/etc/traefik/traefik.yml&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;overlay&lt;/span&gt;
  &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;overlay&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;redis-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres-data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>N8N Installation And Configuration</title>
      <dc:creator>Droid Ek</dc:creator>
      <pubDate>Thu, 06 Nov 2025 18:49:41 +0000</pubDate>
      <link>https://dev.to/sudlo2014/n8n-installation-and-configuration-4k00</link>
      <guid>https://dev.to/sudlo2014/n8n-installation-and-configuration-4k00</guid>
      <description>&lt;p&gt;N8N Installation And Configuration&lt;/p&gt;

&lt;p&gt;Setting Up a Self-Hosted n8n Automation Server on Ubuntu&lt;/p&gt;

&lt;p&gt;This document outlines the end-to-end process of deploying the n8n automation platform on a fresh Ubuntu Server virtual machine using Docker. It also includes optional steps for adding a graphical user interface (GUI) for remote management.&lt;/p&gt;

&lt;p&gt;Operating System: Ubuntu 24.04 LTS (Server Edition)&lt;/p&gt;

&lt;p&gt;Part 1: Server and Prerequisite Setup&lt;/p&gt;

&lt;p&gt;This section covers the initial server preparation, the optional installation of a desktop environment, and the mandatory installation of the Docker Engine.&lt;/p&gt;

&lt;p&gt;Step 1.1: Virtual Machine (VM) Provisioning&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;An Ubuntu 24.04 LTS Server environment was chosen. This is a command-line-only operating system, which is lightweight and secure, making it ideal for server applications.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Step 1.2: (Optional) Installing a Graphical Desktop Environment&lt;/p&gt;

&lt;p&gt;The server operates via command line by default. For users who prefer a graphical interface for management, a desktop environment can be installed.&lt;/p&gt;

&lt;p&gt;Note: This is generally not recommended for a production server as it consumes more system resources (RAM, CPU) and can increase the system's security attack surface.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install the Ubuntu Desktop (GNOME): This command installs the standard graphical interface.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;sudo apt update&lt;/p&gt;

&lt;p&gt;sudo apt install ubuntu-desktop -y&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install a Remote Desktop Server (xrdp): To access the graphical desktop from another computer, a remote desktop protocol (RDP) server is required. xrdp is a common choice.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;sudo apt install xrdp -y&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Allow RDP through the firewall (if enabled): If you are using ufw (Uncomplicated Firewall), you must allow traffic on the RDP port.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;sudo ufw allow 3389&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;After these steps, you can connect to your server's IP address using any standard Remote Desktop Client (like the one built into Windows).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Step 1.3: System Update&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ensure all system packages are up to date.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;sudo apt update &amp;amp;&amp;amp; sudo apt upgrade -y&lt;/p&gt;

&lt;p&gt;Step 1.4: Docker Engine Installation&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install prerequisite packages: These are needed to allow apt to use repositories over HTTPS.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;sudo apt install ca-certificates curl gnupg&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Add Docker's official GPG key: This verifies the authenticity of the Docker packages.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;sudo install -m 0755 -d /etc/apt/keyrings&lt;/p&gt;

&lt;p&gt;curl -fsSL &lt;a href="https://download.docker.com/linux/ubuntu/gpg" rel="noopener noreferrer"&gt;https://download.docker.com/linux/ubuntu/gpg&lt;/a&gt; | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg&lt;/p&gt;

&lt;p&gt;sudo chmod a+r /etc/apt/keyrings/docker.gpg&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Set up the Docker repository: This tells the system where to download Docker from.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;echo \&lt;/p&gt;

&lt;p&gt;"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] &lt;a href="https://download.docker.com/linux/ubuntu" rel="noopener noreferrer"&gt;https://download.docker.com/linux/ubuntu&lt;/a&gt; \&lt;/p&gt;

&lt;p&gt;$(. /etc/os-release &amp;amp;&amp;amp; echo "$VERSION_CODENAME") stable" | \&lt;/p&gt;

&lt;p&gt;sudo tee /etc/apt/sources.list.d/docker.list &amp;gt; /dev/null&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install Docker Engine, CLI, and Compose:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;sudo apt update&lt;/p&gt;

&lt;p&gt;sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Allow non-root user to run Docker (Post-installation): Add your user to the docker group to avoid using sudo for every command.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;sudo usermod -aG docker $USER&lt;/p&gt;

&lt;p&gt;IMPORTANT: You must log out and log back in for this change to take effect.&lt;/p&gt;

&lt;p&gt;Part 2: n8n Application Deployment with Docker Compose&lt;/p&gt;

&lt;p&gt;This section details the deployment of the n8n application container.&lt;/p&gt;

&lt;p&gt;Step 2.1: Create a Project Directory&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Create and enter a dedicated directory to store n8n configuration and data.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;mkdir n8n-selfhosted&lt;/p&gt;

&lt;p&gt;cd n8n-selfhosted&lt;/p&gt;

&lt;p&gt;Step 2.2: Create the docker-compose.yml File&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Using a text editor like nano, create the configuration file that defines the n8n service.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;nano docker-compose.yml&lt;/p&gt;

&lt;p&gt;Step 2.3: Define the n8n Service&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Paste the following configuration into the docker-compose.yml file. This setup ensures data is persisted in a Docker volume.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;YAML&lt;/p&gt;

&lt;p&gt;version: '3.7'&lt;/p&gt;

&lt;p&gt;services:&lt;/p&gt;

&lt;p&gt;n8n:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;image: n8nio/n8n:latest

restart: always

ports:

  - "5678:5678"

environment:

  - GENERIC_TIMEZONE=Asia/Kolkata

  - N8N_ENCRYPTION_KEY='YOUR_SUPER_SECRET_KEY_HERE'

volumes:

  - n8n_data:/home/node/.n8n

# Wait for container to be stopped before killing it

stop_grace_period: 1m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;volumes:&lt;/p&gt;

&lt;p&gt;n8n_data:&lt;/p&gt;

&lt;p&gt;Step 2.4: Customize Configuration&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Timezone: The GENERIC_TIMEZONE was set to Asia/Kolkata to ensure scheduled workflows run at the correct local time.
Encryption Key: A unique and persistent N8N_ENCRYPTION_KEY is critical for securing credentials. A key was generated using the command below and pasted into the 'YOUR_SUPER_SECRET_KEY_HERE' placeholder.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;h1&gt;
  
  
  Run this command to generate a key
&lt;/h1&gt;

&lt;p&gt;openssl rand -base64 32&lt;/p&gt;

&lt;p&gt;Step 2.5: Launch n8n&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;From within the n8n-selfhosted directory, start the n8n container in detached mode.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;p&gt;docker compose up -d&lt;/p&gt;

&lt;p&gt;Part 3: Final Setup and Verification&lt;/p&gt;

&lt;p&gt;This section covers accessing the UI and completing the initial setup.&lt;/p&gt;

&lt;p&gt;Step 3.1: Access the n8n Web Interface&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The n8n instance is accessible via a web browser at:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;http://:5678&lt;/p&gt;

&lt;p&gt;Step 3.2: Create the n8n Owner Account&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Upon first access, the setup screen prompts for the creation of an owner (admin) account with a username, email, and password. This completes the installation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Part 4: First Workflow Creation (Beginner's Guide)&lt;/p&gt;

&lt;p&gt;A simple workflow was created to learn the core concepts of n8n.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Hello World" with the Set Node: A workflow was created with a Manual trigger and a Set node to create a static JSON object ({"message": "Hello..."}). This demonstrated the basic build-and-execute cycle.
Connecting to an API with the Weather Node:
    The Weather node was added to the workflow.
    A new credential was created for the OpenWeatherMap API by providing a free API key.
    The node was configured to fetch the current weather for "Bengaluru". This demonstrated connecting to external services and managing credentials.
Automating with the Cron Trigger:
    The Manual trigger was replaced with a Cron node.
    The schedule was set to run daily at a specific time (e.g., 9:00 AM).
    The workflow was activated using the toggle switch in the top-right, enabling it to run automatically in the background.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Appendix: Common Management Commands&lt;/p&gt;

&lt;p&gt;All commands should be run from the n8n-selfhosted directory.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Stop n8n: docker compose stop
Start n8n: docker compose start
View n8n logs: docker compose logs -f
Update n8n to the latest version:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Bash&lt;/p&gt;

&lt;h1&gt;
  
  
  Pull the latest image from Docker Hub
&lt;/h1&gt;

&lt;p&gt;docker compose pull&lt;/p&gt;

&lt;h1&gt;
  
  
  Recreate the container with the new image
&lt;/h1&gt;

&lt;p&gt;docker compose up -d&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Stop and remove the n8n container: docker compose down (Your data in the n8n_data volume will be p

reserved).
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Note: I am pretty new to the Ai, ML, Deep Learning stuff i am learning as i go.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>n8n</category>
    </item>
    <item>
      <title>Azure Landing Zone</title>
      <dc:creator>Droid Ek</dc:creator>
      <pubDate>Thu, 06 Nov 2025 18:40:53 +0000</pubDate>
      <link>https://dev.to/sudlo2014/azure-landing-zone-2k9g</link>
      <guid>https://dev.to/sudlo2014/azure-landing-zone-2k9g</guid>
      <description>&lt;p&gt;The Complete Guide to Production-Grade Azure Landing Zones&lt;/p&gt;

&lt;p&gt;Note; If you find any mistakes please do not burn me kindly let me know.&lt;/p&gt;

&lt;p&gt;Intro&lt;/p&gt;

&lt;p&gt;An Azure Landing Zone is the foundational output of a multi-subscription Azure environment that considers scale, security, governance, networking, and identity. It provides a well-defined, repeatable starting point for all your cloud workloads, ensuring they are deployed into a secure, compliant, and operationally excellent environment from day one. A landing zone solves critical enterprise challenges like inconsistent security postures, sprawling and ungoverned environments, lack of visibility, and ballooning costs by establishing a baseline architecture and "guardrails" through policy.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Architect and Design:&lt;/strong&gt; Confidently design an enterprise-grade Azure Landing Zone based on the Cloud Adoption Framework's principles.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Build with Confidence:&lt;/strong&gt; Use Infrastructure as Code (Bicep and Terraform) to deploy a complete, modular, and repeatable landing zone.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Govern at Scale:&lt;/strong&gt; Implement robust governance using Azure Policy, Management Groups, and Role-Based Access Control (RBAC) to enforce security and compliance.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Automate Everything:&lt;/strong&gt; Build and configure CI/CD pipelines in GitHub Actions and Azure DevOps to enable safe, automated, and auditable deployments.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Operate with Excellence:&lt;/strong&gt; Establish centralized monitoring, logging, and security to ensure the health, performance, and security of your Azure environment.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Validate and Test:&lt;/strong&gt; Write and execute automated tests to continuously validate the compliance and health of your landing zone.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Prerequisites: Tools, Accounts, and Setup
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;(Estimated Time: 2 Hours)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Before we build, we must prepare our workshop. This module ensures you have all the necessary tools and permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lab 1.1: Tool Installation
&lt;/h3&gt;

&lt;p&gt;| Step | Action | Command/Instructions | Expected Output/Success Indicator | Time |&lt;/p&gt;

&lt;p&gt;| 1 | &lt;strong&gt;Install Azure CLI&lt;/strong&gt; | Follow the official instructions for your OS: &lt;a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/cli/azure/install-azure-cli&lt;/a&gt; | &lt;code&gt;az --version&lt;/code&gt; returns the installed version. | 20m |&lt;br&gt;
| 2 | &lt;strong&gt;Login to Azure&lt;/strong&gt; | &lt;code&gt;az login&lt;/code&gt; | A browser window opens for authentication. The CLI outputs your subscription details in JSON format. | 5m |&lt;br&gt;
| 3 | &lt;strong&gt;Install Bicep&lt;/strong&gt; | &lt;code&gt;az bicep install&lt;/code&gt; | &lt;code&gt;Successfully installed Bicep CLI to...&lt;/code&gt; | 5m |&lt;br&gt;
| 4 | &lt;strong&gt;Install Terraform&lt;/strong&gt; | Follow the official instructions: &lt;a href="https://learn.hashicorp.com/tutorials/terraform/install-cli" rel="noopener noreferrer"&gt;https://learn.hashicorp.com/tutorials/terraform/install-cli&lt;/a&gt; | &lt;code&gt;terraform -version&lt;/code&gt; returns the installed version. | 20m |&lt;br&gt;
| 5 | &lt;strong&gt;Install VS Code&lt;/strong&gt; | Download from &lt;a href="https://code.visualstudio.com/" rel="noopener noreferrer"&gt;https://code.visualstudio.com/&lt;/a&gt; | VS Code application opens successfully. | 15m |&lt;br&gt;
| 6 | &lt;strong&gt;Install VS Code Extensions&lt;/strong&gt; | From the Extensions view (Ctrl+Shift+X), search for and install: &lt;code&gt;ms-azuretools.azure-cli&lt;/code&gt;, &lt;code&gt;ms-azuretools.vscode-bicep&lt;/code&gt;, &lt;code&gt;hashicorp.terraform&lt;/code&gt; | Extensions appear in the "Installed" list. | 15m |&lt;/p&gt;
&lt;h3&gt;
  
  
  Lab 1.2: Account and Permissions Verification
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; A landing zone deployment creates and configures fundamental resources like management groups. These actions require elevated permissions. Verifying them now prevents failures later.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Command/Instructions&lt;/th&gt;
&lt;th&gt;Expected Output/Success Indicator&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Verify Role&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;az ad signed-in-user show --query "userPrincipalName"&lt;/code&gt; and check permissions in the Azure portal at the tenant root management group.&lt;/td&gt;
&lt;td&gt;You need &lt;code&gt;Owner&lt;/code&gt; or a role with &lt;code&gt;Microsoft.Management/managementGroups/write&lt;/code&gt; permissions at the root scope.&lt;/td&gt;
&lt;td&gt;10m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Register Providers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;az provider register --namespace Microsoft.Management&lt;/code&gt; &lt;br&gt; &lt;code&gt;az provider register --namespace Microsoft.Network&lt;/code&gt; &lt;br&gt; &lt;code&gt;az provider register --namespace Microsoft.Insights&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;For each command, the output &lt;code&gt;RegistrationState&lt;/code&gt; should eventually be &lt;code&gt;Registered&lt;/code&gt;.&lt;/td&gt;
&lt;td&gt;25m&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  2. High-Level Architecture, Naming, and Tagging
&lt;/h2&gt;

&lt;p&gt;This section outlines the target state architecture we will build.&lt;/p&gt;
&lt;h3&gt;
  
  
  Architecture Diagram (Hub-and-Spoke)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/------------------------------------------------------\
| Azure Tenant / Root Management Group                 |
|                                                      |
|   /---------------------------------------------\    |
|   | Platform Management Group                   |    |
|   |   /------------------\   /----------------\ |    |
|   |   | Identity MG      |   | Management MG  | |    |
|   |   | (Sub: Identity)  |   | (Sub: Mgmt)    | |    |
|   |   \------------------/   \----------------/ |    |
|   |   /------------------\                      |    |
|   |   | Connectivity MG  |                      |    |
|   |   | (Sub: Hub Ntwk)  |                      |    |
|   |   \------------------/                      |    |
|   \---------------------------------------------/    |
|                                                      |
|   /---------------------------------------------\    |
|   | Landing Zones Management Group              |    |
|   |   /------------------\   /----------------\ |    |
|   |   | Prod MG          |   | Non-Prod MG    | |    |
|   |   | (Sub: Prod-App1) |   | (Sub: Dev-App1)| |    |
|   |   \------------------/   \----------------/ |    |
|   \---------------------------------------------/    |
\------------------------------------------------------/

Network Flow:
[Spoke VNet (Prod-App1)] &amp;lt;--VNet Peering--&amp;gt; [Hub VNet] &amp;lt;--Firewall--&amp;gt; [Internet/On-Prem]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Naming Convention and Tagging Strategy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; A consistent naming and tagging strategy is the bedrock of good governance. It enables automation, simplifies cost management, improves clarity, and enhances security by making resources easily identifiable and groupable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Naming Convention:&lt;/strong&gt; &lt;code&gt;[ResourceType]-[WorkloadName]-[Environment]-[AzureRegion]-[Instance]&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Examples:&lt;/strong&gt; &lt;code&gt;rg-myapp-prod-eastus-001&lt;/code&gt;, &lt;code&gt;vnet-hub-prod-eastus-001&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tagging Strategy (Mandatory Tags):&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tag Key&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Example Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;owner&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Identifies the business or technical owner.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;finance-team@example.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;costCenter&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Associates resource with an internal cost center.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;12345&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;environment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The deployment environment.&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;prod&lt;/code&gt; / &lt;code&gt;dev&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;appName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The name of the application or service.&lt;/td&gt;
&lt;td&gt;&lt;code&gt;SAP-HANA&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  3. Curriculum: The Learning Path
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Module 1: Governance Foundation with Management Groups
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Summary:&lt;/strong&gt; Establish the core hierarchical structure of your Azure environment.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Time:&lt;/strong&gt; 3 Hours&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Difficulty:&lt;/strong&gt; Beginner&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Module 2: Identity &amp;amp; Access Management (IAM)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Summary:&lt;/strong&gt; Configure the identity backbone, defining who can do what.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Time:&lt;/strong&gt; 4 Hours&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Difficulty:&lt;/strong&gt; Intermediate&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Module 3: Policy-Driven Governance &amp;amp; Security Baselines
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Summary:&lt;/strong&gt; Implement automated guardrails to enforce security and compliance.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Time:&lt;/strong&gt; 5 Hours&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Difficulty:&lt;/strong&gt; Intermediate&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Module 4: Network Foundation (Hub-and-Spoke)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Summary:&lt;/strong&gt; Build the core network topology for secure connectivity.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Time:&lt;/strong&gt; 6 Hours&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Difficulty:&lt;/strong&gt; Advanced&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Module 5: Centralized Operations &amp;amp; Shared Services
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Summary:&lt;/strong&gt; Deploy and configure centralized services for logging and secrets.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Time:&lt;/strong&gt; 4 Hours&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Difficulty:&lt;/strong&gt; Intermediate&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Module 6: Infrastructure as Code (IaC) &amp;amp; Repository Structure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Summary:&lt;/strong&gt; Organize your Bicep/Terraform code for scalability and reuse.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Time:&lt;/strong&gt; 5 Hours&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Difficulty:&lt;/strong&gt; Intermediate&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Module 7: CI/CD &amp;amp; GitOps Automation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Summary:&lt;/strong&gt; Build automated pipelines to deploy landing zone changes safely.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Time:&lt;/strong&gt; 6 Hours&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Difficulty:&lt;/strong&gt; Advanced&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Module 8: Capstone Project
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Summary:&lt;/strong&gt; Apply all learned concepts to build a complete landing zone from scratch.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Time:&lt;/strong&gt; 8 Hours&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Difficulty:&lt;/strong&gt; Expert&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Module 1: Governance Foundation with Management Groups
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; Management groups provide a level of scope above subscriptions, allowing you to apply governance controls like policies and access assignments efficiently and consistently across your entire Azure estate. A well-designed hierarchy is the first and most critical step to scaling your cloud environment securely.&lt;/p&gt;
&lt;h3&gt;
  
  
  Hands-on Lab: Creating the Management Group Hierarchy
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Command/Instructions&lt;/th&gt;
&lt;th&gt;Expected Output/Success Indicator&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Create Platform MG&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;az account management-group create --name "lz-platform"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JSON output describing the new &lt;code&gt;lz-platform&lt;/code&gt; MG.&lt;/td&gt;
&lt;td&gt;10m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Create Child MGs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;az account management-group create --name "lz-identity" --parent "lz-platform"&lt;/code&gt; &lt;br&gt; &lt;code&gt;az account management-group create --name "lz-management" --parent "lz-platform"&lt;/code&gt; &lt;br&gt; &lt;code&gt;az account management-group create --name "lz-connectivity" --parent "lz-platform"&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;JSON output for each new MG.&lt;/td&gt;
&lt;td&gt;15m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Create Landing Zones MG&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;az account management-group create --name "lz-landingzones"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JSON output for the &lt;code&gt;lz-landingzones&lt;/code&gt; MG.&lt;/td&gt;
&lt;td&gt;10m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Create Prod/NonProd MGs&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;az account management-group create --name "lz-prod" --parent "lz-landingzones"&lt;/code&gt; &lt;br&gt; &lt;code&gt;az account management-group create --name "lz-nonprod" --parent "lz-landingzones"&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;JSON output for each new MG.&lt;/td&gt;
&lt;td&gt;10m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Verify Hierarchy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;az account management-group show --name "lz-platform" --expand --recurse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A tree structure in the JSON output showing the parent-child relationships.&lt;/td&gt;
&lt;td&gt;5m&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Bicep Artifact: &lt;code&gt;managementGroups.bicep&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;targetScope = 'tenant'

resource mgPlatform 'Microsoft.Management/managementGroups@2021-04-01' = {
  name: 'lz-platform'
  properties: { displayName: 'Platform' }
}

resource mgConnectivity 'Microsoft.Management/managementGroups@2021-04-01' = {
  name: 'lz-connectivity'
  properties: {
    displayName: 'Connectivity'
    details: { parent: { id: mgPlatform.id } }
  }
}
// ... other MGs follow the same pattern
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Deployment:&lt;/strong&gt; &lt;code&gt;az deployment tenant create --location eastus --template-file managementGroups.bicep&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Terraform Artifact: &lt;code&gt;management_groups.tf&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_management_group"&lt;/span&gt; &lt;span class="s2"&gt;"platform"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;display_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Platform"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"lz-platform"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_management_group"&lt;/span&gt; &lt;span class="s2"&gt;"connectivity"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;display_name&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Connectivity"&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"lz-connectivity"&lt;/span&gt;
  &lt;span class="nx"&gt;parent_management_group_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_management_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// ... other MGs follow the same pattern&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Deployment:&lt;/strong&gt; &lt;code&gt;terraform init &amp;amp;&amp;amp; terraform apply&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Architectural Deep Dive &amp;amp; Use Case
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Deep Dive:&lt;/strong&gt; The recommended CAF hierarchy is relatively shallow to reduce complexity. A deep hierarchy modeled after an org chart can become difficult to manage due to complex policy and RBAC inheritance. The functional design (Platform, Landing Zones) provides a more robust model for applying governance.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Case - Preventing Cloud Sprawl:&lt;/strong&gt; An enterprise is struggling with uncontrolled resource creation and costs. By creating &lt;code&gt;Prod&lt;/code&gt; and &lt;code&gt;Non-Prod&lt;/code&gt; management groups, they can apply stricter policies (like limiting expensive VM SKUs) to the &lt;code&gt;Non-Prod&lt;/code&gt; group while applying stricter security policies to the &lt;code&gt;Prod&lt;/code&gt; group, all from a central point of control.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Module 2: Identity &amp;amp; Access Management (IAM)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; Identity is the modern security perimeter. This pillar focuses on ensuring all access to Azure is authenticated, authorized, and audited according to Zero Trust principles.&lt;/p&gt;
&lt;h3&gt;
  
  
  Hands-on Lab: Implementing Least Privilege
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Command/Instructions&lt;/th&gt;
&lt;th&gt;Expected Output/Success Indicator&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Create Custom Role&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create &lt;code&gt;SpokeVnetContributor.json&lt;/code&gt; (see below). Then run: &lt;code&gt;az role definition create --role-definition @SpokeVnetContributor.json&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;JSON output of the new role definition.&lt;/td&gt;
&lt;td&gt;20m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Assign Role&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Get your App Team's Group ID: &lt;code&gt;GROUP_ID=$(az ad group show --group "YourAppTeamGroup" --query id -o tsv)&lt;/code&gt; &lt;br&gt; Get subscription ID: &lt;code&gt;SUB_ID=$(az account show --query id -o tsv)&lt;/code&gt; &lt;br&gt; &lt;code&gt;az role assignment create --assignee $GROUP_ID --role "Spoke VNet Contributor" --scope /subscriptions/$SUB_ID&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;JSON output of the role assignment.&lt;/td&gt;
&lt;td&gt;15m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Configure PIM&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;In the Azure Portal, navigate to Azure AD &amp;gt; Privileged Identity Management. Make your platform admin account "eligible" for the built-in &lt;code&gt;Contributor&lt;/code&gt; role on the &lt;code&gt;lz-platform&lt;/code&gt; management group.&lt;/td&gt;
&lt;td&gt;When you go to "My roles" in PIM, you will see the eligible assignment and an "Activate" button.&lt;/td&gt;
&lt;td&gt;30m&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Artifact: &lt;code&gt;SpokeVnetContributor.json&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Spoke VNet Contributor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allows contributing to resources within a spoke VNet without network modification rights."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Storage/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Compute/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Sql/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Web/*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"NotActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Network/virtualNetworks/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Network/routeTables/*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AssignableScopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"/providers/Microsoft.Management/managementGroups/lz-landingzones"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Architectural Deep Dive &amp;amp; Use Cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Deep Dive - Managed Identities:&lt;/strong&gt; The superior architectural choice over service principals with secrets. A Managed Identity is a credential managed entirely by Azure for a resource (like a VM or Web App). This eliminates the entire class of risks associated with developers managing, rotating, and potentially leaking secrets.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Case 1 - Secure Emergency Access:&lt;/strong&gt; A production application is down. Using &lt;strong&gt;PIM&lt;/strong&gt;, an on-call engineer requests to activate the &lt;code&gt;Contributor&lt;/code&gt; role for 2 hours, providing the incident ticket number as justification. They get temporary, just-in-time access to fix the issue. All actions are audited, and access is automatically revoked, eliminating the risk of a standing privileged account.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Case 2 - Passwordless CI/CD:&lt;/strong&gt; A CI/CD pipeline needs to deploy resources. Instead of storing a service principal secret in GitHub, the pipeline uses &lt;strong&gt;Managed Identity&lt;/strong&gt; (or workload identity federation) to securely obtain an access token, eliminating secrets from the DevOps toolchain.&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Module 3: Policy-Driven Governance &amp;amp; Security Baselines
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; Azure Policy is the core of governance, enabling you to enforce rules at scale. It ensures that as new resources are created, they automatically adhere to security and compliance standards, preventing misconfigurations before they happen.&lt;/p&gt;
&lt;h3&gt;
  
  
  Hands-on Lab: Creating and Assigning Policy
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Command/Instructions&lt;/th&gt;
&lt;th&gt;Expected Output/Success Indicator&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Create "Enforce Tag" Policy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create &lt;code&gt;enforce-tag-policy.json&lt;/code&gt; (see below). Run:&lt;br&gt;&lt;code&gt;az policy definition create --name "enforce-costCenter-tag" --rules enforce-tag-policy.json --mode All&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;JSON output of the created policy definition.&lt;/td&gt;
&lt;td&gt;20m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Create Initiative&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;POLICY_ID=$(az policy definition show --name "enforce-costCenter-tag" --query id -o tsv)&lt;/code&gt;&lt;br&gt;Create &lt;code&gt;initiative.json&lt;/code&gt; (see below). Then run:&lt;br&gt;&lt;code&gt;az policy set-definition create --name "landingzone-baseline" --definitions initiative.json&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;JSON output of the created initiative.&lt;/td&gt;
&lt;td&gt;20m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Assign Initiative&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;INITIATIVE_ID=$(az policy set-definition show --name "landingzone-baseline" --query id -o tsv)&lt;/code&gt;&lt;br&gt;&lt;code&gt;MG_ID=$(az account management-group show --name "lz-landingzones" --query id -o tsv)&lt;/code&gt;&lt;br&gt;&lt;code&gt;az policy assignment create --name "lz-baseline-assignment" --scope $MG_ID --policy-set-definition $INITIATIVE_ID&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;JSON output of the policy assignment.&lt;/td&gt;
&lt;td&gt;15m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Test Policy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Try to create a resource group without the &lt;code&gt;costCenter&lt;/code&gt; tag under the target MG: &lt;code&gt;az group create -n "test-rg" -l "eastus"&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;The command should &lt;strong&gt;fail&lt;/strong&gt; with a policy violation error.&lt;/td&gt;
&lt;td&gt;10m&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Azure Policy JSON Artifacts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;enforce-tag-policy.json&lt;/code&gt; (&lt;code&gt;Deny&lt;/code&gt; effect)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"if"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allOf"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"field"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"equals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Resources/subscriptions/resourceGroups"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"field"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tags['costCenter']"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"exists"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"false"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"then"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"deny"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;initiative.json&lt;/code&gt; (placeholder)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"properties"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"displayName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Landing Zone Baseline Policies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"policyDefinitions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"policyDefinitionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[POLICY_ID]"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Architectural Deep Dive &amp;amp; Use Case
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Deep Dive - Policy-as-Code:&lt;/strong&gt; This is the practice of managing your policy definitions and assignments as code in a Git repository. Every change is peer-reviewed via a pull request and deployed through an automated CI/CD pipeline. This provides versioning, validation (using &lt;code&gt;what-if&lt;/code&gt;), and an audit trail for all your governance rules. The &lt;code&gt;DeployIfNotExists&lt;/code&gt; effect is a powerful remediation tool to automatically configure things like diagnostic settings.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Case - Enforcing Data Sovereignty (GDPR):&lt;/strong&gt; A European company must ensure citizen data remains within the EU. A policy initiative is assigned to their EU management group containing an "Allowed Locations" policy that only permits deployment in &lt;code&gt;West Europe&lt;/code&gt; and &lt;code&gt;North Europe&lt;/code&gt;. This automated guardrail makes it impossible for developers to accidentally violate GDPR, preventing massive potential fines.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Module 4: Network Foundation (Hub-and-Spoke)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; A hub-and-spoke network topology centralizes common services like firewalls and gateways, reducing cost and management overhead. It provides a secure and scalable model for connecting multiple workloads (spokes) while enforcing traffic inspection.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hands-on Lab: Building the Hub-and-Spoke Network
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Command/Instructions&lt;/th&gt;
&lt;th&gt;Expected Output/Success Indicator&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Deploy Hub VNet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use the &lt;code&gt;hubNetwork.bicep&lt;/code&gt; file below with the command:&lt;br&gt;&lt;code&gt;az deployment group create --resource-group "rg-hub-prod-eastus" --template-file hubNetwork.bicep&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Successful deployment. This may take 20-30 minutes for the Firewall to provision.&lt;/td&gt;
&lt;td&gt;30m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Deploy Spoke VNet&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;spokeNetwork.bicep&lt;/code&gt; below with the command:&lt;br&gt;&lt;code&gt;az deployment group create --resource-group "rg-spoke-app1-prod-eastus" --template-file spokeNetwork.bicep&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Successful deployment.&lt;/td&gt;
&lt;td&gt;15m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Peer the VNets&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;(Use CLI or Portal to create peering from Hub -&amp;gt; Spoke and Spoke -&amp;gt; Hub) &lt;code&gt;az network vnet peering create ...&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Peering status becomes &lt;code&gt;Connected&lt;/code&gt;.&lt;/td&gt;
&lt;td&gt;15m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Configure Spoke Route&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;FW_PRIVATE_IP=$(az network firewall show ... --query "ipConfigurations[0].privateIpAddress")&lt;/code&gt;&lt;br&gt;&lt;code&gt;az network route-table route create ... --next-hop-type VirtualAppliance --address-prefix 0.0.0.0/0 --next-hop-ip-address $FW_PRIVATE_IP&lt;/code&gt;&lt;br&gt;&lt;code&gt;az network vnet subnet update ... --route-table &amp;lt;YourRouteTable&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Route table is associated with the spoke subnet.&lt;/td&gt;
&lt;td&gt;20m&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Bicep Artifacts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;hubNetwork.bicep&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;param location string = resourceGroup().location
param vnetName string = 'vnet-hub-prod-eastus-001'
param firewallName string = 'fw-hub-prod-eastus-001'

resource publicIpFirewall 'Microsoft.Network/publicIPAddresses@2022-01-01' = {
  name: '${firewallName}-pip'
  location: location
  sku: { name: 'Standard' }
  properties: { publicIPAllocationMethod: 'Static' }
}

resource hubVnet 'Microsoft.Network/virtualNetworks@2022-01-01' = {
  name: vnetName
  location: location
  properties: {
    addressSpace: { addressPrefixes: [ '10.0.0.0/16' ] }
    subnets: [
      { name: 'AzureFirewallSubnet', properties: { addressPrefix: '10.0.1.0/24' } }
    ]
  }
}

resource firewall 'Microsoft.Network/azureFirewalls@2022-01-01' = {
  name: firewallName
  location: location
  properties: {
    sku: { name: 'AZFW_VNet', tier: 'Standard' }
    ipConfigurations: [
      {
        name: 'fw-ipconfig'
        properties: {
          subnet: { id: hubVnet.properties.subnets[0].id }
          publicIPAddress: { id: publicIpFirewall.id }
        }
      }
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;spokeNetwork.bicep&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;param location string = resourceGroup().location
param vnetName string = 'vnet-spoke-app1-prod-eastus-001'

resource spokeVnet 'Microsoft.Network/virtualNetworks@2022-01-01' = {
  name: vnetName
  location: location
  properties: {
    addressSpace: { addressPrefixes: [ '10.10.0.0/16' ] }
    subnets: [
      { name: 'snet-workload', properties: { addressPrefix: '10.10.1.0/24' } }
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Architectural Deep Dive &amp;amp; Use Case
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Deep Dive - Azure Virtual WAN (vWAN):&lt;/strong&gt; For enterprises with a significant global footprint and many on-premises sites, vWAN is the strategic evolution of the hub-spoke model. It's a Microsoft-managed service that creates a global transit network, simplifying routing, providing built-in transitivity (spoke-to-spoke communication), and reducing operational overhead compared to managing a mesh of regional hubs yourself.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Case - Securing a Regulated Workload (PCI-DSS):&lt;/strong&gt; A payment processing application is deployed into a dedicated spoke VNet. A route table forces all its traffic through the central Azure Firewall. The firewall policy is configured to only allow connections to known payment gateways, denying all other internet traffic. This provides the provable network isolation and traffic inspection required to meet PCI compliance.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Module 5: Centralized Operations &amp;amp; Shared Services
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; Centralizing services like logging and secrets management provides a single pane of glass for security and operations, reduces costs, and simplifies management across the entire estate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hands-on Lab: Deploying Centralized Logging
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Command/Instructions&lt;/th&gt;
&lt;th&gt;Expected Output/Success Indicator&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Create Mgmt RG&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;az group create --name "rg-management-prod-eastus" -l "eastus"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JSON output of new RG.&lt;/td&gt;
&lt;td&gt;5m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Deploy Log Analytics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;az deployment group create -g "rg-management-prod-eastus" --template-file logAnalytics.bicep&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Successful deployment.&lt;/td&gt;
&lt;td&gt;10m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Create Policy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create a &lt;code&gt;DeployIfNotExists&lt;/code&gt; policy to send diagnostics from all Key Vaults to this workspace.&lt;/td&gt;
&lt;td&gt;Policy definition is created.&lt;/td&gt;
&lt;td&gt;20m&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Assign Policy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Assign the policy to the &lt;code&gt;lz-landingzones&lt;/code&gt; management group, passing the workspace ID as a parameter.&lt;/td&gt;
&lt;td&gt;Policy assignment is created. New Key Vaults will now automatically send logs.&lt;/td&gt;
&lt;td&gt;15m&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Bicep Artifact: &lt;code&gt;logAnalytics.bicep&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;param location string = resourceGroup().location
param workspaceName string = 'log-analytics-prod-eastus'

resource logAnalyticsWorkspace 'Microsoft.OperationalInsights/workspaces@2021-06-01' = {
  name: workspaceName
  location: location
  properties: {
    sku: {
      name: 'PerGB2018'
    }
    retentionInDays: 90
  }
}

output workspaceId string = logAnalyticsWorkspace.id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Architectural Deep Dive &amp;amp; Use Case
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Deep Dive - The Subscription Vending Machine:&lt;/strong&gt; This is the pinnacle of platform automation. It's a workflow (e.g., Logic App, GitHub Actions) that allows application teams to request and receive a new, fully configured, and compliant subscription without manual intervention. The workflow creates the sub, moves it to the correct MG (inheriting policies), deploys a baseline spoke VNet peered to the hub, and assigns the team RBAC. This transforms the platform team from a gatekeeper into an enabler.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Use Case - Centralized Incident Response:&lt;/strong&gt; A SOC analyst is alerted to a threat by Azure Defender for Cloud. Because all security signals (Firewall, NSG, Azure AD, Defender) are streamed to a central &lt;strong&gt;Log Analytics Workspace&lt;/strong&gt; and ingested by &lt;strong&gt;Azure Sentinel&lt;/strong&gt;, they can see the entire attack chain in a single incident view—from the initial risky sign-in to the network traffic and the final alert on the VM—drastically reducing investigation time from hours to minutes.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Module 6 &amp;amp; 7: IaC, CI/CD, and GitOps Automation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt; Applying DevOps principles to infrastructure allows for safe, repeatable, and auditable management of your landing zone. Every change is peer-reviewed and automatically validated before being deployed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conceptual Lab: Structuring Your Repository &amp;amp; Pipeline
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Repository Structure:&lt;/strong&gt; Organize your code into a logical structure.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/infra
├── /bicep
│   ├── /modules
│   │   ├── network.bicep
│   │   └── policy.bicep
│   └── main.bicep
└── /pipelines
    └── deploy-landingzone.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Terraform State Management:&lt;/strong&gt; For Terraform, it is critical to use a remote backend to store the state file securely and to manage locking.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;backend&lt;/span&gt; &lt;span class="s2"&gt;"azurerm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rg-tfstate"&lt;/span&gt;
    &lt;span class="nx"&gt;storage_account_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"sttfstateprod"&lt;/span&gt;
    &lt;span class="nx"&gt;container_name&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tfstate"&lt;/span&gt;
    &lt;span class="nx"&gt;key&lt;/span&gt;                  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"landingzone.tfstate"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;CI/CD Pipeline (GitHub Actions):&lt;/strong&gt; The pipeline is the engine of GitOps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Trigger:&lt;/strong&gt; On pull request to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;CI (Validation) Job:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  Check out the code.&lt;/li&gt;
&lt;li&gt;  Install Bicep/Terraform.&lt;/li&gt;
&lt;li&gt;  Run a linter to check code style.&lt;/li&gt;
&lt;li&gt;  Run &lt;code&gt;az deployment mg what-if&lt;/code&gt; (for Bicep) or &lt;code&gt;terraform plan&lt;/code&gt; (for Terraform) to preview the changes.&lt;/li&gt;
&lt;li&gt;  Post the plan results as a comment on the PR.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;CD (Deployment) Job:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Trigger:&lt;/strong&gt; On merge to the &lt;code&gt;main&lt;/code&gt; branch.&lt;/li&gt;
&lt;li&gt;  Requires a manual approval step in the pipeline.&lt;/li&gt;
&lt;li&gt;  Run &lt;code&gt;az deployment mg create&lt;/code&gt; (for Bicep) or &lt;code&gt;terraform apply&lt;/code&gt; (for Terraform) to deploy the changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  GitHub Actions Artifact: &lt;code&gt;deploy-landingzone.yml&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Deploy&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Landing&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Zone'&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;main&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;validate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Azure Login&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure/login@v1&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;creds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AZURE_CREDENTIALS }}&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Bicep What-If&lt;/span&gt;
      &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.event_name == 'pull_request'&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;az deployment tenant what-if \&lt;/span&gt;
          &lt;span class="s"&gt;--location eastus \&lt;/span&gt;
          &lt;span class="s"&gt;--template-file ./infra/bicep/main.bicep&lt;/span&gt;

  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;needs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;validate&lt;/span&gt;
    &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/main' &amp;amp;&amp;amp; github.event_name == 'push'&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Azure Login&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure/login@v1&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;creds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AZURE_CREDENTIALS }}&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Bicep Deploy&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;az deployment tenant create \&lt;/span&gt;
          &lt;span class="s"&gt;--location eastus \&lt;/span&gt;
          &lt;span class="s"&gt;--template-file ./infra/bicep/main.bicep&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Module 8: Capstone Project
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Objective:&lt;/strong&gt; Deploy a complete, multi-subscription landing zone using IaC and a CI/CD pipeline, applying all concepts learned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Statement of Work:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Governance:&lt;/strong&gt; Create a management group hierarchy (Platform, Landing Zones, Prod, Non-Prod).&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Networking:&lt;/strong&gt; Deploy a hub-and-spoke topology. The hub must contain an Azure Firewall and a Log Analytics workspace. Deploy two spoke VNets (one prod, one non-prod) and peer them to the hub.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Policy:&lt;/strong&gt; Author and assign a policy initiative that enforces the &lt;code&gt;costCenter&lt;/code&gt; tag on all resource groups and requires diagnostic settings on all storage accounts.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Identity:&lt;/strong&gt; Create a custom RBAC role for an application team that grants them contributor rights within their spoke VNet but denies them rights to modify the network peering or route tables.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Automation:&lt;/strong&gt; All infrastructure must be defined in Bicep or Terraform. The deployment must be executed via a GitHub Actions pipeline that validates changes on a pull request and deploys on merge to main.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Acceptance Criteria &amp;amp; Scoring Rubric:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Pass Condition&lt;/th&gt;
&lt;th&gt;Score ( /100)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Management Groups&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Correct hierarchy is deployed and visible.&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Network&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hub with Firewall and Spokes are deployed. Peering is &lt;code&gt;Connected&lt;/code&gt;. UDR on spokes forces traffic to Firewall.&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Policy&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Policy initiative is assigned. Attempting to create an untagged RG fails.&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;RBAC&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Custom role is created and assigned. Test user can create a VM but cannot alter peering.&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CI/CD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Pipeline runs &lt;code&gt;what-if&lt;/code&gt;/&lt;code&gt;plan&lt;/code&gt; on PR and successfully deploys on merge to &lt;code&gt;main&lt;/code&gt;.&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;100&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Final Checklist &amp;amp; Production Readiness
&lt;/h2&gt;

&lt;p&gt;Before going live, perform this final go/no-go check.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  [ ] &lt;strong&gt;Governance:&lt;/strong&gt; All required policies are assigned and showing a compliant state.&lt;/li&gt;
&lt;li&gt;  [ ] &lt;strong&gt;Identity:&lt;/strong&gt; All administrative access is managed through PIM. No standing privileged accounts exist.&lt;/li&gt;
&lt;li&gt;  [ ] &lt;strong&gt;Networking:&lt;/strong&gt; Firewall rules are locked down to least privilege. Hybrid connectivity (if any) is stable and redundant.&lt;/li&gt;
&lt;li&gt;  [ ] &lt;strong&gt;Operations:&lt;/strong&gt; Centralized logging is collecting data from all critical resources. High-priority alerts (e.g., for security events) are configured and tested.&lt;/li&gt;
&lt;li&gt;  [ ] &lt;strong&gt;Costs:&lt;/strong&gt; Budgets and cost alerts are configured for all subscriptions/management groups.&lt;/li&gt;
&lt;li&gt;  [ ] &lt;strong&gt;Automation:&lt;/strong&gt; The CI/CD pipeline is the &lt;em&gt;only&lt;/em&gt; way infrastructure changes are deployed. The &lt;code&gt;main&lt;/code&gt; branch is protected, requiring PRs and reviews.&lt;/li&gt;
&lt;li&gt;  [ ] &lt;strong&gt;Validation:&lt;/strong&gt; Automated health checks are in place to validate core landing zone functionality (e.g., DNS resolution, connectivity through the firewall).&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>security</category>
      <category>architecture</category>
      <category>azure</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
