<?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>Forem: Theodora</title>
    <description>The latest articles on Forem by Theodora (@theodora_e6f61d02577a5f06).</description>
    <link>https://forem.com/theodora_e6f61d02577a5f06</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%2F2925654%2F400797ee-f46c-425e-8cb6-d468c65562f6.jpeg</url>
      <title>Forem: Theodora</title>
      <link>https://forem.com/theodora_e6f61d02577a5f06</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/theodora_e6f61d02577a5f06"/>
    <language>en</language>
    <item>
      <title>Git, GitHub, and EC2: A Practical Walkthrough from Local Repo to Live Deployment</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Thu, 29 Jan 2026 22:22:24 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/git-github-and-ec2-a-practical-walkthrough-from-local-repo-to-live-deployment-j7c</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/git-github-and-ec2-a-practical-walkthrough-from-local-repo-to-live-deployment-j7c</guid>
      <description>&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most Git and deployment issues don’t come from advanced problems, they come from skipped steps, assumptions, and rushed workflows. This post walks through a complete, end-to-end setup using Git, GitHub, and AWS EC2, focusing on how these tools are actually used in team environments.&lt;/p&gt;

&lt;p&gt;Rather than abstract theory, this guide shows the exact commands, decisions, and checks involved in moving from a local repository to a live Nginx deployment, and finally to contributing changes through a pull request. Along the way, I’ll point out where things commonly break, why certain steps matter more than they appear, and how to structure work so it’s reviewable, reversible, and safe.&lt;/p&gt;

&lt;p&gt;If you already use Git and Linux, this is meant as a practical reference and a reinforcement of good habits such as clean commits, verified state, isolated branches, and predictable deployments,because those are the details teams rely on long after the tools stop feeling new.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initializing the Project and Git Repository&lt;/li&gt;
&lt;li&gt;Configuring Git Identity (Local vs Global)&lt;/li&gt;
&lt;li&gt;Verifying Repository State Before Working&lt;/li&gt;
&lt;li&gt;Creating Project Files&lt;/li&gt;
&lt;li&gt;Adding Starter Content&lt;/li&gt;
&lt;li&gt;Tracking and Staging Files&lt;/li&gt;
&lt;li&gt;Creating the First Commit&lt;/li&gt;
&lt;li&gt;Making a Controlled Change&lt;/li&gt;
&lt;li&gt;Deploying to EC2 with Nginx&lt;/li&gt;
&lt;li&gt;Branching Workflow: Adding a Contact Page&lt;/li&gt;
&lt;li&gt;Verifying Branch Isolation&lt;/li&gt;
&lt;li&gt;Merging the Feature Branch&lt;/li&gt;
&lt;li&gt;Inspecting Commit History&lt;/li&gt;
&lt;li&gt;GitHub Collaboration: Forks and Remotes&lt;/li&gt;
&lt;li&gt;Syncing with Upstream&lt;/li&gt;
&lt;li&gt;Creating a Pull Request to Upstream&lt;/li&gt;
&lt;li&gt;Final Notes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Initializing the Project and Git Repository
&lt;/h2&gt;

&lt;p&gt;First, create your project directory and initialize Git.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1qyqadstka44wfhu8bt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1qyqadstka44wfhu8bt.png" alt=" " width="373" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To confirm Git is actually tracking this directory:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw5p22cybpx635xsc5vx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw5p22cybpx635xsc5vx.png" alt=" " width="277" height="105"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should see a .git folder. Without it, Git isn’t tracking anything,no commits, no branches, no history. Every Git workflow depends on this being present.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Git Identity (Local vs Global)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Local (Repo-Specific) Identity
&lt;/h3&gt;

&lt;p&gt;In professional environments, repositories often require specific commit identities. I configured a &lt;strong&gt;local Git identity&lt;/strong&gt; for this project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wqfti6knnxzvjowjcmp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0wqfti6knnxzvjowjcmp.png" alt=" " width="328" height="133"&gt;&lt;/a&gt;&lt;br&gt;
This ensures commits in this repo don’t accidentally use a different identity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Global Identity
&lt;/h3&gt;

&lt;p&gt;For personal or non-restricted repositories, a global identity is convenient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jscondoqbt5mgoeax6u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2jscondoqbt5mgoeax6u.png" alt=" " width="401" height="113"&gt;&lt;/a&gt;&lt;br&gt;
Local config always overrides global config. That precedence matters more than people think.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying Repository State Before Working
&lt;/h2&gt;

&lt;p&gt;Before creating files, always confirm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’re in the right directory&lt;/li&gt;
&lt;li&gt;Git is active&lt;/li&gt;
&lt;li&gt;You’re on the expected branch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3bmifkyfbxg1rj9i8nb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv3bmifkyfbxg1rj9i8nb.png" alt=" " width="255" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most Git mistakes come from skipping this check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Project Files
&lt;/h2&gt;

&lt;p&gt;I created two basic frontend files:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkk6u1x4sr38ieao0d7a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnkk6u1x4sr38ieao0d7a.png" alt=" " width="286" height="94"&gt;&lt;/a&gt;&lt;br&gt;
Verify they exist.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnbnqayltkc891c3wr5eb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnbnqayltkc891c3wr5eb.png" alt=" " width="195" height="84"&gt;&lt;/a&gt;&lt;br&gt;
This might seem trivial, but confirming file creation avoids silent errors,especially when working across multiple terminals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Starter Content
&lt;/h2&gt;

&lt;p&gt;I copied starter HTML and CSS from a remote repository and pasted it into my local files using VS Code. This mirrors real-world scenarios where teams provide templates or base layouts.&lt;/p&gt;

&lt;p&gt;At this stage, nothing is tracked yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tracking and Staging Files
&lt;/h2&gt;

&lt;p&gt;Check the current status:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhanph4dn0pv3rb4xivzc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhanph4dn0pv3rb4xivzc.png" alt=" " width="195" height="85"&gt;&lt;/a&gt;&lt;br&gt;
You should see both files listed as &lt;strong&gt;untracked&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Stage the files:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1wy5ta2uzin1503akpy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1wy5ta2uzin1503akpy.png" alt=" " width="222" height="101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;verify staging&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvev5eam21r67fojjv5cf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvev5eam21r67fojjv5cf.png" alt=" " width="233" height="101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Staging is how you control exactly what goes into a commit. Professionals don’t commit blindly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating the First Commit
&lt;/h2&gt;

&lt;p&gt;Create a clean initial commit:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxhsav4my3xprhqfpff7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxhsav4my3xprhqfpff7.png" alt=" " width="526" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify commit history&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82a4mwdnyrxjaykdtlld.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82a4mwdnyrxjaykdtlld.png" alt=" " width="216" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clear commit messages make history readable and useful months later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making a Controlled Change
&lt;/h2&gt;

&lt;p&gt;I modified the homepage content in &lt;code&gt;index.html&lt;/code&gt;, then checked status:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xe2vg2xve85z630fyil.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5xe2vg2xve85z630fyil.png" alt=" " width="300" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Stage only the modified file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2coujdxftri1188bwjo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2coujdxftri1188bwjo.png" alt=" " width="253" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Commit the change:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjath64vhfkbm44sqr5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffjath64vhfkbm44sqr5k.png" alt=" " width="330" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Multiple small commits are easier to review and easier to roll back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploying to EC2 with Nginx
&lt;/h2&gt;

&lt;h3&gt;
  
  
  SSH into the Server
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F211dms58zmg9ds6izd9r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F211dms58zmg9ds6izd9r.png" alt=" " width="365" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;-chi.pem is the name of my key.pem&lt;br&gt;
Install and Verify Nginx&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpizhyaxvpfq0y00r2hp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcpizhyaxvpfq0y00r2hp.png" alt=" " width="274" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Copy Files from Local Machine
&lt;/h3&gt;

&lt;p&gt;Since the files weren’t zipped, I transferred them individually:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmtjcao729uy9gtecq9ff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmtjcao729uy9gtecq9ff.png" alt=" " width="505" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Move Files to Nginx Web Root&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl21jgqgnnfj9mwvljsvn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl21jgqgnnfj9mwvljsvn.png" alt=" " width="356" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set Permissions&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyw5kyto6ge6petlpbti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyw5kyto6ge6petlpbti.png" alt=" " width="373" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Validate Configuration&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg36x0uh4b0sr1b3a60s5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg36x0uh4b0sr1b3a60s5.png" alt=" " width="250" height="95"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify Locally on Server&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztjv5cgqlhs16bq55far.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fztjv5cgqlhs16bq55far.png" alt=" " width="230" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then access the site in a browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi61tb58je7r7ax4eoprl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi61tb58je7r7ax4eoprl.png" alt=" " width="280" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Branching Workflow: Adding a Contact Page
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Let's talk about branching workflows!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create and Switch to &lt;strong&gt;Feature Branch&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8keduxijmhnj7x61zesq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8keduxijmhnj7x61zesq.png" alt=" " width="320" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Add New File contact.html, edit with &lt;strong&gt;VS code editor not nano&lt;/strong&gt; and Commit&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1oo9advmfhfqjs7abor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1oo9advmfhfqjs7abor.png" alt=" " width="319" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Update index.html Separately by adding the contact page link&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sq8u1w321f6zhvofvt7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4sq8u1w321f6zhvofvt7.png" alt=" " width="345" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each logical change gets its own commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying Branch Isolation
&lt;/h2&gt;

&lt;p&gt;Switch back to main branch:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk9wb3dssdd1kyj6i3f4k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk9wb3dssdd1kyj6i3f4k.png" alt=" " width="293" height="106"&gt;&lt;/a&gt;&lt;br&gt;
contact.html should not exist here. This confirms isolation before merging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Merging the Feature Branch.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhivmhb7d29u7yugzq320.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhivmhb7d29u7yugzq320.png" alt=" " width="319" height="93"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Verify files exist and render correctly in the browser.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspecting Commit History
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsm3v95kp698iu8my41dy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsm3v95kp698iu8my41dy.png" alt=" " width="327" height="95"&gt;&lt;/a&gt;&lt;br&gt;
If the history looks linear, that’s likely due to a fast-forward merge. This is expected unless --no-ff is used.It should be in a graph format.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Collaboration: Forks and Pull Requests
&lt;/h2&gt;

&lt;p&gt;Add Remotes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbidffk4l9ngaumy2rvl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbidffk4l9ngaumy2rvl.png" alt=" " width="535" height="100"&gt;&lt;/a&gt;&lt;br&gt;
Verify&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6plrjnrv8c7pxgjmae7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6plrjnrv8c7pxgjmae7k.png" alt=" " width="177" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sync with Upstream&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flcwm64a3duf4y9va3h8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flcwm64a3duf4y9va3h8e.png" alt=" " width="309" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Push Feature Branch&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76drsxuyglv6kpc3p9dh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76drsxuyglv6kpc3p9dh.png" alt=" " width="374" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then open a pull request from your fork to the upstream repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Pull Request to Upstream
&lt;/h2&gt;

&lt;p&gt;Once the feature branch is pushed to your fork, the final step is opening a Pull Request (PR) to the upstream repository. This is where your changes are reviewed and (if approved) merged.&lt;/p&gt;

&lt;h3&gt;
  
  
  Verify Your Branch Is Pushed
&lt;/h3&gt;

&lt;p&gt;First, make sure your feature branch exists on GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pxz1q808jxo4ep0clv7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4pxz1q808jxo4ep0clv7.png" alt=" " width="384" height="108"&gt;&lt;/a&gt;&lt;br&gt;
The -u flag sets the upstream tracking branch so future pushes don’t require extra arguments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open the Pull Request on GitHub
&lt;/h3&gt;

&lt;p&gt;1.Go to your fork on GitHub&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5vgutpgoa5n425xwxokx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5vgutpgoa5n425xwxokx.png" alt=" " width="639" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Switch to your feature branch (&lt;code&gt;feature/contact-page&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click &lt;strong&gt;Compare &amp;amp; pull request&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(If you don’t see it, go to &lt;strong&gt;Pull Requests → New Pull Request&lt;/strong&gt; manually.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Confirm PR Target Settings
&lt;/h3&gt;

&lt;p&gt;This part matters more than people think. Double-check everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Base repository:&lt;/strong&gt; &lt;code&gt;pravinmishraaws/devops-micro-internship-interviews&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Base branch:&lt;/strong&gt; &lt;code&gt;main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Head repository:&lt;/strong&gt; your fork&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare branch:&lt;/strong&gt; &lt;code&gt;feature/contact-page&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A surprising number of PRs fail review simply because they target the wrong repo or branch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a Clear PR Title and Description
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;PR Title&lt;/strong&gt;-docs: add contact page&lt;br&gt;
&lt;strong&gt;PR Description&lt;/strong&gt;-This PR adds a contact page and links it from the homepage.&lt;br&gt;
Changes were made on a feature branch and verified before merge.&lt;br&gt;
The goal here isn’t verbosity ,it’s clarity. Reviewers should understand what changed and why in under 10 seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the Pull Request
&lt;/h3&gt;

&lt;p&gt;Click &lt;strong&gt;Create Pull Request&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At this point:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your code is isolated&lt;/li&gt;
&lt;li&gt;The change is traceable&lt;/li&gt;
&lt;li&gt;Reviewers can comment line-by-line&lt;/li&gt;
&lt;li&gt;The main branch stays protected&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the core of how teams collaborate safely at scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why This Step Matters in Practice
&lt;/h3&gt;

&lt;p&gt;In theory, PRs are just a formality.&lt;/p&gt;

&lt;p&gt;In practice, they’re where most quality control happens.&lt;/p&gt;

&lt;p&gt;PRs are used to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Catch unintended changes&lt;/li&gt;
&lt;li&gt;Enforce standards&lt;/li&gt;
&lt;li&gt;Share context&lt;/li&gt;
&lt;li&gt;Prevent direct pushes to protected branches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Teams that skip or rush PRs usually pay for it later — in broken releases or messy rollbacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thought
&lt;/h3&gt;

&lt;p&gt;From local commits → feature branches → deployment → pull requests, this workflow isn’t about tools. It’s about &lt;strong&gt;reducing risk&lt;/strong&gt; while moving fast.&lt;/p&gt;

&lt;p&gt;Once you internalize this flow, you stop “using Git” and start &lt;strong&gt;working with teams&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>git</category>
      <category>github</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Deploying a Real React App on an Ubuntu VM with AWS and Serving It with Nginx</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Tue, 20 Jan 2026 00:26:34 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/deploying-a-real-react-app-on-an-ubuntu-vm-with-aws-and-serving-it-with-nginx-13o</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/deploying-a-real-react-app-on-an-ubuntu-vm-with-aws-and-serving-it-with-nginx-13o</guid>
      <description>&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;What You’ll Need&lt;/li&gt;
&lt;li&gt;
Step 0: Launch an Ubuntu Server on AWS EC2 and Connect via SSH

&lt;ul&gt;
&lt;li&gt;Launch the EC2 Instance&lt;/li&gt;
&lt;li&gt;Retrieve the Public IP Address&lt;/li&gt;
&lt;li&gt;Connect to the Server via SSH&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Update the System&lt;/li&gt;

&lt;li&gt;Install Node.js and npm&lt;/li&gt;

&lt;li&gt;Install and Start Nginx&lt;/li&gt;

&lt;li&gt;Clone the React Application Repository&lt;/li&gt;

&lt;li&gt;Modify the React Application&lt;/li&gt;

&lt;li&gt;Install Dependencies and Build the Application&lt;/li&gt;

&lt;li&gt;Serve the React App via Nginx&lt;/li&gt;

&lt;li&gt;Configure Nginx for a React Single-Page Application&lt;/li&gt;

&lt;li&gt;Test the Deployment&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This guide walks through launching an Ubuntu server on AWS EC2, securely connecting to it via SSH, and deploying a real React application that is served using Nginx and accessible through the server’s public IP address.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You’ll Need
&lt;/h2&gt;

&lt;p&gt;Before starting, ensure you have:&lt;/p&gt;

&lt;p&gt;An AWS account&lt;/p&gt;

&lt;p&gt;Basic familiarity with the Linux command line&lt;/p&gt;

&lt;p&gt;An SSH client (Git Bash, VS Code terminal, or WSL)&lt;/p&gt;

&lt;p&gt;Internet access&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 0: Launch an Ubuntu Server on AWS EC2 and Connect via SSH
&lt;/h2&gt;

&lt;h2&gt;
  
  
  0.1 Launch the EC2 Instance
&lt;/h2&gt;

&lt;p&gt;Log in to the AWS Management Console&lt;/p&gt;

&lt;p&gt;Navigate to EC2 → Instances → Launch instance&lt;/p&gt;

&lt;p&gt;Configure the instance:&lt;/p&gt;

&lt;p&gt;Name: react-nginx-server (or any preferred name)&lt;/p&gt;

&lt;p&gt;AMI: Ubuntu Server 22.04 LTS&lt;/p&gt;

&lt;p&gt;Instance type: t3.micro (eligible for free tier)&lt;/p&gt;

&lt;p&gt;Key pair: Create or select an existing .pem key&lt;/p&gt;

&lt;p&gt;Network settings:&lt;/p&gt;

&lt;p&gt;Allow SSH (port 22) from your IP&lt;/p&gt;

&lt;p&gt;Allow HTTP (port 80) from anywhere&lt;/p&gt;

&lt;p&gt;Launch the instance and wait until its state shows Running&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxkmzssah7y7mfom3fhvl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxkmzssah7y7mfom3fhvl.png" alt=" " width="784" height="795"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0ud80ykotq2xl1f8bfu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg0ud80ykotq2xl1f8bfu.png" alt=" " width="798" height="255"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xujwfkm76xv1qqeh44z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xujwfkm76xv1qqeh44z.png" alt=" " width="592" height="555"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbryugj98reos0m806r4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmbryugj98reos0m806r4.png" alt=" " width="784" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatce3wpf88vc7bbnio1a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fatce3wpf88vc7bbnio1a.png" alt=" " width="395" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3u29j8pr1u0vyscinugg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3u29j8pr1u0vyscinugg.png" alt=" " width="566" height="92"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Note&lt;/strong&gt;- when you click on the above , it will show the instance in a running state.&lt;/p&gt;

&lt;h2&gt;
  
  
  0.2 Retrieve the Public IP Address
&lt;/h2&gt;

&lt;p&gt;From the EC2 instance details page, copy the Public IPv4 address. This IP will be used both for SSH access and later to view the deployed React app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5w15gbtule7veev984lv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5w15gbtule7veev984lv.png" alt=" " width="658" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  0.3 Connect to the Server via SSH
&lt;/h2&gt;

&lt;p&gt;You may use Git Bash, VS Code terminal, or WSL. The command is the same.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ps1wh449f6fqfvh1qd8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ps1wh449f6fqfvh1qd8.png" alt=" " width="605" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnok19yk8tw0q83bktlya.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnok19yk8tw0q83bktlya.png" alt=" " width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbe0l2dllllkzvxm68isf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbe0l2dllllkzvxm68isf.png" alt=" " width="793" height="646"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ssh -i your-key.pem ubuntu@&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Update the System
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F059z89u7pe3ns0uhf2ys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F059z89u7pe3ns0uhf2ys.png" alt=" " width="331" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Install Node.js and npm
&lt;/h2&gt;

&lt;p&gt;These are application dependencies.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7qltqsbi786bgll5x6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7qltqsbi786bgll5x6c.png" alt=" " width="384" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Verify the installation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2cgtbb8tl85tozgg262o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2cgtbb8tl85tozgg262o.png" alt=" " width="266" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Install and Start Nginx
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pq28mrt7xfj2kbe55x9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2pq28mrt7xfj2kbe55x9.png" alt=" " width="291" height="127"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;check status&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbadl2wtf8ktqzi2kta4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbadl2wtf8ktqzi2kta4b.png" alt=" " width="276" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, Nginx should already be serving the default welcome page on port 80.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcp6wzhakg0idt90dz1qg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcp6wzhakg0idt90dz1qg.png" alt=" " width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Clone the React Application Repository
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0trmi2g2pmcvpxp5c23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0trmi2g2pmcvpxp5c23.png" alt=" " width="513" height="95"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This pulls the application source code to the server.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Modify the React Application
&lt;/h2&gt;

&lt;p&gt;Navigate to the source directory&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw1a832h58oebmheno4rc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw1a832h58oebmheno4rc.png" alt=" " width="335" height="92"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(You may use vi or vim if preferred.)]&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Replace the placeholder values with your own details:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6dwzrahlega78z19fua.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6dwzrahlega78z19fua.png" alt=" " width="463" height="133"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Example&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhr7zgg5kwu8qqezwdltp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhr7zgg5kwu8qqezwdltp.png" alt=" " width="391" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Save and exit the editor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Install Dependencies and Build the Application
&lt;/h2&gt;

&lt;p&gt;Return to the project root directory&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fozqtj12k86hiq70ugmgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fozqtj12k86hiq70ugmgc.png" alt=" " width="209" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Install dependencies&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0w2s2mhtksos1k0bvce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0w2s2mhtksos1k0bvce.png" alt=" " width="175" height="59"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Build the production bundle&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmimmzl8fkhne4hm2xsi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frmimmzl8fkhne4hm2xsi.png" alt=" " width="182" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This generates a build/ directory containing optimized static files.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7: Serve the React App via Nginx
&lt;/h2&gt;

&lt;p&gt;Clear the default web directory&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwprhuwz97olv0r8171ri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwprhuwz97olv0r8171ri.png" alt=" " width="286" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the build output to Nginx’s document root&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fso6k9u512yqhnx78iwxn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fso6k9u512yqhnx78iwxn.png" alt=" " width="293" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Set correct permissions&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx27t0z1k0pu89n34599b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx27t0z1k0pu89n34599b.png" alt=" " width="393" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This ensures Nginx can read and serve the files securely.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 8: Configure Nginx for a React Single-Page Application
&lt;/h2&gt;

&lt;p&gt;Replace the default Nginx site configuration &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq56u76zfp81ol0d66lf5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq56u76zfp81ol0d66lf5.png" alt=" " width="548" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;- This should be ran directly on your terminal&lt;/p&gt;

&lt;p&gt;Restart Nginx&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmxkstxzxyk4te3p2dfd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmxkstxzxyk4te3p2dfd.png" alt=" " width="256" height="80"&gt;&lt;/a&gt;&lt;br&gt;
Optional validation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgi2ejh9hvme038yua075.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgi2ejh9hvme038yua075.png" alt=" " width="218" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 9: Test the Deployment
&lt;/h2&gt;

&lt;p&gt;Retrieve your public IP address&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fga73mhowv4zkf6sfhf1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fga73mhowv4zkf6sfhf1g.png" alt=" " width="251" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Access the application in your browser&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9kng6n2pb65zb6j0xd3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi9kng6n2pb65zb6j0xd3.png" alt=" " width="333" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhw1zn2wuy5a5y164nl0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhw1zn2wuy5a5y164nl0q.png" alt=" " width="714" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations&lt;/p&gt;

&lt;p&gt;You have successfully:&lt;/p&gt;

&lt;p&gt;Launched an Ubuntu server on AWS EC2&lt;/p&gt;

&lt;p&gt;Connected securely via SSH&lt;/p&gt;

&lt;p&gt;Built a React application for production&lt;/p&gt;

&lt;p&gt;Served it efficiently using Nginx&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Deploying a Dockerized Web Application to Azure Using Terraform (Manual Docker Build and Push)</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Sun, 26 Oct 2025 15:36:25 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/deploying-a-dockerized-web-application-to-azure-using-terraform-manual-docker-build-and-push-3pmp</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/deploying-a-dockerized-web-application-to-azure-using-terraform-manual-docker-build-and-push-3pmp</guid>
      <description>&lt;p&gt;We will go through the process of deploying a Dockerized Node.js application to Azure Container Instances (ACI) using Terraform. Along the way, we’ll leverage a manual approach to build and push the Docker image to Azure Container Registry (ACR) deployed by Terraform, and then automate the deployment of that image to ACI using Terraform.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before diving into the deployment, make sure you have the following tools installed and configured:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terraform&lt;/strong&gt; installed: &lt;a href="https://developer.hashicorp.com/terraform/downloads" rel="noopener noreferrer"&gt;Install Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt; installed and running: &lt;a href="https://docs.docker.com/get-docker/" rel="noopener noreferrer"&gt;Install Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure CLI&lt;/strong&gt; installed and authenticated: &lt;a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli" rel="noopener noreferrer"&gt;Install Guide&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Azure Subscription&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
Step 1: Set Up Azure Container Registry (ACR)

&lt;ul&gt;
&lt;li&gt;
Set Up variables.tf
&lt;/li&gt;
&lt;li&gt;
Create terraform.tfvars
&lt;/li&gt;
&lt;li&gt;
Apply Terraform to Deploy Azure Container Registry
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Step 2: Manually Build and Push the Docker Image
&lt;/li&gt;
&lt;li&gt;
Step 3: Deploy to Azure Container Instances (ACI) Using Terraform
&lt;/li&gt;
&lt;li&gt;
Step 4: Apply Terraform and Deploy
&lt;/li&gt;
&lt;li&gt;
Step 5: Access Your Application
&lt;/li&gt;
&lt;li&gt;
Troubleshooting Tips
&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Set Up Azure Container Registry (ACR)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To get started, we first need to create an &lt;strong&gt;Azure Container Registry (ACR)&lt;/strong&gt;, which will store our Docker images before deploying them to &lt;strong&gt;Azure Container Instances (ACI)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In your &lt;strong&gt;Terraform configuration&lt;/strong&gt;, create the following resources:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;main.tf (Terraform Configuration)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex3odxv6p8eo2jaz4ztn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex3odxv6p8eo2jaz4ztn.png" alt=" " width="764" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;rg-theodora-container&lt;/code&gt;&lt;/strong&gt;: The resource group in Azure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;hostcr2025&lt;/code&gt;&lt;/strong&gt;: The Azure Container Registry where we will push our Docker image.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  set up variables.tf
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfg3u61gdrd09vhhr258.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpfg3u61gdrd09vhhr258.png" alt=" " width="708" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create terraform.tfvars
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1mcgp7s2px0bhsgumsb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1mcgp7s2px0bhsgumsb.png" alt=" " width="503" height="214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Apply Terraform to Deploy Azure Container Registry
&lt;/h2&gt;

&lt;p&gt;Once your main.tf, variables.tf, and terraform.tfvars files are ready, use the following commands to deploy your Azure resources:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdiwkc6w0filodkca6jzm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdiwkc6w0filodkca6jzm.png" alt=" " width="611" height="87"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Initializes Terraform, downloads the required providers (like AzureRM), and prepares your workspace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7dq65x7te5epdnkae0s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7dq65x7te5epdnkae0s.png" alt=" " width="536" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Checks that all Terraform files are syntactically correct and the configuration is valid.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwtia090fnhajjg8ek39a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwtia090fnhajjg8ek39a.png" alt=" " width="531" height="66"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Generates and shows an execution plan, detailing what Terraform will create, modify, or destroy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbb1rqv2tl5y9vpn1oss4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbb1rqv2tl5y9vpn1oss4.png" alt=" " width="552" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Executes the deployment based on your plan.&lt;br&gt;
When prompted, type yes to confirm and start creating the Azure resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Manually Build and Push the Docker Image&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that we have our ACR setup, we need to &lt;strong&gt;manually build the Docker image&lt;/strong&gt; and &lt;strong&gt;push it to ACR&lt;/strong&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Dockerfile&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Here’s the &lt;strong&gt;Dockerfile&lt;/strong&gt; for a basic &lt;strong&gt;Node.js&lt;/strong&gt; application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2heh9ru0hys5r4xeybs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2heh9ru0hys5r4xeybs.png" alt=" " width="742" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This &lt;strong&gt;Dockerfile&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Starts from a &lt;strong&gt;Node.js&lt;/strong&gt; base image.&lt;/li&gt;
&lt;li&gt;Installs dependencies.&lt;/li&gt;
&lt;li&gt;Runs the app using &lt;strong&gt;&lt;code&gt;serve&lt;/code&gt;&lt;/strong&gt; on &lt;strong&gt;port 3000&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Manually Build and Push Docker Image&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To build and push the Docker image to ACR manually, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Login to ACR&lt;/strong&gt;:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ywob3hx76dkue50av8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ywob3hx76dkue50av8w.png" alt=" " width="446" height="77"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build the Docker image:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frndbub9g3v519cyha6ri.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frndbub9g3v519cyha6ri.png" alt=" " width="516" height="113"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Push the Docker image to ACR:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff94jgii4vi25ial4qndc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff94jgii4vi25ial4qndc.png" alt=" " width="427" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This step ensures that your Docker image is available in ACR, and Terraform can reference it during the deployment to Azure Container Instances (ACI).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Deploy Docker Image to Azure Container Instances (ACI) with Terraform&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that the Docker image is in &lt;strong&gt;ACR&lt;/strong&gt;, we’ll use &lt;strong&gt;Terraform&lt;/strong&gt; to deploy the container to &lt;strong&gt;Azure Container Instances (ACI)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Create your &lt;strong&gt;ACI.tf&lt;/strong&gt; with the following configuration to deploy the image:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Terraform Configuration for ACI Deployment&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fep63tjoro6j50ghblip1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fep63tjoro6j50ghblip1.png" alt=" " width="798" height="573"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This configuration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses the &lt;strong&gt;image&lt;/strong&gt; we pushed to &lt;strong&gt;ACR&lt;/strong&gt; (&lt;code&gt;hostcr2025.azurecr.io/electrot:v1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Exposes port &lt;strong&gt;3000&lt;/strong&gt; (matching the app’s internal port).&lt;/li&gt;
&lt;li&gt;Creates a &lt;strong&gt;public IP&lt;/strong&gt; and a &lt;strong&gt;DNS label&lt;/strong&gt; (&lt;code&gt;theocontainer2025&lt;/code&gt;) for external access.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 4: Apply Terraform to Deploy the Container&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Now that everything is set up, we’ll use &lt;strong&gt;Terraform&lt;/strong&gt; to deploy the container.&lt;br&gt;
 &lt;strong&gt;Follow the terraform deployment process above&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 5: Access Your Application&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After deploying the container to &lt;strong&gt;Azure Container Instances (ACI)&lt;/strong&gt;, you should be able to access your application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DNS Name&lt;/strong&gt;: &lt;code&gt;http://theocontainer2025.eastus.azurecontainer.io:3000&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public IP&lt;/strong&gt;: You can also access the app using the public IP address of your ACI container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, the &lt;strong&gt;public IP&lt;/strong&gt; can be retrieved using this Azure CLI command:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6y3xkono1c3d53r3ose.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6y3xkono1c3d53r3ose.png" alt=" " width="684" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Troubleshooting Tips&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inaccessible Image&lt;/strong&gt;: If you encounter the &lt;code&gt;InaccessibleImage&lt;/code&gt; error, it typically means there’s an issue with image permissions in &lt;strong&gt;ACR&lt;/strong&gt;. Double-check that the image exists in ACR and that &lt;strong&gt;ACI&lt;/strong&gt; has the correct credentials to pull the image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port Binding&lt;/strong&gt;: Ensure that your application is listening to the right port.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container Logs&lt;/strong&gt;: You can check the logs of your container to make sure it's running correctly using:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7huuah303dhmwd8p2uf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa7huuah303dhmwd8p2uf.png" alt=" " width="670" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this tutorial, we:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Set up an Azure Container Registry (ACR)&lt;/strong&gt; using &lt;strong&gt;Terraform&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manually built&lt;/strong&gt; and &lt;strong&gt;pushed the Docker image&lt;/strong&gt; to &lt;strong&gt;ACR&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Used &lt;strong&gt;Terraform&lt;/strong&gt; to &lt;strong&gt;deploy the image to Azure Container Instances (ACI)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Exposed the application via &lt;strong&gt;public IP&lt;/strong&gt; and &lt;strong&gt;DNS&lt;/strong&gt; for external access.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While the manual &lt;strong&gt;Docker build and push&lt;/strong&gt; process can seem tedious, it gives you full control and debugging capabilities, especially when things don’t work perfectly with automation. Using &lt;strong&gt;Terraform&lt;/strong&gt; for deployment makes managing and automating the infrastructure side seamless.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>docker</category>
      <category>terraform</category>
      <category>devops</category>
    </item>
    <item>
      <title>Creating and Deploying a Custom Docker Image with Azure Container Registry and Azure Container Instances</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Mon, 20 Oct 2025 21:49:43 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/creating-and-deploying-a-custom-docker-image-with-azure-container-registry-and-azure-container-3d80</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/creating-and-deploying-a-custom-docker-image-with-azure-container-registry-and-azure-container-3d80</guid>
      <description>&lt;p&gt;Table of Contents&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Step 1: Create a Simple Dockerfile and Shell Script&lt;/li&gt;
&lt;li&gt;Step 2: Build the Docker Image&lt;/li&gt;
&lt;li&gt;Step 3: Set Up Azure Container Registry&lt;/li&gt;
&lt;li&gt;Step 4: Push Docker Image to ACR&lt;/li&gt;
&lt;li&gt;Step 5: Deploy to Azure Container Instances&lt;/li&gt;
&lt;li&gt;Common Errors and Fixes&lt;/li&gt;
&lt;li&gt;Final Checks&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Make sure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✔️ An &lt;a href="https://portal.azure.com/" rel="noopener noreferrer"&gt;Azure account&lt;/a&gt; (you can create one for free)&lt;/li&gt;
&lt;li&gt;✔️ &lt;a href="https://learn.microsoft.com/en-us/cli/azure/install-azure-cli" rel="noopener noreferrer"&gt;Azure CLI&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✔️ &lt;a href="https://www.docker.com/products/docker-desktop" rel="noopener noreferrer"&gt;Docker Desktop&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;✔️ A terminal or PowerShell window&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Create a Simple Dockerfile and Shell Script
&lt;/h2&gt;

&lt;p&gt;Create a new directory, then inside it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1v5ck8ntbyhasjn1u6n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb1v5ck8ntbyhasjn1u6n.png" alt=" " width="563" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a minimal Dockerfile using the nginx base image and a custom shell script.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;FROM nginx:latest&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This tells Docker to &lt;strong&gt;use the latest version of the official &lt;code&gt;nginx&lt;/code&gt; image&lt;/strong&gt; from Docker Hub as the base image.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The base image already includes Nginx installed and configured.&lt;/li&gt;
&lt;li&gt;It's lightweight and typically used for serving web content.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;ARG VERSION&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This declares a &lt;strong&gt;build-time argument&lt;/strong&gt; named &lt;code&gt;VERSION&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ARG&lt;/code&gt; is only available during the image &lt;strong&gt;build process&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You can pass it using &lt;code&gt;-build-arg&lt;/code&gt; like this:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;docker build --build-arg VERSION=1.2.3&lt;/strong&gt;&lt;br&gt;
 ### &lt;strong&gt;&lt;code&gt;ENV VERSION=$VERSION&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This sets an &lt;strong&gt;environment variable inside the container&lt;/strong&gt; using the value passed during build time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ENV&lt;/code&gt; is available at &lt;strong&gt;runtime&lt;/strong&gt; — your script or Nginx can access it.&lt;/li&gt;
&lt;li&gt;You can verify it with:
&lt;strong&gt;echo $VERSION&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;COPY hostname.sh .&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This &lt;strong&gt;copies the &lt;code&gt;hostname.sh&lt;/code&gt; script from your local directory into the image's working directory&lt;/strong&gt; (which is &lt;code&gt;/&lt;/code&gt; by default unless changed).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you want it in a specific directory like &lt;code&gt;/usr/local/bin&lt;/code&gt;, you should write:
&lt;strong&gt;COPY hostname.sh /usr/local/bin/&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;code&gt;CMD ["/hostname.sh"]&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;This sets the &lt;strong&gt;default command that runs when the container starts&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It overrides Nginx’s default command.&lt;/li&gt;
&lt;li&gt;So instead of starting Nginx, the container will &lt;strong&gt;run the &lt;code&gt;hostname.sh&lt;/code&gt; script&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; If the script isn't executable or doesn't start with a shebang (#!/bin/bash or similar), the container will fail.&lt;/p&gt;

&lt;p&gt;This Dockerfile creates a container that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Uses the latest Nginx image.&lt;/li&gt;
&lt;li&gt;Accepts a version number at build time.&lt;/li&gt;
&lt;li&gt;Sets that version as an environment variable.&lt;/li&gt;
&lt;li&gt;Copies a script called &lt;code&gt;hostname.sh&lt;/code&gt; into the container.&lt;/li&gt;
&lt;li&gt;Runs that script instead of Nginx when the container starts&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Script Breakdown: hostname.sh
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3x5t5py0cho3rbe9l8n1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3x5t5py0cho3rbe9l8n1.png" alt=" " width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;#!/bin/sh&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;This line tells the system to use the &lt;strong&gt;&lt;code&gt;sh&lt;/code&gt; shell&lt;/strong&gt; to run the script.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;HOSTNAME=\&lt;/code&gt;hostname``
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Runs the &lt;code&gt;hostname&lt;/code&gt; command, capturing the &lt;strong&gt;machine/container name&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Stores it in the variable &lt;code&gt;HOSTNAME&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;VERSION=${VERSION:-v1}&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Reads the &lt;code&gt;VERSION&lt;/code&gt; environment variable if it’s set.&lt;/li&gt;
&lt;li&gt;If not, it defaults to &lt;code&gt;v1&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Creates a landing HTML page for the root of the Nginx server:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;cat &amp;gt; /usr/share/nginx/html/index.html &amp;lt;&amp;lt;EOF&lt;br&gt;
...&lt;br&gt;
EOF&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This file will be served when someone visits &lt;code&gt;/&lt;/code&gt; in the browser.&lt;/li&gt;
&lt;li&gt;It includes:

&lt;ul&gt;
&lt;li&gt;Writes an HTML file directly to the default Nginx directory.&lt;/li&gt;
&lt;li&gt;The hostname (of the container or VM)&lt;/li&gt;
&lt;li&gt;The version number&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;mkdir /usr/share/nginx/html/healthz /usr/share/nginx/html/hostname /usr/share/nginx/html/version&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Creates &lt;strong&gt;3 subdirectories&lt;/strong&gt; inside Nginx's web root:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/healthz&lt;/code&gt; – for liveness/readiness checks&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/hostname&lt;/code&gt; – for showing the container’s hostname and version&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/version&lt;/code&gt; – for showing the version only&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Writes mini HTML/text responses to each endpoint:&lt;br&gt;
&lt;strong&gt;cat &amp;gt; /usr/share/nginx/html/hostname/index.html &amp;lt;&amp;lt;EOF&lt;br&gt;
$HOSTNAME -- $VERSION&lt;br&gt;
EOF&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shows: &lt;code&gt;hostname -- version&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Endpoint: &lt;code&gt;/hostname&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;cat &amp;gt; /usr/share/nginx/html/version/index.html &amp;lt;&amp;lt;EOF&lt;br&gt;
$VERSION&lt;br&gt;
EOF&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Endpoint: &lt;code&gt;/version&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Shows: version only&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;chmod 777 /usr/share/nginx/html/healthz&lt;br&gt;
cat &amp;gt; /usr/share/nginx/html/healthz/index.html &amp;lt;&amp;lt;EOF&lt;br&gt;
healthy&lt;br&gt;
EOF&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Grants all permissions to &lt;code&gt;/healthz&lt;/code&gt; directory (not ideal for production, but okay for dev/demo).&lt;/li&gt;
&lt;li&gt;Writes a file that says &lt;code&gt;healthy&lt;/code&gt; to &lt;code&gt;/healthz/index.html&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;This is useful for Kubernetes or Docker health checks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;nginx -g "daemon off;"&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Starts Nginx in &lt;strong&gt;foreground mode&lt;/strong&gt; (so the container doesn't exit).&lt;/li&gt;
&lt;li&gt;This is required in Docker — if the main process exits, the container stops.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When this script runs inside a Docker container, it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpukud4mdguboshooiknj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpukud4mdguboshooiknj.png" alt=" " width="484" height="262"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you access the container in a browser (or curl):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt; → HTML page showing the hostname and version&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/healthz&lt;/code&gt; → returns &lt;code&gt;healthy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/hostname&lt;/code&gt; → returns &lt;code&gt;hostname -- version&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/version&lt;/code&gt; → returns the version string&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 2: Build the Docker Image
&lt;/h2&gt;

&lt;p&gt;Open PowerShell in the folder and run:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftl8ogssurg5yhd732lpd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftl8ogssurg5yhd732lpd.png" alt=" " width="517" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi00g4fvj6585cyuirxaq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi00g4fvj6585cyuirxaq.png" alt=" " width="526" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femdz5bnuuuipf0vr52kj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Femdz5bnuuuipf0vr52kj.png" alt=" " width="800" height="280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdtwpsdki2v2awvqa05a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdtwpsdki2v2awvqa05a.png" alt=" " width="587" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Set Up Azure Container Registry
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://portal.azure.com/" rel="noopener noreferrer"&gt;Azure Portal&lt;/a&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search for &lt;strong&gt;Container Registry&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Choose a name (mine was &lt;code&gt;hostcr&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Set the resource group, region, SKU, etc.&lt;/li&gt;
&lt;li&gt;Enable &lt;strong&gt;Admin User&lt;/strong&gt; under Access Keys after creation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdqhf1iph3xrfktpngsf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdqhf1iph3xrfktpngsf.png" alt=" " width="800" height="739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Focnv7z4a5hg1paztnehl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Focnv7z4a5hg1paztnehl.png" alt=" " width="463" height="840"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nobkk2kknmny91rqh0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5nobkk2kknmny91rqh0t.png" alt=" " width="483" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8phn9l1lwwjw89cqi0a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn8phn9l1lwwjw89cqi0a.png" alt=" " width="707" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Push Docker Image to ACR
&lt;/h2&gt;

&lt;p&gt;1.Authenticate with Azure:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fci53fmfeya5iur71p7sb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fci53fmfeya5iur71p7sb.png" alt=" " width="521" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tag Your Docker Image&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvsvffbfpxhnh4t01u9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxvsvffbfpxhnh4t01u9s.png" alt=" " width="463" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to ACR&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j8w4qeqht0w4mpt2eg8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3j8w4qeqht0w4mpt2eg8.png" alt=" " width="401" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9dki566614pr43l786p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu9dki566614pr43l786p.png" alt=" " width="302" height="93"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Push the Image to ACR&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4j4roirkk6noiq08tzho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4j4roirkk6noiq08tzho.png" alt=" " width="421" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpg77mcr4odv427zsocbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpg77mcr4odv427zsocbp.png" alt=" " width="700" height="143"&gt;&lt;/a&gt;&lt;br&gt;
 &lt;strong&gt;boops&lt;/strong&gt;-I lost my screenshot of the Azure intercae for this&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Deploy to Azure Container Instances
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the Azure portal, search for &lt;strong&gt;Container Instances&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Fill in:

&lt;ul&gt;
&lt;li&gt;Name&lt;/li&gt;
&lt;li&gt;Resource Group&lt;/li&gt;
&lt;li&gt;Image source: Azure Container Registry&lt;/li&gt;
&lt;li&gt;Image: &lt;code&gt;hostcr.azurecr.io/hostname:v1&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Review and create&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0w0eqn6bbw6a8xewox2h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0w0eqn6bbw6a8xewox2h.png" alt=" " width="663" height="744"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjs8tmg81r5p92fopw2de.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjs8tmg81r5p92fopw2de.png" alt=" " width="601" height="762"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcorlbozehra90udq6cfy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcorlbozehra90udq6cfy.png" alt=" " width="675" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Errors and Fixes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ &lt;code&gt;docker push&lt;/code&gt; returns "authentication required"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Make sure you're logged into ACR:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmf1a6qmyx84vrggun0q0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmf1a6qmyx84vrggun0q0.png" alt=" " width="366" height="101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ❌ &lt;code&gt;az login&lt;/code&gt; fails due to tenant mismatch
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Use the right tenant ID explicitly:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu06yqozgxyxw67ndr2n3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu06yqozgxyxw67ndr2n3.png" alt=" " width="405" height="110"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✅ Final Checks
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to your deployed &lt;strong&gt;Container Instance&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Copy the &lt;strong&gt;public IP&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Visit in browser:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hcmoktfrmpx8bellxn2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7hcmoktfrmpx8bellxn2.png" alt=" " width="440" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You should see HTML responses with hostname, version, and health check status.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpu9hkvr6gk62l8w69a8w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpu9hkvr6gk62l8w69a8w.png" alt=" " width="694" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nexedge</category>
      <category>maryajayi</category>
      <category>tutorial</category>
      <category>cloudcomputing</category>
    </item>
    <item>
      <title>Getting Started with Docker Compose: A Hands-On Guide to Multi-Container Applications</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Fri, 10 Oct 2025 22:39:23 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/getting-started-with-docker-compose-a-hands-on-guide-to-multi-container-applications-4lom</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/getting-started-with-docker-compose-a-hands-on-guide-to-multi-container-applications-4lom</guid>
      <description>&lt;p&gt;If you’ve been working with Docker, you’ve probably been dealing with single-container applications. However, when your applications become more complex, you may need to run multiple services, such as databases, message queues, or caches. The question is: &lt;strong&gt;Do you install everything in a single container, or do you run multiple containers?&lt;/strong&gt; And if you run multiple containers, &lt;strong&gt;how do you connect them together?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this blog post, we’ll explore how &lt;strong&gt;Docker Compose&lt;/strong&gt; makes managing multi-container applications easy. We’ll work with a simple to-do list app built with &lt;strong&gt;Node.js&lt;/strong&gt; and &lt;strong&gt;MySQL&lt;/strong&gt; to demonstrate how Docker Compose can manage your containers, network, and persistent data, all in a single YAML file.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Table of Contents&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Why Use Docker Compose?&lt;/li&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Lab 1: Setting Up the Application&lt;/li&gt;
&lt;li&gt;Lab 2: Starting the Application&lt;/li&gt;
&lt;li&gt;Lab 3: Accessing the Application&lt;/li&gt;
&lt;li&gt;Tearing Down the Application&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Why Use Docker Compose?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;One of the key best practices for containers is that &lt;strong&gt;each container should do one thing and do it well&lt;/strong&gt;. When your project grows, running everything inside a single container can quickly become a mess. Imagine running a database, an application server, and a message queue all in one container,it’s not scalable, maintainable, or efficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker Compose&lt;/strong&gt; solves this problem by allowing you to define multiple containers and their configurations in a single file, called a &lt;code&gt;docker-compose.yml&lt;/code&gt;. This file allows you to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Define all services&lt;/strong&gt; in one place.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automate network setup&lt;/strong&gt; for your containers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persist data&lt;/strong&gt; across container restarts using volumes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manage environments&lt;/strong&gt; with environment variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rebuild containers&lt;/strong&gt; when changes are made using a simple command.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker Compose is declarative. You define what you need, and when you run &lt;code&gt;docker-compose up&lt;/code&gt;, Docker Compose ensures your environment is built correctly.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Prerequisites&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before you begin, make sure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Docker Desktop&lt;/strong&gt;: Install it from the official Docker website for your operating system.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git&lt;/strong&gt;: To clone the application repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Lab 1: Setting Up the Application&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s begin by setting up the sample application.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Clone the Sample Application&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;First, open your terminal and clone the application repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fxo9f5tt1qo5r9cxl3j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fxo9f5tt1qo5r9cxl3j.png" alt=" " width="569" height="122"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Explore the Compose File&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Inside the &lt;code&gt;todo-list-app&lt;/code&gt; directory, you’ll find a file named &lt;code&gt;docker-compose.yml&lt;/code&gt; (also called the Compose file). This YAML file defines all the services that make up your application, their configurations, and how they connect.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Overview of the Docker Compose File&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;docker-compose.yml&lt;/code&gt; file includes the following key sections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;services&lt;/strong&gt;: Defines the individual containers (e.g., app, mysql).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;networks&lt;/strong&gt;: Specifies how services communicate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;volumes&lt;/strong&gt;: Persists data, especially for databases, even when containers are stopped.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;environment variables&lt;/strong&gt;: Provides configuration data to containers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3b2dm0e8akeil6x7zbb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3b2dm0e8akeil6x7zbb1.png" alt=" " width="747" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Lab 2: Starting the Application&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, let’s start the application with Docker Compose.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Run the Application Using Docker Compose&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Run the following command to start the application in detached mode (&lt;code&gt;-d&lt;/code&gt;) and build the services:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25bslkx00xzmbl9px8mc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25bslkx00xzmbl9px8mc.png" alt=" " width="553" height="107"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbxuaniumhrnuoy1j9kn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbxuaniumhrnuoy1j9kn.png" alt=" " width="487" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What happened?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker pulled the &lt;strong&gt;Node.js&lt;/strong&gt; and &lt;strong&gt;MySQL&lt;/strong&gt; images from Docker Hub.&lt;/li&gt;
&lt;li&gt;A new &lt;strong&gt;network&lt;/strong&gt; was created for the application to allow communication between the containers.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;volume&lt;/strong&gt; was created to persist MySQL data.&lt;/li&gt;
&lt;li&gt;Two containers, &lt;code&gt;todo-list-app-app-1&lt;/code&gt; (Node.js app) and &lt;code&gt;todo-list-app-mysql-1&lt;/code&gt; (MySQL), were started.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F19kdthvjtqnkyc174v1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F19kdthvjtqnkyc174v1i.png" alt=" " width="800" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Lab 3: Accessing the Application&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Once everything is up and running, you can access your to-do list app in your browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Access the Frontend&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In your browser, visit:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firrml2d37fou2ysmrpr0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Firrml2d37fou2ysmrpr0.png" alt=" " width="526" height="104"&gt;&lt;/a&gt;&lt;br&gt;
 or on docker desktop, click&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtvachl8841ilk7ac1es.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhtvachl8841ilk7ac1es.png" alt=" " width="685" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhzxqs010ed9n69w670g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhzxqs010ed9n69w670g.png" alt=" " width="557" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;View the Containers in Docker Desktop&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You can also use &lt;strong&gt;Docker Desktop&lt;/strong&gt; to monitor your containers and their configurations. Open Docker Desktop and navigate to the &lt;strong&gt;Containers&lt;/strong&gt; tab to see the &lt;code&gt;todo-list-app-app-1&lt;/code&gt; and &lt;code&gt;todo-list-app-mysql-1&lt;/code&gt; containers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcj9qvyi84o2f9hzbrrnz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcj9qvyi84o2f9hzbrrnz.png" alt=" " width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Tearing Down the Application&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When you're done with the application, it’s easy to tear everything down using Docker Compose.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Stop the Containers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To stop all running containers and remove them, run:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwth2gsa4qbbqlsrnjhmf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwth2gsa4qbbqlsrnjhmf.png" alt=" " width="530" height="99"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Expected Output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fco3t8cwij6u6vwc342c8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fco3t8cwij6u6vwc342c8.png" alt=" " width="557" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Remove Volumes (Optional)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;By default, volumes are not removed when tearing down the application to allow you to retain your data. If you want to remove the volumes as well, run:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnb7ichlr022huqstk5zb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnb7ichlr022huqstk5zb.png" alt=" " width="539" height="106"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Expected Output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe8zl41j0k57e7t93o7im.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe8zl41j0k57e7t93o7im.png" alt=" " width="545" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this hands-on guide, you learned how to use &lt;strong&gt;Docker Compose&lt;/strong&gt; to define, build, and run a &lt;strong&gt;multi-container application&lt;/strong&gt;. We explored how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Set up and configure services&lt;/strong&gt; using &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start the app&lt;/strong&gt; and view it in your browser.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easily tear down&lt;/strong&gt; the app when done.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker Compose makes it easy to work with multiple containers, saving time and effort when managing complex applications. This workflow is essential for modern development, and now you’re equipped to run your own multi-container Docker applications.&lt;/p&gt;

</description>
      <category>maryajayi</category>
      <category>cloudcomputing</category>
      <category>nexedge</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How to Build, Tag, and Push Docker Images to Docker Hub</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Fri, 10 Oct 2025 21:39:51 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/how-to-build-tag-and-push-docker-images-to-docker-hub-1660</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/how-to-build-tag-and-push-docker-images-to-docker-hub-1660</guid>
      <description>&lt;p&gt;In this blog, we’ll walk through the process of building, tagging, and pushing a Docker image to Docker Hub. We will also troubleshoot some common errors encountered during this process.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lab 1: Building the Docker Image&lt;/li&gt;
&lt;li&gt;Lab 2: Tagging the Docker Image&lt;/li&gt;
&lt;li&gt;Lab 3: Pushing the Image to Docker Hub&lt;/li&gt;
&lt;li&gt;Troubleshooting Common Errors&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Lab 1: Building the Docker Image&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Build the Image&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this first step, we are building the Docker image from a Dockerfile in the &lt;code&gt;Electro&lt;/code&gt; project folder. The &lt;code&gt;-t&lt;/code&gt; flag is used to tag the image with a version name.&lt;/p&gt;

&lt;p&gt;Run the following command in your PowerShell or terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhqc4ua2ceyf631z4yii.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhqc4ua2ceyf631z4yii.png" alt=" " width="520" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68sjrg8opim5xv2x4k19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F68sjrg8opim5xv2x4k19.png" alt=" " width="674" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o0cjie12fc0bb6sejq5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6o0cjie12fc0bb6sejq5.png" alt=" " width="800" height="39"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Lab 2: Tagging the Docker Image&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now that the image is built, it’s time to tag it properly to push it to Docker Hub.&lt;/p&gt;

&lt;p&gt;The image we built locally is &lt;code&gt;electro:v1&lt;/code&gt;. We now need to tag it for our Docker Hub repository under the username &lt;code&gt;theodora22&lt;/code&gt;. Here’s the command to tag the image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8vmlrz4aaqa9ygy503tb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8vmlrz4aaqa9ygy503tb.png" alt=" " width="518" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You should not see any output after running this command, which means the image has been tagged successfully. You can verify the tagging by running:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhqu35h43srqe79ruohn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhqu35h43srqe79ruohn.png" alt=" " width="507" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Example Output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyinza0plpotx11yhlxdq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyinza0plpotx11yhlxdq.png" alt=" " width="546" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; Remember to create a repository first on docker hub before tagging the docker image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftr0sv40gaoblw46s54zi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftr0sv40gaoblw46s54zi.png" alt=" " width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Lab 3: Pushing the Image to Docker Hub&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, let’s push the tagged image to Docker Hub.&lt;/p&gt;

&lt;p&gt;Run the following command to push the image to your Docker Hub repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqknhlpn08onh3j52ksq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsqknhlpn08onh3j52ksq.png" alt=" " width="493" height="102"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Expected Output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg4mbdj6f944w9cmp76ns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg4mbdj6f944w9cmp76ns.png" alt=" " width="687" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpjlivu3eqhp01k0f4gm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpjlivu3eqhp01k0f4gm.png" alt=" " width="800" height="541"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Troubleshooting Common Errors&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Error: Tag does not exist&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3sp7klar40zofjpy9ryt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3sp7klar40zofjpy9ryt.png" alt=" " width="528" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This error occurs if the image isn’t tagged correctly or hasn’t been built yet. Ensure the image exists locally by checking with:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fopegb9s6o0fmfa2xupt9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fopegb9s6o0fmfa2xupt9.png" alt=" " width="522" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then tag the image correctly:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gv9vxc4o6nge5sv7vj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gv9vxc4o6nge5sv7vj4.png" alt=" " width="537" height="108"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And retry pushing.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In this lab, we learned how to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build a Docker image using a &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Tag the image appropriately to push it to Docker Hub.&lt;/li&gt;
&lt;li&gt;Push the image to Docker Hub, making it available to others or for use in production.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Docker simplifies the process of building and deploying applications across various environments.&lt;/p&gt;

</description>
      <category>maryajayi</category>
      <category>cloudcomputing</category>
      <category>tutorial</category>
      <category>nexedge</category>
    </item>
    <item>
      <title>Build and Run Your First Container</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Mon, 29 Sep 2025 04:54:47 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/build-and-run-your-first-container-hm2</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/build-and-run-your-first-container-hm2</guid>
      <description>&lt;p&gt;Containerization has changed how software is developed, deployed, and managed. Docker allows developers to package applications with all dependencies into portable containers. This blog shows hands-on experience with Docker, from installation to running a frontend app.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lab 1: Installing Docker&lt;/li&gt;
&lt;li&gt;Lab 2: Running Your First Container&lt;/li&gt;
&lt;li&gt;Step 1: Clone Sample Application&lt;/li&gt;
&lt;li&gt;Step 2: Explore the Dockerfile&lt;/li&gt;
&lt;li&gt;Step 3: Build the Docker Image&lt;/li&gt;
&lt;li&gt;Step 4: Run the Container&lt;/li&gt;
&lt;li&gt;Step 5: Access the application&lt;/li&gt;
&lt;li&gt;Step 6: Stop the Container&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lab 1: Installing Docker
&lt;/h2&gt;

&lt;p&gt;Download Docker Desktop &lt;/p&gt;

&lt;p&gt;Docker Desktop includes the Docker Engine, CLI, and Docker Compose, providing everything you need to build and run containers locally.&lt;br&gt;
Go to the &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;https://www.docker.com/&lt;/a&gt;&lt;br&gt;
 and download Docker Desktop for your operating system.&lt;/p&gt;

&lt;p&gt;Run the installer and follow the on-screen instructions for your platform. After installation, restart your computer if required.&lt;/p&gt;

&lt;p&gt;This process sets up Docker’s core components and ensures that your system is ready to manage containers.&lt;/p&gt;

&lt;p&gt;Verify Installation&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figh1dj8zpwtaa7vn01bm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Figh1dj8zpwtaa7vn01bm.png" alt=" " width="558" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Output&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbil0iv9yn9pbsq3luynp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbil0iv9yn9pbsq3luynp.png" alt=" " width="427" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These commands confirm that Docker and Docker Compose are installed and ready to use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lab 2: Running Your First Container
&lt;/h2&gt;

&lt;p&gt;This step verifies that Docker can pull images from Docker Hub and run them as containers on your system.&lt;/p&gt;

&lt;p&gt;Run a simple test container:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ghl0rkdd94lmh9qsc79.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ghl0rkdd94lmh9qsc79.png" alt=" " width="442" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Expected Output:&lt;br&gt;
Docker will download a small test image and display a success message.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbftbn8cuzm648xon5c5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxbftbn8cuzm648xon5c5.png" alt=" " width="609" height="205"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Clone Sample Application
&lt;/h2&gt;

&lt;p&gt;Cloning the repository gives you all the source code and the Dockerfile needed to build your containerized application.&lt;/p&gt;

&lt;p&gt;Clone the sample application repository:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpi1qfgzruy3d61qeeqc3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpi1qfgzruy3d61qeeqc3.png" alt=" " width="439" height="78"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Explore the Dockerfile
&lt;/h2&gt;

&lt;p&gt;The Dockerfile acts as a blueprint that tells Docker how to set up your container consistently.&lt;br&gt;
The Dockerfile defines the environment for your app:&lt;br&gt;
Base image: node:22-alpine&lt;/p&gt;

&lt;p&gt;Working directory: /app&lt;/p&gt;

&lt;p&gt;Copy application files and install dependencies&lt;/p&gt;

&lt;p&gt;Build the app and remove unnecessary files&lt;/p&gt;

&lt;p&gt;Expose port 3000 and serve the app using serve -s build&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pa1uwxk5a9qdftf6nqh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pa1uwxk5a9qdftf6nqh.png" alt=" " width="800" height="464"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Build the Docker Image
&lt;/h2&gt;

&lt;p&gt;Building an image packages your app and all its dependencies into a single, portable unit that can run anywhere Docker is installed.&lt;/p&gt;

&lt;p&gt;Build the Docker image using:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bvvlvfeewyreyaurl3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8bvvlvfeewyreyaurl3r.png" alt=" " width="423" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Expected Output&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts5qz35ybf3h1tlpqps4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fts5qz35ybf3h1tlpqps4.png" alt=" " width="547" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Run the Container
&lt;/h2&gt;

&lt;p&gt;Running a container launches your application in an isolated environment. Port 3000 is mapped so you can access the app from your browser.&lt;/p&gt;

&lt;p&gt;Run your image as a container:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mxxr9vzjdzrel1x9gw5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4mxxr9vzjdzrel1x9gw5.png" alt=" " width="426" height="52"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomkh6656319xvfy8s24z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fomkh6656319xvfy8s24z.png" alt=" " width="610" height="173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Optionally &lt;/p&gt;

&lt;p&gt;In Docker Desktop, go to the Images tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03y3gmqxdobxdachjs4z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F03y3gmqxdobxdachjs4z.png" alt=" " width="800" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next to your image, select Run.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ilgzc954fubk5h83in2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ilgzc954fubk5h83in2.png" alt=" " width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Expand the Optional settings.&lt;/p&gt;

&lt;p&gt;In Host port, specify 8089&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzou4o48a0yr9ylu0843.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzou4o48a0yr9ylu0843.png" alt=" " width="635" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Select Run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Access the Application
&lt;/h2&gt;

&lt;p&gt;This confirms that your containerized application is running correctly and accessible locally.&lt;/p&gt;

&lt;p&gt;Open a browser and go to:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvs68kttm7xfmeublt4gy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvs68kttm7xfmeublt4gy.png" alt=" " width="343" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foou8269q0zld81jgsx1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foou8269q0zld81jgsx1n.png" alt=" " width="785" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Optionally&lt;/p&gt;

&lt;p&gt;Select the link next to your container in Docker Desktop to access the application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3itaqcb0v01i1t4edbqu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3itaqcb0v01i1t4edbqu.png" alt=" " width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Stop the Container
&lt;/h2&gt;

&lt;p&gt;Stopping the container frees system resources. docker ps shows which containers are currently running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiipd3b6gvyhu8nuzxkij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiipd3b6gvyhu8nuzxkij.png" alt=" " width="392" height="63"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;List running containers and stop yours&lt;/p&gt;

&lt;p&gt;Optionally&lt;/p&gt;

&lt;p&gt;To stop the container in Docker Desktop, go to the Containers tab and select the Stop icon in the Actions column of your container.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zgvlq880zi2hrqhj7zq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zgvlq880zi2hrqhj7zq.png" alt=" " width="800" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this lab, you learned how to install Docker, build a container, and run it locally. You now understand how Docker packages applications and their dependencies, making them portable and consistent across environments.&lt;/p&gt;

</description>
      <category>maryajayi</category>
      <category>cloudcomputing</category>
      <category>nexedgetechnologies</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Using SSH Keys on Windows: Fixing “Unprotected Private Key File” Errors</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Sun, 31 Aug 2025 09:18:51 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/using-ssh-keys-on-windows-fixing-unprotected-private-key-file-errors-1d07</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/using-ssh-keys-on-windows-fixing-unprotected-private-key-file-errors-1d07</guid>
      <description>&lt;p&gt;When you use SSH to connect to an EC2 instance, the client checks the permissions on your private key file (.pem).&lt;/p&gt;

&lt;p&gt;On Linux/macOS, this is enforced with chmod 400 (file is only readable by the owner).&lt;/p&gt;

&lt;p&gt;On Windows with OpenSSH, the same check is enforced via NTFS file permissions (ACLs).&lt;/p&gt;

&lt;p&gt;If the file is accessible to other groups like Authenticated Users, Users, or Everyone, SSH will refuse to use it and you’ll see:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F89q34g7ljn6ewv35m1j2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F89q34g7ljn6ewv35m1j2.png" alt=" " width="768" height="196"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The core concept
&lt;/h2&gt;

&lt;p&gt;A private key must be owned by you and only readable by you.&lt;/p&gt;

&lt;p&gt;On Windows, this is controlled by ACLs (Access Control Lists), not chmod.&lt;/p&gt;

&lt;p&gt;To fix the issue, you must take ownership of the file and restrict its ACLs so only your account (plus SYSTEM/Administrators) can read it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Take ownership
&lt;/h2&gt;

&lt;p&gt;If you downloaded or copied the file from another system, ownership may not match your account. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;takeown /F "D:\3-tier-web-arch\nfs-key.pem"&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Remove inheritance
&lt;/h2&gt;

&lt;p&gt;Prevent the file from inheriting broad permissions from the folder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;icacls "D:\3-tier-web-arch\nfs-key.pem" /inheritance:r&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Remove broad groups
&lt;/h2&gt;

&lt;p&gt;Remove default Windows groups that make the file accessible to others&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;icacls "D:\3-tier-web-arch\nfs-key.pem" /remove:g "Authenticated Users" "Users" "Everyone"&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Grant only necessary access
&lt;/h2&gt;

&lt;p&gt;Give your account read permission, and (optionally) keep SYSTEM and Administrators with full control&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;icacls "D:\3-tier-web-arch\nfs-key.pem" /grant "DESKTOP-ABCD\Amanda:(R)"&lt;br&gt;
icacls "D:\3-tier-web-arch\nfs-key.pem" /grant "NT AUTHORITY\SYSTEM:(F)" "BUILTIN\Administrators:(F)"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;If you want to do this in one clean command&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;icacls "D:\3-tier-web-arch\nfs-key.pem" /inheritance:r /grant:r `&lt;br&gt;
  "DESKTOP-ABCD\Amanda:(R)" "NT AUTHORITY\SYSTEM:(F)" "BUILTIN\Administrators:(F)"&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Verify
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;icacls "D:\3-tier-web-arch\nfs-key.pem"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Expected output&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DESKTOP-ABCD\Amanda:(R)&lt;br&gt;
BUILTIN\Administrators:(F)&lt;br&gt;
NT AUTHORITY\SYSTEM:(F)&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6:Connect to EC2
&lt;/h2&gt;

&lt;p&gt;Now you can connect&lt;br&gt;
ssh -i "D:\3-tier-web-arch\nfs-key.pem" ec2-user@&lt;/p&gt;

&lt;h2&gt;
  
  
  Best practice is to Store keys in ~.ssh
&lt;/h2&gt;

&lt;p&gt;For convenience, place the key in your .ssh folder&lt;br&gt;
&lt;strong&gt;mkdir "$env:USERPROFILE.ssh" -Force&lt;br&gt;
copy "D:\3-tier-web-arch\nfs-key.pem" "$env:USERPROFILE.ssh\nfs-key.pem"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Then create a config file (~/.ssh/config) so you can connect with just&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ssh my-ec2&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;SSH enforces strict private key security. On Windows, that means taking ownership of the PEM file and restricting its ACLs so only you (and optionally SYSTEM/Administrators) can read it. This is the Windows equivalent of chmod 400 on Linux.&lt;/p&gt;

&lt;h2&gt;
  
  
  Note- Run commands on Powershell as Administrator and then connect to EC2 Instance on VScode  powershell Terminal or powershell on windows.
&lt;/h2&gt;

</description>
      <category>maryajayi</category>
      <category>ai</category>
      <category>beginners</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to Host a Static Website on Azure Blob Storage</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Sat, 17 May 2025 13:25:02 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/how-to-host-a-static-website-on-azure-blob-storage-egk</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/how-to-host-a-static-website-on-azure-blob-storage-egk</guid>
      <description>&lt;p&gt;Hosting a static website on Azure Blob Storage is a simple, cost-effective way to make your web content accessible globally. In this tutorial, I'll show you how to deploy a static website using Azure Blob Storage, starting with a sample website I downloaded and edited using VS Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
Prerequisites
&lt;/li&gt;
&lt;li&gt;
Prepare Your Static Website
&lt;/li&gt;
&lt;li&gt;
Create an Azure Storage Account
&lt;/li&gt;
&lt;li&gt;
Enable Static Website Hosting
&lt;/li&gt;
&lt;li&gt;
Upload Website Files
&lt;/li&gt;
&lt;li&gt;
Access Your Website
&lt;/li&gt;
&lt;li&gt;
Troubleshooting Tips
&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Prerequisites
&lt;/h1&gt;

&lt;p&gt;Before we get started, make sure you have:&lt;/p&gt;

&lt;p&gt;An active Azure account.&lt;/p&gt;

&lt;p&gt;Visual Studio Code installed.&lt;/p&gt;

&lt;p&gt;A sample static website ready to deploy.&lt;/p&gt;

&lt;p&gt;Firstly, you download the sample static website from Luther, unzip the file, and saved it to a preferred location on your local machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxw33os8g57p9zb997im.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxw33os8g57p9zb997im.png" alt=" " width="800" height="538"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuj75m0o71mwya6uem2xi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuj75m0o71mwya6uem2xi.png" alt=" " width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Prepare Your Static Website
&lt;/h1&gt;

&lt;p&gt;Using VS Code, open the sample website files and make the necessary edits on index.html.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc55yvkj5l61496rp09i8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc55yvkj5l61496rp09i8.png" alt=" " width="638" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4tyxote57wp5lulm1ixr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4tyxote57wp5lulm1ixr.png" alt=" " width="800" height="603"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1mymjgv7u47pqjkzhta.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1mymjgv7u47pqjkzhta.png" alt=" " width="608" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Edit the White parts like name and intro and then Save.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fio56idptuyla3tps9cyp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fio56idptuyla3tps9cyp.png" alt=" " width="618" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run the website by selecting Run without debugging in VS Code to open the website in your browser and verify the content. Once you’re satisfied, we’ll proceed to deploy the site to Azure.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzicyfdmhx6eoa4sz7w1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzicyfdmhx6eoa4sz7w1z.png" alt=" " width="800" height="517"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Make sure your website works locally before deploying it on Azure&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Create an Azure Storage Account
&lt;/h1&gt;

&lt;p&gt;Log in to the Azure Portal and create a new Storage Account:&lt;/p&gt;

&lt;p&gt;Click Create a resource &amp;gt; Storage &amp;gt; Storage account.&lt;/p&gt;

&lt;p&gt;Fill in the required fields: subscription, resource group, storage account name, region, etc.&lt;/p&gt;

&lt;p&gt;Review and create the storage account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnbpqnpeixsvl8g8g3ajc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnbpqnpeixsvl8g8g3ajc.png" alt=" " width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2ml042wxe4trzchqevo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2ml042wxe4trzchqevo.png" alt=" " width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzrix8c47pb7f7ypdaz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkzrix8c47pb7f7ypdaz1.png" alt=" " width="800" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fill in the Basics tab&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F669ukdd9pgl5llft2c3q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F669ukdd9pgl5llft2c3q.png" alt=" " width="800" height="749"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Enable Static Website Hosting
&lt;/h1&gt;

&lt;p&gt;Once the storage account is created:&lt;/p&gt;

&lt;p&gt;Navigate to your storage account by going to resource.&lt;/p&gt;

&lt;p&gt;In the left sidebar, under Settings, select Static website or on the right side under capabilities.&lt;/p&gt;

&lt;p&gt;Enable Static website hosting.&lt;/p&gt;

&lt;p&gt;Specify your index document name (index.html) and error document path (error.html).&lt;/p&gt;

&lt;p&gt;Save your changes.&lt;/p&gt;

&lt;p&gt;Azure will automatically create a $web container to store your website files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkjepdwf4lnp67wzkaq7a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkjepdwf4lnp67wzkaq7a.png" alt=" " width="800" height="439"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type in index.html — This is the main page of your website.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Type in error.html — This page will be displayed if a user tries to access a URL that doesn’t exist on your site.&lt;/strong&gt;**&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdx78debj0c1637vg7blj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdx78debj0c1637vg7blj.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fila3l37lh6dvtw2gdruz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fila3l37lh6dvtw2gdruz.png" alt=" " width="800" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Copy the Primary endpoint URL and open it in your browser. At this point, you won’t see any website content because the files haven’t been uploaded yet. Next, we’ll upload our web files to Azure to make the site live&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1k0fb9zfao7rc70pdb03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1k0fb9zfao7rc70pdb03.png" alt=" " width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6udnx4ma3v8dt2vimrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6udnx4ma3v8dt2vimrg.png" alt=" " width="800" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Upload Website Files
&lt;/h1&gt;

&lt;p&gt;Next, upload your local website files to the $web container:&lt;/p&gt;

&lt;p&gt;In your storage account, go to Containers.&lt;/p&gt;

&lt;p&gt;Open the $web container.&lt;/p&gt;

&lt;p&gt;Click Upload and select all your website files and folders (e.g., index.html, error.html, CSS files, images).&lt;/p&gt;

&lt;p&gt;Upload them to Azure.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2khojlgxxfejc9gic0l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2khojlgxxfejc9gic0l.png" alt=" " width="800" height="631"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohctppwa9fvf4nby1nfr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohctppwa9fvf4nby1nfr.png" alt=" " width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmmosdvy902muge6mtrcq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmmosdvy902muge6mtrcq.png" alt=" " width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Access Your Website
&lt;/h1&gt;

&lt;p&gt;After uploading, go back to the Static website page in the Azure Portal.&lt;/p&gt;

&lt;p&gt;Copy the Primary endpoint URL and paste it into your browser.&lt;/p&gt;

&lt;p&gt;Your static website should now be live and accessible from anywhere in the world!&lt;/p&gt;

&lt;p&gt;Example URL format:&lt;br&gt;
&lt;a href="https://portfoliowebsite123.z13.web.core.windows.net/index.html" rel="noopener noreferrer"&gt;https://portfoliowebsite123.z13.web.core.windows.net/index.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fll1zj94od64dee8uxxz4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fll1zj94od64dee8uxxz4.png" alt=" " width="800" height="558"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Now  everyone can see it, Bingo!!!!!&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Troubleshooting Tips
&lt;/h1&gt;

&lt;p&gt;No content showing? Ensure your files are correctly uploaded in the $web container.&lt;/p&gt;

&lt;p&gt;Page not found errors? Check your index and error document names in the static website settings.&lt;/p&gt;

&lt;p&gt;File paths broken? Make sure all relative links in your HTML files are correct.&lt;/p&gt;

&lt;p&gt;Cache issues? Try clearing your browser cache or open the page in an incognito window.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Hosting static websites on Azure Blob Storage is fast, affordable, and scalable. By following these steps, you can quickly get your site online without managing a web server.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Creating and Connecting to a Linux Virtual Machine Scale Set (VMSS) on Azure</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Tue, 06 May 2025 23:48:41 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/creating-and-connecting-to-a-linux-virtual-machine-scale-set-vmss-on-azure-45b1</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/creating-and-connecting-to-a-linux-virtual-machine-scale-set-vmss-on-azure-45b1</guid>
      <description>&lt;p&gt;Azure Virtual Machine Scale Sets (VMSS) are a great solution for managing and scaling a large number of identical virtual machines in Azure. With VMSS, you can automatically scale your infrastructure based on demand, ensuring high availability and load balancing for your applications. In this guide, we'll go through the steps to create a Linux VMSS, configure it, and connect to the individual instances using SSH.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What is a Virtual Machine Scale Set (VMSS)?&lt;/li&gt;
&lt;li&gt;Create a Linux VMSS in Azure&lt;/li&gt;
&lt;li&gt;Generate SSH Keys&lt;/li&gt;
&lt;li&gt;Connect to an Instance in the VMSS Using SSH&lt;/li&gt;
&lt;li&gt;Scaling and Load Balancing&lt;/li&gt;
&lt;li&gt;Troubleshooting&lt;/li&gt;
&lt;li&gt;
Spot VMs: Cost-effective but Preemptible
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is a Virtual Machine Scale Set (VMSS)?
&lt;/h2&gt;

&lt;p&gt;A Virtual Machine Scale Set is an Azure resource that allows you to deploy and manage a set of identical virtual machines. VMSS makes it easier to:&lt;/p&gt;

&lt;p&gt;Automatically scale VM instances up or down based on load.&lt;/p&gt;

&lt;p&gt;Ensure high availability across multiple availability zones.&lt;/p&gt;

&lt;p&gt;Simplify management by handling updates and upgrades to multiple VMs at once.&lt;/p&gt;

&lt;p&gt;With VMSS, you can quickly set up a fleet of identical VMs that are load-balanced and auto-scalable, which is perfect for web applications and services that need to scale dynamically.&lt;/p&gt;

&lt;h1&gt;
  
  
  Create a Linux VMSS in Azure
&lt;/h1&gt;

&lt;p&gt;Let’s walk through the steps of creating a Linux Virtual Machine Scale Set in Azure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Log in to Azure Portal
&lt;/h2&gt;

&lt;p&gt;First, log in to the Azure Portal with your Microsoft account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frj22opbk5yq1q28h0gxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frj22opbk5yq1q28h0gxg.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Create a Virtual Machine Scale Set
&lt;/h2&gt;

&lt;p&gt;In the Azure Portal, click “Create a resource” from the sidebar.&lt;/p&gt;

&lt;p&gt;Search for Virtual Machine Scale Set.&lt;/p&gt;

&lt;p&gt;Click Create to start the setup process.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqkrgmo3d3bodx6t9i9l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqkrgmo3d3bodx6t9i9l.png" alt=" " width="501" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fttly0yq9n1nv7xifhtdp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fttly0yq9n1nv7xifhtdp.png" alt=" " width="793" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbwegpuvm3hajhzavv15.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcbwegpuvm3hajhzavv15.png" alt=" " width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Configure the Basic Settings
&lt;/h2&gt;

&lt;p&gt;In the Basics tab:&lt;/p&gt;

&lt;p&gt;Subscription: Select your subscription.&lt;/p&gt;

&lt;p&gt;Resource Group: Create a new one or select an existing group.&lt;/p&gt;

&lt;p&gt;Region: Choose the region where you want to deploy the scale set (e.g., East US).&lt;/p&gt;

&lt;p&gt;VMSS Name: Name your VMSS (e.g., MyLinuxVMSS).&lt;/p&gt;

&lt;p&gt;Availability zone: You can choose none or any zone you want&lt;/p&gt;

&lt;p&gt;Orchestration mode: Uniform- This means Azure will automatically create and manage identical virtual machines for you, based on a single configuration. It's easier to use and perfect when you want all VMs to be the same.&lt;/p&gt;

&lt;p&gt;Security type: Standard&lt;/p&gt;

&lt;p&gt;Scaling options- Manual, also &lt;strong&gt;configure scaling options&lt;/strong&gt; to enable predictive auto scaling. It doesn’t make any scaling changes—it just helps you visualize what auto scaling might look like in the future. &lt;strong&gt;Scale-In Policy&lt;/strong&gt;-Choose how Azure decides which VM instances to delete first when scaling in (reducing the number of VMs).&lt;br&gt;
You can prioritize based on the newest, oldest, or custom rules.&lt;/p&gt;

&lt;p&gt;Image: Choose Ubuntu 20.04 LTS (or any other Linux distribution you prefer).&lt;/p&gt;

&lt;p&gt;Instance Size: Choose an appropriate size (e.g., Standard B1ms for testing).&lt;/p&gt;

&lt;p&gt;Instance count:2 or any size you want&lt;/p&gt;

&lt;p&gt;Authentication Type: Choose SSH public key.&lt;/p&gt;

&lt;p&gt;Username: Create a user (e.g., azureuser).&lt;/p&gt;

&lt;p&gt;SSH Public Key: You’ll add this later after generating the key pair.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xedii5d7b50tov9i6az.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xedii5d7b50tov9i6az.png" alt=" " width="800" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuld8xkcge5x3bp8x4dn1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuld8xkcge5x3bp8x4dn1.png" alt=" " width="777" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8v3wfg2w3fw11y6odyv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8v3wfg2w3fw11y6odyv.png" alt=" " width="765" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0v3rf4fwhok7wst4340.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0v3rf4fwhok7wst4340.png" alt=" " width="697" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Configure the Disk Settings
&lt;/h2&gt;

&lt;p&gt;In the Disks tab:&lt;/p&gt;

&lt;p&gt;OS Disk Type: Choose Standard SSD or Premium SSD, depending on your requirements.&lt;/p&gt;

&lt;p&gt;Data Disks: You can also add data disks if your VMSS requires additional storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Leave everything at default&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctxdcj4rxft9kwlt5yyj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fctxdcj4rxft9kwlt5yyj.png" alt=" " width="800" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Configure the VMSS Networking
&lt;/h2&gt;

&lt;p&gt;In the Networking tab:&lt;/p&gt;

&lt;p&gt;Virtual Network: Select Default or create a new network.&lt;/p&gt;

&lt;p&gt;Subnet: Select Default or create a new subnet.&lt;/p&gt;

&lt;p&gt;Network Interface Card (NIC): Make sure to set your NIC properly to connect the VM instances to the network.&lt;/p&gt;

&lt;p&gt;Public IP: Choose Enabled to ensure each VM instance has a public IP for external access.&lt;/p&gt;

&lt;p&gt;Allow selected ports: Make sure to allow SSH (port 22) for secure access and HTTP (port 80) for web traffic.&lt;/p&gt;

&lt;p&gt;This ensures that SSH connections to manage your VMs and HTTP traffic for the web server are allowed.&lt;/p&gt;

&lt;p&gt;Load Balancer:&lt;/p&gt;

&lt;p&gt;Choose Azure Load Balancer to distribute traffic evenly across all VM instances for better performance and availability.&lt;/p&gt;

&lt;p&gt;Click Create a new load balancer, give it a name (e.g., MyVMSSLoadBalancer).&lt;/p&gt;

&lt;p&gt;Set the IP type to Public.&lt;/p&gt;

&lt;p&gt;Choose TCP for Protocol to handle traffic.&lt;/p&gt;

&lt;p&gt;Click Create to set up the load balancer.&lt;/p&gt;

&lt;p&gt;This will ensure that incoming traffic is distributed evenly to your VM instances, improving your application’s scalability and reliability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2atm671oy4akn6xjdup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2atm671oy4akn6xjdup.png" alt=" " width="787" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flk1wdgbsg22zfaeb994j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flk1wdgbsg22zfaeb994j.png" alt=" " width="800" height="765"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F057fxbfhcgonv8tqpdd9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F057fxbfhcgonv8tqpdd9.png" alt=" " width="781" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4220b3yjhuy7qfbngl97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4220b3yjhuy7qfbngl97.png" alt=" " width="566" height="842"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Review + Create
&lt;/h2&gt;

&lt;p&gt;Review the configuration and click Create to deploy the Virtual Machine Scale Set. Azure will start the deployment, and it will take a few minutes to set up the resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl07jzivi7n5m05lj9587.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl07jzivi7n5m05lj9587.png" alt=" " width="729" height="747"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsfk11gyqkl09x94etrvh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsfk11gyqkl09x94etrvh.png" alt=" " width="568" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rbu85ir0ktjwxjtwk1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8rbu85ir0ktjwxjtwk1n.png" alt=" " width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Go to Instances and view your two virtual machines&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0jd85vbm77jlk3wyrs8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh0jd85vbm77jlk3wyrs8.png" alt=" " width="579" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ac0h5s3499j1ivo5o36.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8ac0h5s3499j1ivo5o36.png" alt=" " width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Connect to an Instance in the VMSS Using SSH
&lt;/h1&gt;

&lt;p&gt;Now that the scale set is deployed, let’s connect to an instance using SSH.&lt;/p&gt;

&lt;p&gt;Step 1: Find the Public IP Address of Your VMSS&lt;/p&gt;

&lt;p&gt;Under Instances, you’ll see a list of your VM instances.&lt;/p&gt;

&lt;p&gt;Find the Public IP address of one of the instances.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffya02i7u5ood8i2yrvqt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffya02i7u5ood8i2yrvqt.png" alt=" " width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: SSH into the Instance
&lt;/h2&gt;

&lt;p&gt;Use the following SSH command to connect to the instance.&lt;/p&gt;

&lt;p&gt;ssh -i ~/.ssh/myVMSSKey azureuser@&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fglq2oj793fiv6ei7icaw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fglq2oj793fiv6ei7icaw.png" alt=" " width="800" height="621"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4czo7gh7yivbvnkjlijq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4czo7gh7yivbvnkjlijq.png" alt=" " width="714" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To connect to all instances within the Virtual Machine Scale Set (VMSS), you can use the frontend IP address of the load balancer. This ensures that traffic is evenly distributed across all VM instances in the scale set.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fonl5jt0oixr0u8k65iq3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fonl5jt0oixr0u8k65iq3.png" alt=" " width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use the following SSH command to connect to all instances.&lt;br&gt;
 ssh -i C:\Users\hp\Downloads\MyLinuxVMSS_key.pem &lt;a href="mailto:azureuser@20.169.225.135"&gt;azureuser@20.169.225.135&lt;/a&gt; -p 50000&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwu13n921amuk3s376byg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwu13n921amuk3s376byg.png" alt=" " width="800" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Extra
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Autoscaling&lt;/strong&gt;&lt;br&gt;
You can enable autoscaling to automatically adjust the number of VM instances based on CPU usage, memory usage, or other metrics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0yvx1hnpwela3yo5dv4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu0yvx1hnpwela3yo5dv4.png" alt=" " width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Spot VMs: Cost-effective but Preemptible
&lt;/h1&gt;

&lt;p&gt;Spot VMs are preemptible virtual machines that offer significant cost savings compared to regular VMs in Azure. However, they come with a risk: they can be terminated by Azure when there is high demand for capacity. Spot VMs are ideal for workloads that are flexible and can tolerate interruptions.&lt;/p&gt;

&lt;p&gt;Key Features of Spot VMs:&lt;br&gt;
Cost-effective: Up to 90% cheaper than regular VMs.&lt;/p&gt;

&lt;p&gt;Interruptible: Azure can terminate these VMs with little notice when resources are in high demand.&lt;/p&gt;

&lt;p&gt;Best for flexible workloads: Suitable for jobs like batch processing or testing, where occasional interruptions are acceptable.&lt;/p&gt;

&lt;p&gt;By leveraging Spot VMs, you can save significantly on Azure compute costs, but it's important to plan workloads that can tolerate interruptions and be terminated without affecting your overall application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0258b3xvr3off7iy7k5t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0258b3xvr3off7iy7k5t.png" alt=" " width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>maryajayi</category>
      <category>beginners</category>
      <category>devops</category>
      <category>azure</category>
    </item>
    <item>
      <title>Mastering Azure: Core Architectural Components Explained</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Sat, 19 Apr 2025 16:59:14 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/mastering-azure-core-architectural-components-explained-28g6</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/mastering-azure-core-architectural-components-explained-28g6</guid>
      <description>&lt;p&gt;Microsoft Azure is one of the leading cloud platforms, providing businesses with a wide range of services to build, manage, and deploy applications on a global scale. Azure’s architecture is designed to offer flexibility, scalability, security, and high availability. Understanding the core components of Azure’s architecture is essential for designing and implementing efficient cloud-based solutions.&lt;/p&gt;

&lt;p&gt;This guide explores the eight core architectural components of Azure, including compute, storage, networking, identity, and monitoring — giving you the foundation to build secure, high-performing applications on Azure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
Azure Regions and Availability Zones
&lt;/li&gt;
&lt;li&gt;
Compute Services

&lt;ul&gt;
&lt;li&gt;
Azure Virtual Machines
&lt;/li&gt;
&lt;li&gt;
Azure App Service
&lt;/li&gt;
&lt;li&gt;
Azure Kubernetes Service
&lt;/li&gt;
&lt;li&gt;
Azure Functions
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Storage Services

&lt;ul&gt;
&lt;li&gt;
Azure Blob Storage
&lt;/li&gt;
&lt;li&gt;
Azure Files
&lt;/li&gt;
&lt;li&gt;
Azure Disk Storage
&lt;/li&gt;
&lt;li&gt;
Azure Table Storage
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Networking

&lt;ul&gt;
&lt;li&gt;
Azure Virtual Network
&lt;/li&gt;
&lt;li&gt;
Azure Load Balancer
&lt;/li&gt;
&lt;li&gt;
Azure ExpressRoute
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Identity and Access Management

&lt;ul&gt;
&lt;li&gt;
Azure Active Directory
&lt;/li&gt;
&lt;li&gt;
Role-Based Access Control
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Monitoring and Management

&lt;ul&gt;
&lt;li&gt;
Azure Monitor
&lt;/li&gt;
&lt;li&gt;
Azure Application Insights
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Security and Compliance

&lt;ul&gt;
&lt;li&gt;
Azure Security Center
&lt;/li&gt;
&lt;li&gt;
Azure Key Vault
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Databases

&lt;ul&gt;
&lt;li&gt;
Azure SQL Database
&lt;/li&gt;
&lt;li&gt;
Cosmos DB
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Conclusion
&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Azure Regions and Availability Zones
&lt;/h1&gt;

&lt;p&gt;Azure’s global infrastructure is organized into regions and availability zones to provide high availability, fault tolerance, and redundancy.&lt;/p&gt;

&lt;h1&gt;
  
  
  Azure Regions
&lt;/h1&gt;

&lt;p&gt;A region is a geographical area containing a set of data centers.&lt;br&gt;
Azure currently operates in over 60 regions across the globe, making it one of the most widely available cloud platforms.&lt;br&gt;
Each region is strategically located to meet compliance and data residency requirements.&lt;/p&gt;

&lt;h1&gt;
  
  
  Availability Zones
&lt;/h1&gt;

&lt;p&gt;Availability zones are physically separated data centers within a region.&lt;br&gt;
Each zone has its own power, cooling, and networking to prevent failures from affecting all zones.&lt;br&gt;
Deploying resources across multiple availability zones ensures redundancy and disaster recovery.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthwhbkrfih4nhemgejru.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fthwhbkrfih4nhemgejru.png" alt=" " width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Compute Services
&lt;/h1&gt;

&lt;p&gt;Azure provides a range of compute options to run applications and services at scale.&lt;/p&gt;

&lt;h1&gt;
  
  
  Azure Virtual Machines
&lt;/h1&gt;

&lt;p&gt;On-demand, scalable compute resources that allow you to run Windows and Linux-based workloads.&lt;br&gt;
Support for different machine sizes based on CPU, memory, and storage requirements.&lt;br&gt;
VMs can be configured for high availability by deploying them across availability zones.&lt;/p&gt;

&lt;h1&gt;
  
  
  Azure App Service
&lt;/h1&gt;

&lt;p&gt;A fully managed platform for building and hosting web apps, RESTful APIs, and mobile backends.&lt;br&gt;
Supports multiple programming languages such as .NET, Java, Node.js, Python, and PHP.&lt;/p&gt;

&lt;h1&gt;
  
  
  Azure Kubernetes Service
&lt;/h1&gt;

&lt;p&gt;Fully managed Kubernetes service that allows you to deploy and manage containerized applications.&lt;br&gt;
Supports scaling, monitoring, and orchestration of containers.&lt;/p&gt;

&lt;h1&gt;
  
  
  Azure Functions
&lt;/h1&gt;

&lt;p&gt;Serverless compute service that allows you to execute code in response to events without managing infrastructure.&lt;br&gt;
Ideal for event-driven applications and background processing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23uzk2j4iqqah3q4lal9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23uzk2j4iqqah3q4lal9.png" alt=" " width="267" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>tutorial</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>How to Create and Connect to a Linux VM Using a Public Key</title>
      <dc:creator>Theodora</dc:creator>
      <pubDate>Sat, 19 Apr 2025 15:48:09 +0000</pubDate>
      <link>https://forem.com/theodora_e6f61d02577a5f06/how-to-create-and-connect-to-a-linux-vm-using-a-public-key-34k0</link>
      <guid>https://forem.com/theodora_e6f61d02577a5f06/how-to-create-and-connect-to-a-linux-vm-using-a-public-key-34k0</guid>
      <description>&lt;h2&gt;
  
  
  How to Create and Connect to a Linux VM Using a Public Key
&lt;/h2&gt;

&lt;p&gt;Creating a Linux Virtual Machine (VM) and connecting to it via SSH using a public key is a secure and efficient method for managing cloud-based systems. This guide walks you through the entire process of creating a Linux VM in Azure and securely connecting to it using SSH keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
Create a Linux VM in Azure
&lt;/li&gt;
&lt;li&gt;
Generate SSH Private Key
&lt;/li&gt;
&lt;li&gt;
Connect to the Linux VM Using SSH
&lt;/li&gt;
&lt;li&gt;
Update the Server and Install a Web Server (Nginx)
&lt;/li&gt;
&lt;li&gt;
Troubleshooting
&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Create a Linux VM in Azure
&lt;/h2&gt;

&lt;p&gt;Before you can connect to a Linux VM using SSH, you need to create it. Follow the steps below to create the VM in &lt;strong&gt;Azure&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Log in to Azure Portal
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open the Azure Portal and sign in with your Microsoft account.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpjbmrpc79oxu6waaesu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmpjbmrpc79oxu6waaesu.png" alt="login page" width="373" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create a Virtual Machine
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In the &lt;strong&gt;Azure Portal&lt;/strong&gt;, click on &lt;strong&gt;"Create a resource"&lt;/strong&gt; in the left sidebar.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt; to start the VM creation process.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwcct9zqnld5o1mwqgj9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwcct9zqnld5o1mwqgj9.png" alt="creating a vm" width="705" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymngmshwpblm5n9wnb2f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymngmshwpblm5n9wnb2f.png" alt="creating a vm" width="754" height="738"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fill Out the Basics Tab
&lt;/h3&gt;

&lt;p&gt;Subscription: Select your subscription&lt;/p&gt;

&lt;p&gt;Resource Group: Create a new one or use an existing one&lt;/p&gt;

&lt;p&gt;VM Name: e.g., LinuxVM&lt;/p&gt;

&lt;p&gt;Region: Choose the closest location&lt;/p&gt;

&lt;p&gt;Availability options- No Infrastructure redundancy as i am not replicating the vm&lt;/p&gt;

&lt;p&gt;Security - Standard&lt;/p&gt;

&lt;p&gt;Image: Any Ubuntu distribution that you want&lt;/p&gt;

&lt;p&gt;Size: e.g., Standard B1s (suitable for testing) or any size&lt;/p&gt;

&lt;p&gt;Authentication Type: Select SSH public key&lt;/p&gt;

&lt;p&gt;Username: e.g., azureuser&lt;/p&gt;

&lt;p&gt;SSH Public Key: Generate new key pair&lt;/p&gt;

&lt;p&gt;Inbound port rules- Allow selected ports and select SSH(22) and HTTP(80). Open port 80 to access the IP address on a browser as a simple web server will be installed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodjxwd39ki9rkhxkwano.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fodjxwd39ki9rkhxkwano.png" alt="Basic tab" width="800" height="704"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4cbnjhn0zfwiomuzo3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs4cbnjhn0zfwiomuzo3a.png" alt="Basic tab" width="800" height="716"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvbpl23bl59a3sp4ea0v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvbpl23bl59a3sp4ea0v.png" alt="Basic tab" width="759" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure the Disks Tab
&lt;/h3&gt;

&lt;p&gt;OS disk type: Choose Standard SSD or Premium SSD depending on your needs&lt;/p&gt;

&lt;p&gt;Leave other options at default unless you have specific disk encryption or backup requirements&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F501wms4s1os2t7ifwd3y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F501wms4s1os2t7ifwd3y.png" alt="Disk tab" width="800" height="668"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure the Networking Tab
&lt;/h3&gt;

&lt;p&gt;Virtual Network: Use default or create a new one&lt;/p&gt;

&lt;p&gt;Subnet: Leave as default&lt;/p&gt;

&lt;p&gt;Public IP: Enabled&lt;/p&gt;

&lt;p&gt;NIC network security group: Choose Basic&lt;/p&gt;

&lt;p&gt;Select inbound ports:&lt;br&gt;
SSH (port 22) – to connect to the VM&lt;br&gt;
HTTP (port 80) – to access a web server via browser&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgld5tj1xia4gkq1lssjz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgld5tj1xia4gkq1lssjz.png" alt="Networking" width="778" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Generate SSH private Key
&lt;/h2&gt;

&lt;p&gt;Click Review + Create&lt;br&gt;
Azure will validate the configuration&lt;/p&gt;

&lt;p&gt;Click Download private key and the deployment will start&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5s2qs2a8cm4p2ga8tw8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5s2qs2a8cm4p2ga8tw8e.png" alt=" " width="769" height="742"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtuy8syo6j874wi5e4ck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgtuy8syo6j874wi5e4ck.png" alt=" " width="451" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97dxnpku5peqveuqx0ay.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97dxnpku5peqveuqx0ay.png" alt=" " width="705" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect to the Linux VM Using SSH
&lt;/h2&gt;

&lt;p&gt;click on connect&lt;br&gt;
we will connect to this VM using our public IP address and admin user name&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvll11dbi7by8fxzb5nq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvll11dbi7by8fxzb5nq.png" alt=" " width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0n85706qk6p53vh8e5vu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0n85706qk6p53vh8e5vu.png" alt=" " width="797" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to your terminal(Windows PowerShell) and run the SSH command to connect to the Linux VM.&lt;br&gt;
ssh -i "/path/to/your_downloaded_key.pem" azureuser@your-vm-ip-address&lt;br&gt;
Explanation:&lt;br&gt;
ssh: The secure shell command used to connect to remote servers.&lt;/p&gt;

&lt;p&gt;-i "/path/to/your_downloaded_key.pem": Specifies the path to your private key file (downloaded from Azure).&lt;/p&gt;

&lt;p&gt;azureuser: This is the username you set when creating the VM.&lt;/p&gt;

&lt;p&gt;your-vm-ip-address: Replace this with the public IP address of your VM (you can find it in the Azure Portal).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5ylp1uqmofddqujl6vx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5ylp1uqmofddqujl6vx.png" alt=" " width="736" height="703"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Update the Server and Install a Web Server (Nginx)
&lt;/h3&gt;

&lt;p&gt;Now that you're connected to your VM, it's time to update the system and install a basic web server. We’ll use Nginx, a lightweight and fast web server ideal for serving static websites.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Update Your Server
&lt;/h3&gt;

&lt;p&gt;Run the following commands to update the package list and install any available upgrades:&lt;br&gt;
sudo apt update&lt;br&gt;
sudo apt upgrade -y&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Install Nginx
&lt;/h3&gt;

&lt;p&gt;Once the system is updated, install the Nginx web server:&lt;br&gt;
sudo apt install nginx -y&lt;/p&gt;

&lt;h3&gt;
  
  
  Step3 :Access Your Web Server in a Browser
&lt;/h3&gt;

&lt;p&gt;Open your browser and visit:&lt;br&gt;
http://&lt;br&gt;
You should see the default Nginx welcome page.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F29nv7eyhw2kbzetwolgu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F29nv7eyhw2kbzetwolgu.png" alt=" " width="655" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;p&gt;If you encounter issues:&lt;/p&gt;

&lt;p&gt;✅ NSG Inbound Rules: Ensure port 22 and port 80 are open&lt;/p&gt;

&lt;p&gt;✅ Correct IP: Use the public IP from Azure&lt;/p&gt;

&lt;p&gt;✅ File Permissions: Confirm private key permission if necessary&lt;/p&gt;

&lt;p&gt;chmod 600 ~/.ssh/myLinuxKey&lt;/p&gt;

&lt;p&gt;✅ SSH Key Format: Ensure the entire public key was pasted correctly&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Congratulations! You’ve successfully:&lt;/p&gt;

&lt;p&gt;Created a Linux VM in Azure&lt;/p&gt;

&lt;p&gt;Configured it for SSH access using a public key&lt;/p&gt;

&lt;p&gt;Enabled web traffic via port 80 for web server deployment&lt;/p&gt;

&lt;p&gt;You're now ready to install your favorite web server and start developing or deploying apps securely.&lt;/p&gt;

</description>
      <category>maryajayi</category>
      <category>beginners</category>
      <category>devops</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
