<?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: BAKRE JAMIU</title>
    <description>The latest articles on Forem by BAKRE JAMIU (@jamiu_cloud).</description>
    <link>https://forem.com/jamiu_cloud</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%2F2032476%2F7b90aad0-a783-4dfa-aa65-4b7f12a24be4.jpg</url>
      <title>Forem: BAKRE JAMIU</title>
      <link>https://forem.com/jamiu_cloud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jamiu_cloud"/>
    <language>en</language>
    <item>
      <title>📘 Ansible Learning Journey - From Manual SSH to Automation Thinking</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Wed, 14 Jan 2026 15:07:46 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/ansible-learning-journey-from-manual-ssh-to-automation-thinking-2a2o</link>
      <guid>https://forem.com/jamiu_cloud/ansible-learning-journey-from-manual-ssh-to-automation-thinking-2a2o</guid>
      <description>&lt;p&gt;&lt;strong&gt;CloudWithHorla | Cloud &amp;amp; DevOps Engineer (Learning in Progress 🚀)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Automation looks simple from the outside — until you try to build it yourself.&lt;/p&gt;

&lt;p&gt;Recently, I worked on an &lt;strong&gt;Ansible hands-on project&lt;/strong&gt; as part of my continuous learning in Cloud and DevOps engineering. The goal was simple on paper:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;set up a controller node and manage multiple target nodes using Ansible&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%2Fu3bqh7aqj4sj2fruuivf.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%2Fu3bqh7aqj4sj2fruuivf.png" alt=" " width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In reality, the journey taught me far more than just commands.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ Project Overview
&lt;/h2&gt;

&lt;p&gt;I built a small but realistic infrastructure on AWS consisting of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;* &lt;strong&gt;1 EC2 Controller (Ansible Master)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;* &lt;strong&gt;3 EC2 Target Nodes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;* Ubuntu-based servers&lt;/li&gt;
&lt;li&gt;* SSH key-based authentication&lt;/li&gt;
&lt;li&gt;* Ansible ad-hoc commands and playbooks&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%2Fi4oftonmq3pvn8e12k6s.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%2Fi4oftonmq3pvn8e12k6s.png" alt=" " width="800" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This setup mirrors what actually happens in real-world environments — not just labs.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 What I Implemented (Step-by-Step)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Provisioned EC2 instances&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;1 controller&lt;/li&gt;
&lt;li&gt;3 managed nodes&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Installed core dependencies&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Python3&lt;/li&gt;
&lt;li&gt;Pip&lt;/li&gt;
&lt;li&gt;Ansible on the controller&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Created Ansible configuration&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Custom &lt;code&gt;ansible.cfg&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Inventory file defining all target nodes&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;SSH Key-Based Authentication&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Generated SSH key pair on the controller&lt;/li&gt;
&lt;li&gt;Injected the controller’s &lt;strong&gt;public key&lt;/strong&gt; into each node’s &lt;code&gt;authorized_keys&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Learned the difference between:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt;  &lt;span class="c"&gt;# append (safe)&lt;/span&gt;
 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;   &lt;span class="c"&gt;# overwrite (dangerous)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You are adding a new line of Public Key which is safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCppACFB47TRDuT8YXSSxL+T9jxirz0yC04avxRB8nAOnVcz5xXpyT0mhYbhcLCbI2D4pcWkSb1NqGyUwF3OeHGtur+0MkDq7/9jhPG0amrFbk+RBQM+WZ7UaEzopiK7ZB8MUKwtMGVhR9wgtIiSK6+fgmzNaCpfj13B9aH7iiMRn4sHCwr81zCAskb79DnhCmB8Y7NU2VAqlMnW5NIFEujv3aixmPSZbIKomNotGT2ljtOV5EoMuFFqq3DqA/kZVM1WJjBMEAlWtdQTn2UM5dTAi5BNvPMYJcdzEfc4fXvkp11rFYLiEc9ZUFkYi6APg1Ju5bPgh0Yp+9YOhlCMEuEPlAdxUIHE4Ih3HoNhLOB622c+a6lNK5SF7Y76gB5cdK8Rar/tRQqF6kxqy852SLfZbLnXkfIOuktF4XGemMMt13F7yw1k980vwcwCgfAK4zOZ2hmaDypmG0Rd/lhsIpC+4i6s4T8a+AB3BSKt9KH/Dn9cxUM0BVgxgM1hWyk7Hs= ubuntu@ip-10-0-8-231" &amp;gt;&amp;gt; .ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caveat: Best practise&lt;/p&gt;

&lt;p&gt;You are removing an existing "Public Key" which is not safe.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCppACFB47TRDuT8YXSSxL+T9jxirz0yC04avxRB8nAOnVcz5xXpyT0mhYbhcLCbI2D4pcWkSb1NqGyUwF3OeHGtur+0MkDq7/9jhPG0amrFbk+RBQM+WZ7UaEzopiK7ZB8MUKwtMGVhR9wgtIiSK6+fgmzNaCpfj13B9aH7iiMRn4sHCwr81zCAskb79DnhCmB8Y7NU2VAqlMnW5NIFEujv3aixmPSZbIKomNotGT2ljtOV5EoMuFFqq3DqA/kZVM1WJjBMEAlWtdQTn2UM5dTAi5BNvPMYJcdzEfc4fXvkp11rFYLiEc9ZUFkYi6APg1Ju5bPgh0Yp+9YOhlCMEuEPlAdxUIHE4Ih3HoNhLOB622c+a6lNK5SF7Y76gB5cdK8Rar/tRQqF6kxqy852SLfZbLnXkfIOuktF4XGemMMt13F7yw1k980vwcwCgfAK4zOZ2hmaDypmG0Rd/lhsIpC+4i6s4T8a+AB3BSKt9KH/Dn9cxUM0BVgxgM1hWyk7Hs= ubuntu@ip-10-0-8-231" &amp;gt; .ssh/authorized_keys
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Caveat: Not a best practise&lt;/p&gt;

&lt;p&gt;Sample &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Privilege Escalation&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Used &lt;code&gt;become: true&lt;/code&gt; for system-level tasks&lt;/li&gt;
&lt;li&gt;Ensured sudo access without breaking security&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ansible Ad-Hoc Commands&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   ansible &lt;span class="nt"&gt;-m&lt;/span&gt; apt &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"name=git state=present"&lt;/span&gt; all &lt;span class="nt"&gt;-b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Ansible Playbook Execution&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Installed and removed packages&lt;/li&gt;
&lt;li&gt;Copied files to remote nodes&lt;/li&gt;
&lt;li&gt;Managed services across multiple machines in parallel&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📄 Sample Playbook used in my project:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Installing nginx playbook&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;all&lt;/span&gt;
  &lt;span class="na"&gt;become&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;First Task&lt;/span&gt;
      &lt;span class="na"&gt;apt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;absent&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Second Task&lt;/span&gt;
      &lt;span class="na"&gt;apt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;present&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Copy file with owner and permissions&lt;/span&gt;
      &lt;span class="na"&gt;ansible.builtin.copy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./index.html&lt;/span&gt;
        &lt;span class="na"&gt;dest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/www/html/index.html&lt;/span&gt;
        &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
        &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
        &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0777'&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Third Task&lt;/span&gt;
      &lt;span class="na"&gt;apt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apache2&lt;/span&gt;
        &lt;span class="na"&gt;state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;present&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚠️ Challenges I Faced (and What I Learned)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1️⃣ “Permission denied (publickey)”
&lt;/h3&gt;

&lt;p&gt;I initially thought Ansible could manage nodes &lt;strong&gt;without SSH access&lt;/strong&gt;.&lt;br&gt;
Through research and troubleshooting, I learned a critical truth:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Ansible always uses SSH. There is no automation without an initial trust path.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Key-based authentication must be established &lt;strong&gt;at least once&lt;/strong&gt; — either at instance creation or manually.&lt;/p&gt;




&lt;h3&gt;
  
  
  2️⃣ PasswordAuthentication Confusion
&lt;/h3&gt;

&lt;p&gt;I tried disabling password authentication &lt;em&gt;before&lt;/em&gt; confirming key-based access.&lt;/p&gt;

&lt;p&gt;That was a big lesson:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;❌ Disabling &lt;code&gt;PasswordAuthentication&lt;/code&gt; does NOT give access&lt;br&gt;
✅ It only removes password login &lt;strong&gt;after SSH keys already work&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Correct order matters:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Establish SSH key access&lt;/li&gt;
&lt;li&gt;Test connectivity&lt;/li&gt;
&lt;li&gt;Then disable password authentication&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  3️⃣ APT Lock Errors (&lt;code&gt;unattended-upgrades&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;One node failed while others succeeded.&lt;/p&gt;

&lt;p&gt;Cause:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ubuntu auto-updates were running in the background&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lesson:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Infrastructure is &lt;strong&gt;not deterministic&lt;/strong&gt; — nodes behave independently.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Solution:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wait and retry&lt;/li&gt;
&lt;li&gt;Or design playbooks with retries and checks&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Screenshot 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%2Fa21okez4i0b57ntn8u1p.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%2Fa21okez4i0b57ntn8u1p.png" alt=" " width="800" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is when I ping of the node&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%2Fxy3l3mke9kao6b9nbwr1.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%2Fxy3l3mke9kao6b9nbwr1.png" alt=" " width="800" height="294"&gt;&lt;/a&gt;&lt;br&gt;
This is when I ping all the node&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%2Fj3fa4t23n1o2u75s1nc7.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%2Fj3fa4t23n1o2u75s1nc7.png" alt=" " width="800" height="321"&gt;&lt;/a&gt;&lt;br&gt;
This is the first page output of my Playbook&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%2F7qua607uilk36clhlpzg.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%2F7qua607uilk36clhlpzg.png" alt=" " width="800" height="201"&gt;&lt;/a&gt;&lt;br&gt;
This is the second page output of my Playbook&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%2Foncy46lc4mzzf72n3wog.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%2Foncy46lc4mzzf72n3wog.png" alt=" " width="800" height="457"&gt;&lt;/a&gt;&lt;br&gt;
Node 01&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%2Faf5vhb0d3z0fmj90kuub.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%2Faf5vhb0d3z0fmj90kuub.png" alt=" " width="757" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Node 02&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%2Fm9toag8k4la1ar2yo4ol.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%2Fm9toag8k4la1ar2yo4ol.png" alt=" " width="588" height="409"&gt;&lt;/a&gt;&lt;br&gt;
Node 03&lt;/p&gt;




&lt;h3&gt;
  
  
  4️⃣ Wrong Package Names
&lt;/h3&gt;

&lt;p&gt;I attempted to install &lt;code&gt;apache&lt;/code&gt; instead of &lt;code&gt;apache2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lesson:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Automation does exactly what you tell it — &lt;strong&gt;not what you mean&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Small naming errors can break entire workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Key Takeaways I Want Others to Learn
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🔑 &lt;strong&gt;SSH is foundational&lt;/strong&gt; — Ansible cannot bypass it&lt;/li&gt;
&lt;li&gt;🔁 Automation is about &lt;strong&gt;idempotency and retries&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🧪 Always test with &lt;code&gt;--syntax-check&lt;/code&gt; and &lt;code&gt;ping&lt;/code&gt; yourself (localhost) for test.&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%2Fx8ebyk4ih18zogvemebi.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%2Fx8ebyk4ih18zogvemebi.png" alt=" " width="800" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔐 Never overwrite &lt;code&gt;authorized_keys&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🛠️ Real learning happens when things break&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🌱 Growth Mindset
&lt;/h2&gt;

&lt;p&gt;This project reinforced my core belief:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Never stop learning.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every error I faced forced me to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Research deeper&lt;/li&gt;
&lt;li&gt;Read documentation&lt;/li&gt;
&lt;li&gt;Understand &lt;em&gt;why&lt;/em&gt; things work — not just &lt;em&gt;how&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m still learning.&lt;br&gt;
I’m still breaking things.&lt;br&gt;
And I’m still getting better — one tool at a time.&lt;/p&gt;




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

&lt;p&gt;Automation isn’t about avoiding work —&lt;br&gt;
it’s about &lt;strong&gt;doing the work once, correctly and at scale&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CloudWithHorla ☁️&lt;/strong&gt;&lt;br&gt;
Cloud &amp;amp; DevOps Engineer | Always Learning&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ansible</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>My Ongoing Cloud Migration Journey 🚀</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Mon, 10 Nov 2025 16:22:16 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/my-ongoing-cloud-migration-journey-3i1a</link>
      <guid>https://forem.com/jamiu_cloud/my-ongoing-cloud-migration-journey-3i1a</guid>
      <description>&lt;p&gt;Over the past few months, I’ve been working on one of the most exciting and challenging cloud migration projects of my career, a large-scale transformation initiative between &lt;strong&gt;xyz&lt;/strong&gt; (a global technology consulting firm) and &lt;strong&gt;abc&lt;/strong&gt; (a major telecommunications company).&lt;/p&gt;

&lt;p&gt;The goal of this project is simple but powerful: &lt;strong&gt;to move dozens of critical enterprise applications from on-premises data centers into a secure, scalable, and automated AWS environment&lt;/strong&gt; without disrupting existing business operations. This is part of a broader modernization program that will allow abc to run its workloads faster, more securely, and more efficiently in the cloud.&lt;/p&gt;




&lt;h3&gt;
  
  
  What We’re Doing
&lt;/h3&gt;

&lt;p&gt;The migration involves a mix of rehosting, redeploying, and refactoring applications using &lt;strong&gt;AWS native tools, Terraform for Infrastructure as Code (IaC), and automated CI/CD pipelines&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Our scope includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Designing and deploying AWS environments for multiple business units.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setting up &lt;strong&gt;VPCs, subnets, IAM roles, security groups, load balancers, and monitoring tools&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implementing &lt;strong&gt;cross-account role assumption&lt;/strong&gt; for secure access and governance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Coordinating closely with both the cloud engineering and application teams to ensure smooth transitions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As of now, we’re working through a pipeline of &lt;strong&gt;over 30 applications&lt;/strong&gt; scheduled for migration to AWS. Several have already been successfully redeployed and tested in non-production and production environments.&lt;/p&gt;




&lt;h3&gt;
  
  
  My Role
&lt;/h3&gt;

&lt;p&gt;As a Cloud Engineer on this project, my role cuts across technical execution, documentation, and coordination. I’ve been directly involved in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Designing AWS architectures&lt;/strong&gt; for multiple applications; defining network layout, IAM roles, and access controls.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Collaborating on Terraform automation&lt;/strong&gt;, including maintaining GitHub repositories and building modular scripts for consistent infrastructure deployment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Managing environment readiness&lt;/strong&gt;, which includes server provisioning, IAM access configuration, and validating connectivity between on-prem databases and cloud servers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Supporting MGN setup&lt;/strong&gt;, ensuring source servers are correctly configured for migration replication.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Contributing to migration design documents&lt;/strong&gt;, including the logical architecture, deployment models, dependencies, and database connections.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Coordinating with the application and security teams&lt;/strong&gt; to manage firewall requests, DNS cutovers, and access provisioning.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  What I’ve Achieved So Far
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Successfully supported the &lt;strong&gt;AWS environment setup&lt;/strong&gt; for multiple application migrations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Created and refined design documentation&lt;/strong&gt; that clearly outlines migration strategy, deployment processes, and technical architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Validated IAM roles and cross-account access&lt;/strong&gt;, ensuring secure provisioning in multi-account AWS setups.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Helped establish a &lt;strong&gt;Terraform-based deployment workflow&lt;/strong&gt;, integrating version control and infrastructure automation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Worked closely with the project leads to &lt;strong&gt;align AWS provisioning with organizational compliance standards&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Gained practical experience in &lt;strong&gt;AWS MGN (Migration Hub)&lt;/strong&gt;, &lt;strong&gt;Terraform automation&lt;/strong&gt;, and &lt;strong&gt;enterprise migration governance&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Where We Are Now
&lt;/h3&gt;

&lt;p&gt;Our team has completed the foundation setup AWS accounts, networking, IAM, and automation frameworks are now in place. We’re currently focused on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accelerating AWS application deployments through Terraform automation.&lt;/li&gt;
&lt;li&gt;Coordinating with database and app owners for production cutovers.&lt;/li&gt;
&lt;li&gt;Streamlining server provisioning and post-deployment checks.&lt;/li&gt;
&lt;li&gt;Ensuring security compliance and monitoring with AWS CloudWatch and Config.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  What Makes This Experience Stand Out
&lt;/h3&gt;

&lt;p&gt;This project is more than just moving workloads to AWS; it’s a &lt;strong&gt;complete cloud enablement initiative&lt;/strong&gt;. I’ve learned the value of collaboration between cloud engineers, app owners, database administrators, and project managers, all working toward a shared goal of modernization.&lt;/p&gt;

&lt;p&gt;Every day comes with new learning: understanding enterprise migration frameworks, managing IAM at scale, troubleshooting deployment issues, and optimizing Terraform code for real-world production environments.&lt;/p&gt;




&lt;h3&gt;
  
  
  My Reflection
&lt;/h3&gt;

&lt;p&gt;This experience has strengthened my skills not only as a Cloud Engineer but as a problem solver and collaborator. From designing secure AWS architectures to supporting production rollouts, I’ve seen firsthand how cloud migration works at scale the challenges, the coordination, and the satisfaction that comes when an application successfully goes live in the cloud.&lt;/p&gt;

&lt;p&gt;We’re still moving forward, with many more applications to migrate in the coming weeks. And as we continue to build, automate, and refine, I’m proud to be part of a team that’s shaping the future of cloud transformation for one of the biggest enterprises in the industry.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>mgn</category>
      <category>terraform</category>
      <category>git</category>
    </item>
    <item>
      <title>Building a Scalable AWS E-Learning Platform for Government Use</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Sat, 18 Oct 2025 13:37:45 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/building-a-scalable-aws-e-learning-platform-for-government-use-hb5</link>
      <guid>https://forem.com/jamiu_cloud/building-a-scalable-aws-e-learning-platform-for-government-use-hb5</guid>
      <description>&lt;h3&gt;
  
  
  🌍 Project Overview
&lt;/h3&gt;

&lt;p&gt;As part of a Architect Engineer assessment for &lt;strong&gt;XYZ Company&lt;/strong&gt;, I was tasked with designing a &lt;strong&gt;secure, scalable, and reliable AWS-based architecture&lt;/strong&gt; for a &lt;strong&gt;government-backed e-learning platform&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The goal was to create a system capable of serving &lt;strong&gt;up to 200 million users&lt;/strong&gt; across multiple regions — supporting video streaming, quizzes, progress tracking, and a multilingual AI chatbot.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧱 Architecture Goal
&lt;/h3&gt;

&lt;p&gt;Design a &lt;strong&gt;3-tier AWS architecture&lt;/strong&gt; that ensures:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt; for millions of users&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security and compliance&lt;/strong&gt; with government data standards&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High availability&lt;/strong&gt; across multiple Availability Zones&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost efficiency&lt;/strong&gt; using serverless and auto-scaling resources&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ⚙️ Core AWS Services Used
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;1️⃣ User Authentication &amp;amp; Access Management&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Cognito&lt;/strong&gt; for secure user authentication&lt;/li&gt;
&lt;li&gt;Integrated with &lt;strong&gt;government identity providers&lt;/strong&gt; via &lt;strong&gt;SAML/OAuth&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-Factor Authentication (MFA)&lt;/strong&gt; enabled for all users&lt;/li&gt;
&lt;li&gt;Role-based access for students, instructors, and administrators&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;2️⃣ Video Delivery and Streaming&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amazon S3&lt;/strong&gt; stores all course materials and videos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Elemental MediaConvert&lt;/strong&gt; handles video transcoding&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon CloudFront (CDN)&lt;/strong&gt; delivers content with adaptive bitrate streaming for smooth playback across all regions&lt;/li&gt;
&lt;li&gt;Content is secured using &lt;strong&gt;signed URLs&lt;/strong&gt; and &lt;strong&gt;S3 encryption&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;3️⃣ Multilingual AI Chatbot&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Lex&lt;/strong&gt; powers the conversational interface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon Translate&lt;/strong&gt; automatically detects and translates languages&lt;/li&gt;
&lt;li&gt;Chatbot supports &lt;strong&gt;English, Yoruba, Hausa, Igbo, and Pidgin&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Personalized responses based on user progress data stored in Aurora&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;4️⃣ Monitoring &amp;amp; Compliance&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS CloudTrail&lt;/strong&gt; logs all API activities for audit purposes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon CloudWatch&lt;/strong&gt; monitors performance metrics and triggers alarms&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Config&lt;/strong&gt; ensures resource compliance with security policies&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;5️⃣ Quizzes &amp;amp; Progress Tracking&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time quiz scoring and feedback&lt;/strong&gt; using &lt;strong&gt;AWS Lambda + API Gateway&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Data stored in &lt;strong&gt;Amazon Aurora (PostgreSQL)&lt;/strong&gt; for structured consistency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DynamoDB&lt;/strong&gt; used for low-latency user progress tracking&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;6️⃣ Data Storage &amp;amp; Analytics&lt;/strong&gt;
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Data Type&lt;/th&gt;
&lt;th&gt;AWS Service&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Videos &amp;amp; Materials&lt;/td&gt;
&lt;td&gt;Amazon S3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;User &amp;amp; Quiz Data&lt;/td&gt;
&lt;td&gt;Amazon Aurora&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Progress Tracking&lt;/td&gt;
&lt;td&gt;Amazon DynamoDB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Analytics &amp;amp; Reporting&lt;/td&gt;
&lt;td&gt;AWS Glue + Redshift (future phase)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;Here is the Native Design below:&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%2Frocm1jj64ug3qfib1gbm.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%2Frocm1jj64ug3qfib1gbm.png" alt=" " width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🏗️ 3-Tier Architecture Design
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Tier 1: Web Layer&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deployed on &lt;strong&gt;Auto-Scaled EC2 instances&lt;/strong&gt; behind an &lt;strong&gt;Application Load Balancer (ALB)&lt;/strong&gt; in &lt;strong&gt;public subnets&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tier 2: Application Layer&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stateless compute services (EC2 or AWS Lambda) in &lt;strong&gt;private subnets&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tier 3: Database Layer&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aurora Cluster&lt;/strong&gt; in &lt;strong&gt;private subnets&lt;/strong&gt;, Multi-AZ enabled with read replicas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Additional Infrastructure:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VPC&lt;/strong&gt; with 6 subnets (3 public, 3 private across 3 AZs)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NAT Gateway&lt;/strong&gt; for private subnet outbound access&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security Groups&lt;/strong&gt; + &lt;strong&gt;Network ACLs&lt;/strong&gt; for layered protection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CloudFront CDN&lt;/strong&gt; for global performance acceleration&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  💰 Cost Optimization Highlights
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Aurora Serverless v2&lt;/strong&gt; for automatic scaling of database capacity&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S3 Intelligent-Tiering&lt;/strong&gt; for optimizing storage costs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spot Instances&lt;/strong&gt; for EC2 auto-scaling groups&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Budgets + Cost Explorer&lt;/strong&gt; for continuous cost monitoring&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧠 Key Outcomes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Highly available&lt;/strong&gt;, &lt;strong&gt;fault-tolerant&lt;/strong&gt;, and &lt;strong&gt;secure&lt;/strong&gt; architecture&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimized for millions of concurrent users&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Ready for &lt;strong&gt;NDPR/ISO compliance&lt;/strong&gt; via CloudTrail and IAM governance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inclusive learning&lt;/strong&gt; through multilingual AI support&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  🧾 Deliverables
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;AWS Architecture Diagram&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Statement of Work (SOW)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Presentation Slide Deck&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  🚀 Conclusion
&lt;/h3&gt;

&lt;p&gt;This project demonstrates the power of &lt;strong&gt;cloud-native architecture on AWS&lt;/strong&gt; in enabling &lt;strong&gt;education at scale&lt;/strong&gt; — bringing inclusive, accessible, and secure learning to millions of users across regions.&lt;/p&gt;

&lt;p&gt;It also highlights my practical experience as a &lt;strong&gt;Cloud Engineer&lt;/strong&gt; in building enterprise-grade solutions that combine &lt;strong&gt;scalability, security, and innovation&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  📬 Connect With Me
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;👤 Bakre Jamiu (CloudWithHorla)&lt;/strong&gt;&lt;br&gt;
AWS Cloud &amp;amp; DevOps Engineer&lt;br&gt;
✉️ &lt;a href="//mailto:bakrejamiu@gmail.com"&gt;bakrejamiu@gmail.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>architectengineer</category>
      <category>cloudnative</category>
      <category>nlp</category>
    </item>
    <item>
      <title>🚀 Optimizing Costs Without Downtime: My Hands-On Experience Downgrading AWS Lightsail; A Step-by-Step Journey</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Wed, 06 Aug 2025 15:46:27 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/optimizing-costs-without-downtime-my-hands-on-experience-downgrading-aws-lightsail-a-jaf</link>
      <guid>https://forem.com/jamiu_cloud/optimizing-costs-without-downtime-my-hands-on-experience-downgrading-aws-lightsail-a-jaf</guid>
      <description>&lt;p&gt;Over 3 days, I planned, executed, and documented the entire process. Here’s how I successfully completed the downgrade while maintaining service availability.&lt;/p&gt;

&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;In cloud engineering, cost optimization without compromising performance is a skill every professional must master. Recently, I faced a real-world challenge: one of my projects running on AWS Lightsail required a downgrade to a smaller instance to reduce monthly costs. The catch? I had to ensure zero downtime and data integrity.&lt;/p&gt;

&lt;h1&gt;
  
  
  🛠 Project Objective
&lt;/h1&gt;

&lt;p&gt;Task: Downgrade AWS Lightsail instance to a smaller plan.&lt;/p&gt;

&lt;p&gt;Goal: Achieve cost savings while keeping the application online.&lt;/p&gt;

&lt;h2&gt;
  
  
  📌 Project Context
&lt;/h2&gt;

&lt;p&gt;A client’s web application was running on an oversized AWS Lightsail instance. The workload was consistently under-utilizing CPU, memory, and storage resources, which meant &lt;strong&gt;unnecessary monthly costs&lt;/strong&gt;. The client requested a &lt;strong&gt;downgrade to a smaller Lightsail instance&lt;/strong&gt; without affecting uptime, performance, or security.&lt;/p&gt;

&lt;p&gt;As a &lt;strong&gt;Cloud &amp;amp; DevOps Engineer&lt;/strong&gt;, I took ownership of the entire migration and cost-optimization project, delivering results in &lt;strong&gt;3 days&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Objectives
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Downgrade AWS Lightsail&lt;/strong&gt; to a smaller instance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ensure zero downtime&lt;/strong&gt; during migration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintain SSL, Nginx, and PM2 configurations&lt;/strong&gt; for seamless performance.&lt;/li&gt;
&lt;li&gt;Implement &lt;strong&gt;rollback and backup strategies&lt;/strong&gt; to avoid risk.&lt;/li&gt;
&lt;li&gt;Document the entire process for transparency and client knowledge.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  📍 End-to-End Execution
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Day 1: Assessment &amp;amp; Planning&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Assessment &amp;amp; Planning&lt;br&gt;
Reviewed resource utilization metrics (CPU, RAM, Disk) via Lightsail Monitoring and CloudWatch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Resource Utilization Analysis&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logged into AWS Lightsail Dashboard.&lt;/li&gt;
&lt;li&gt;Checked &lt;strong&gt;CPU, RAM, and Network metrics&lt;/strong&gt; via built-in monitoring.&lt;/li&gt;
&lt;li&gt;Cross-verified with &lt;strong&gt;CloudWatch metrics&lt;/strong&gt; for accurate trend analysis.&lt;/li&gt;
&lt;li&gt;Identified that the current instance size was over-provisioned (using ~30% capacity).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Downgrade Strategy Design&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Determined the &lt;strong&gt;target instance size&lt;/strong&gt; that could handle peak loads.&lt;/li&gt;
&lt;li&gt;Outlined a &lt;strong&gt;rollback plan&lt;/strong&gt; using snapshots.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Created a &lt;strong&gt;migration checklist&lt;/strong&gt; covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application files&lt;/li&gt;
&lt;li&gt;Database&lt;/li&gt;
&lt;li&gt;Nginx configuration&lt;/li&gt;
&lt;li&gt;SSL certificates&lt;/li&gt;
&lt;li&gt;Environment variables&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Backup Creation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Took a &lt;strong&gt;snapshot&lt;/strong&gt; of the existing Lightsail instance for disaster recovery.&lt;/li&gt;
&lt;li&gt;Exported database dump for redundancy using &lt;code&gt;mysqldump&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  🎯 What I achieved on Day 1:
&lt;/h1&gt;

&lt;p&gt;Identified the current instance type and determined a smaller instance plan suitable for the workload.&lt;/p&gt;

&lt;p&gt;Created a rollback plan in case of failure.&lt;/p&gt;

&lt;p&gt;Backed up the existing instance snapshot for disaster recovery.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Day 2: Environment Setup &amp;amp; Migration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Provisioning the New Lightsail Instance&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launched a new Lightsail instance with the &lt;strong&gt;downgraded size&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Configured &lt;strong&gt;SSH keys&lt;/strong&gt; for secure access.&lt;/li&gt;
&lt;li&gt;Set up networking (firewall rules, static IP).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Application Environment Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installed required packages:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;nginx mysql-client nodejs npm &lt;span class="nt"&gt;-y&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; pm2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Pulled application files from transferred via SCP.&lt;/li&gt;
&lt;li&gt;Restored environment variables from &lt;code&gt;.env&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Database Migration&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created a new MySQL instance inside Lightsail (or reused existing).&lt;/li&gt;
&lt;li&gt;Imported the database:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  mysql &lt;span class="nt"&gt;-u&lt;/span&gt; username &lt;span class="nt"&gt;-p&lt;/span&gt; database_name &amp;lt; backup.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Nginx &amp;amp; SSL Setup&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Configured Nginx virtual host with HTTPS redirect.&lt;/li&gt;
&lt;li&gt;Installed Let’s Encrypt SSL certificate with Certbot:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;certbot python3-certbot-nginx &lt;span class="nt"&gt;-y&lt;/span&gt;
  &lt;span class="nb"&gt;sudo &lt;/span&gt;certbot &lt;span class="nt"&gt;--nginx&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; example.com &lt;span class="nt"&gt;-d&lt;/span&gt; www.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Validated with &lt;code&gt;nginx -t&lt;/code&gt; and reloaded.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Application Process Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Started application with PM2:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  pm2 start app.js &lt;span class="nt"&gt;--name&lt;/span&gt; myapp
  pm2 save
  pm2 startup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ensured &lt;strong&gt;auto-start on reboot&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  🎯 What I achieved on Day 2 – Environment Preparation:
&lt;/h1&gt;

&lt;p&gt;Provisioned a new Lightsail instance with the downgraded size.&lt;/p&gt;

&lt;p&gt;Configured security groups, firewall rules, and SSH access.&lt;/p&gt;

&lt;p&gt;Migrated application files and environment variables from the old server.&lt;/p&gt;

&lt;p&gt;Installed and configured necessary dependencies (Nginx, Node.js, PM2, etc.).&lt;/p&gt;

&lt;p&gt;Validated that all services ran as expected on the smaller instance.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Day 3: DNS Cutover &amp;amp; Validation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. DNS Redirection&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updated Lightsail static IP for the new instance.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Testing &amp;amp; Monitoring&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verified that HTTPS was redirecting correctly.&lt;/li&gt;
&lt;li&gt;Tested login/admin pages to ensure proper routing.&lt;/li&gt;
&lt;li&gt;Confirmed API endpoints (&lt;code&gt;devapi.flexdelivery24.com&lt;/code&gt;) were functional.&lt;/li&gt;
&lt;li&gt;Monitored logs with:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/nginx/access.log
  &lt;span class="nb"&gt;tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/nginx/error.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Monitored CPU &amp;amp; RAM usage under live traffic for 24 hours.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Final Optimization&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cleaned up unused packages and logs.&lt;/li&gt;
&lt;li&gt;Documented final server architecture and cost savings.&lt;/li&gt;
&lt;li&gt;Shared final access and rollback documentation with the client.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  🎯 What I achieved on Day 3 – Cutover &amp;amp; Optimization
&lt;/h1&gt;

&lt;p&gt;Redirected DNS records to the new Lightsail instance.&lt;/p&gt;

&lt;p&gt;Tested application endpoints, admin login pages, and SSL configuration.&lt;/p&gt;

&lt;p&gt;Verified user sessions and ensured HTTPS redirection was functioning properly.&lt;/p&gt;

&lt;p&gt;Monitored server health (CPU/RAM) under production traffic for stability.&lt;/p&gt;

&lt;p&gt;Documented the final architecture and cost reduction achieved.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Deliverables
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;New &lt;strong&gt;Lightsail downgraded instance&lt;/strong&gt; in production.&lt;/li&gt;
&lt;li&gt;Full &lt;strong&gt;rollback snapshot&lt;/strong&gt; in case of failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL-secured environment&lt;/strong&gt; with automated renewals.&lt;/li&gt;
&lt;li&gt;Updated &lt;strong&gt;DNS configuration&lt;/strong&gt; with zero downtime.&lt;/li&gt;
&lt;li&gt;Detailed &lt;strong&gt;post-migration documentation&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📊 Results &amp;amp; Impact
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cost Reduction:&lt;/strong&gt; ~40% lower monthly Lightsail bill.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero Downtime:&lt;/strong&gt; Application stayed online throughout the migration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance Stability:&lt;/strong&gt; New instance running at ~65% capacity under peak load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Satisfaction:&lt;/strong&gt; A leaner, secure, and efficient environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🏆 Impact&lt;br&gt;
This project reinforced my ability to balance cost optimization and reliability. With a careful step-by-step approach, I delivered results that aligned with business goals while maintaining system uptime.&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Lessons Learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Always &lt;strong&gt;benchmark workloads&lt;/strong&gt; before downsizing to prevent under-provisioning.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snapshots and database dumps&lt;/strong&gt; are critical for safe rollbacks.&lt;/li&gt;
&lt;li&gt;DNS cutover timing is crucial—setting a low TTL can make transitions smoother.&lt;/li&gt;
&lt;li&gt;Post-migration monitoring ensures the environment remains stable under real traffic.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🏆 Conclusion
&lt;/h2&gt;

&lt;p&gt;This project demonstrates my ability to manage &lt;strong&gt;cloud cost optimization&lt;/strong&gt; while balancing &lt;strong&gt;availability, security, and scalability&lt;/strong&gt;. Over 3 days, I delivered a solution that not only reduced costs but also improved infrastructure efficiency.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>awslightsail</category>
      <category>node</category>
      <category>mysql</category>
    </item>
    <item>
      <title>🚀 How I Deployed a Python Flask App with Docker and Troubleshot My Way to Victory 🛠️🐍🐳</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Tue, 13 May 2025 18:52:59 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/how-i-deployed-a-python-flask-app-with-docker-and-troubleshot-my-way-to-victory-1io5</link>
      <guid>https://forem.com/jamiu_cloud/how-i-deployed-a-python-flask-app-with-docker-and-troubleshot-my-way-to-victory-1io5</guid>
      <description>&lt;p&gt;Deploying a Python Flask app with Docker sounds straightforward… until it &lt;em&gt;isn’t&lt;/em&gt;. 😅 Recently, I rolled up my sleeves to containerize and deploy a simple Flask app connected to PostgreSQL. While it seemed like a walk in the cloud, I ran into several walls—but breaking through them made the win even sweeter. Here’s how it all went down 👇&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗️ Project Setup
&lt;/h2&gt;

&lt;p&gt;I started with a basic Flask app that connects to a PostgreSQL database. My directory looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📁 python-docker-project/
├── Dockerfile
├── compose.yml
├── app.py
├── requirements.txt
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My &lt;code&gt;app.py&lt;/code&gt; had two routes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;/&lt;/code&gt;: returns a simple greeting&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/db&lt;/code&gt;: connects to PostgreSQL and returns the DB version&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal? Run this app in a Docker container and use Docker Compose to spin up both the app and a PostgreSQL service in one command.&lt;/p&gt;




&lt;h2&gt;
  
  
  🐳 Dockerfile Setup
&lt;/h2&gt;

&lt;p&gt;I created a simple Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.11-slim&lt;/span&gt;

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

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

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Looks good, right? 🤓 But here’s where the trouble started…&lt;/p&gt;




&lt;h2&gt;
  
  
  💥 The First Crash: Dependency Drama
&lt;/h2&gt;

&lt;p&gt;When I ran:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose &lt;span class="nt"&gt;-f&lt;/span&gt; compose.yml up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Boom 💣&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ERROR: Could not find a version that satisfies the requirement &lt;span class="nv"&gt;click&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;8.2.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hmm. Turns out the &lt;code&gt;click==8.2.0&lt;/code&gt; version in &lt;code&gt;requirements.txt&lt;/code&gt; requires Python &amp;gt;= 3.10, but I was using &lt;code&gt;python:3.9-slim-buster&lt;/code&gt; as my base image.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔧 Fix:
&lt;/h3&gt;

&lt;p&gt;I upgraded the base image in my Dockerfile to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; python:3.11-slim&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problem solved. ✅&lt;/p&gt;




&lt;h2&gt;
  
  
  🧊 The Second Freeze: Compose Conundrum
&lt;/h2&gt;

&lt;p&gt;Feeling confident, I re-ran the build and... 💥 another error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;KeyError: &lt;span class="s1"&gt;'ContainerConfig'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, I’m like, &lt;em&gt;“What even is ContainerConfig?”&lt;/em&gt; 😤&lt;/p&gt;

&lt;h3&gt;
  
  
  🕵️‍♂️ Root Cause:
&lt;/h3&gt;

&lt;p&gt;I was using Docker Compose v1.29.2 (legacy), which doesn't play nice with newer images or Docker Engine versions.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔧 Fix:
&lt;/h3&gt;

&lt;p&gt;I upgraded to Docker Compose v2 using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; ~/.docker/cli-plugins/
curl &lt;span class="nt"&gt;-SL&lt;/span&gt; https://github.com/docker/compose/releases/latest/download/docker-compose-linux-x86_64 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-o&lt;/span&gt; ~/.docker/cli-plugins/docker-compose
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ~/.docker/cli-plugins/docker-compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And voilà! &lt;code&gt;docker compose up&lt;/code&gt; started working without the dreaded &lt;code&gt;ContainerConfig&lt;/code&gt; error. 🎉&lt;/p&gt;




&lt;h2&gt;
  
  
  🟢 Final Compose File
&lt;/h2&gt;

&lt;p&gt;Here’s a sneak peek at my &lt;code&gt;compose.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5000:5000"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;DATABASE_URL=postgresql://postgres:mysecretpassword@db:5432/mydatabase&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db&lt;/span&gt;

  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:13&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysecretpassword&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mydatabase&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;db-data:/var/lib/postgresql/data&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  🎯 The Sweet Success
&lt;/h2&gt;

&lt;p&gt;After all the bumps, running the final command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fpd0bd0pbp77cylrawh52.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%2Fpd0bd0pbp77cylrawh52.png" alt="Image description" width="800" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;…worked flawlessly. I visited:&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%2F3zqnj0zdy4df7yyu36q6.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%2F3zqnj0zdy4df7yyu36q6.png" alt="Image description" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;http://localhost:5000/&lt;/code&gt; → Hello from Flask ✅&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%2Fhq4t5yw1drt8ri711xng.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%2Fhq4t5yw1drt8ri711xng.png" alt="Image description" width="800" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;http://localhost:5000/db&lt;/code&gt; → PostgreSQL version info ✅&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🐍 Match your Python version with compatible libraries (watch those &lt;code&gt;requirements.txt&lt;/code&gt; entries)&lt;/li&gt;
&lt;li&gt;🐳 Use Docker Compose v2 for smoother experience with modern images&lt;/li&gt;
&lt;li&gt;🧠 Don’t panic when you hit errors—each one teaches you something&lt;/li&gt;
&lt;li&gt;🔧 Always check if errors are due to version mismatches, especially with Docker&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏁 Final Words
&lt;/h2&gt;

&lt;p&gt;This small project taught me that deployment isn't always plug-and-play—but that's what makes it rewarding. If you're running into Docker or Python-related issues, you're not alone. Just breathe, dig deep, and Google like a ninja. 💻&lt;/p&gt;




&lt;p&gt;Want more stories like this or need help with your own cloud projects? Follow me at &lt;strong&gt;CloudWithHorla&lt;/strong&gt; ☁️💪&lt;/p&gt;

</description>
      <category>aws</category>
      <category>docker</category>
      <category>python</category>
      <category>pythonflask</category>
    </item>
    <item>
      <title>🛠️ From Concept to Container: My Journey Deploying MongoDB &amp; Mongo-Express with Docker (No Docker Compose!)</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Mon, 05 May 2025 19:50:58 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/from-concept-to-container-my-journey-deploying-mongodb-mongo-express-with-docker-no-docker-3ec5</link>
      <guid>https://forem.com/jamiu_cloud/from-concept-to-container-my-journey-deploying-mongodb-mongo-express-with-docker-no-docker-3ec5</guid>
      <description>&lt;h3&gt;
  
  
  🔥 Real-World Skills, Real Results — A Cloud Engineer’s Perspective
&lt;/h3&gt;

&lt;p&gt;In cloud engineering, we often celebrate smooth deployments—but the real growth lies in the challenges we troubleshoot along the way. This project is a perfect example of that. I set out to containerize and connect a backend database (&lt;strong&gt;MongoDB&lt;/strong&gt;) and a frontend admin interface (&lt;strong&gt;Mongo Express&lt;/strong&gt;) using Docker. The twist? I chose not to use Docker Compose. I wanted to master every part of the networking, environment configuration, and volume persistence manually—because that’s how pros sharpen their edge.&lt;/p&gt;

&lt;p&gt;Let’s dive into the steps I followed, the problems I solved, and how I ensured my data persisted—even after destroying and recreating my containers.&lt;/p&gt;




&lt;h3&gt;
  
  
  📌 Step 1: Create a Docker Network
&lt;/h3&gt;

&lt;p&gt;First, I created a custom bridge network to allow seamless communication between my containers.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker network create jamiu-network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🧱 Step 2: Deploy the MongoDB Container
&lt;/h3&gt;

&lt;p&gt;Here, I launched MongoDB with a mounted volume to persist data. This step ensures that even if the container is deleted, the data will remain intact.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; mongo-database &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network&lt;/span&gt; jamiu-network &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 27017:27017 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; mongo-data:/data/db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MONGO_INITDB_ROOT_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mongoadmin &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MONGO_INITDB_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret &lt;span class="se"&gt;\&lt;/span&gt;
  mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Takeaway:&lt;/strong&gt;&lt;br&gt;
Notice the &lt;code&gt;-v mongo-data:/data/db&lt;/code&gt; line—that’s the magic of Docker volumes doing the heavy lifting for persistence.&lt;/p&gt;


&lt;h3&gt;
  
  
  🌐 Step 3: Deploy Mongo Express
&lt;/h3&gt;

&lt;p&gt;Now, I deployed Mongo Express and connected it to my MongoDB container through the custom network. This acts as a simple frontend for interacting with my database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network&lt;/span&gt; jamiu-network &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; mongo-express &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 8085:8081 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;ME_CONFIG_OPTIONS_EDITORTHEME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"ambiance"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;ME_CONFIG_MONGODB_SERVER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mongo-database"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;ME_CONFIG_MONGODB_ADMINUSERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mongoadmin"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;ME_CONFIG_MONGODB_ADMINPASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"secret"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;ME_CONFIG_BASICAUTH_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"user"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;ME_CONFIG_BASICAUTH_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"fairly long password"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  mongo-express
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Access Mongo Express at:&lt;br&gt;
🌍 &lt;strong&gt;&lt;a href="http://localhost:8085" rel="noopener noreferrer"&gt;http://localhost:8085&lt;/a&gt;&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%2Fyr8a8d3grcjl08epuqge.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%2Fyr8a8d3grcjl08epuqge.png" alt="Image description" width="800" height="426"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The view for Mongo-express
&lt;/h2&gt;
&lt;h3&gt;
  
  
  ⚔️ Real Talk: Troubleshooting Was My Superpower
&lt;/h3&gt;

&lt;p&gt;Was it smooth sailing? Absolutely not.&lt;/p&gt;

&lt;p&gt;Mongo Express initially failed to connect. The logs screamed:&lt;br&gt;
&lt;code&gt;Name does not resolve&lt;/code&gt; and &lt;code&gt;mongo:27017 Invalid argument&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The issue? I had incorrectly set the MongoDB hostname. Instead of using &lt;code&gt;"mongo-database"&lt;/code&gt;—which is the container name and acts as the hostname inside the Docker network—I had used &lt;code&gt;"mongo"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once I corrected the &lt;code&gt;ME_CONFIG_MONGODB_SERVER&lt;/code&gt; value to match the actual MongoDB container name, everything clicked.&lt;/p&gt;

&lt;p&gt;🧠 &lt;strong&gt;Lesson:&lt;/strong&gt; Troubleshooting isn't a skill—it's a &lt;em&gt;superpower&lt;/em&gt;. It’s what separates a "deployer" from a real &lt;strong&gt;Cloud Engineer&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  🧪 Step 4: Test Volume Persistence Like a Pro
&lt;/h3&gt;

&lt;p&gt;After confirming the Mongo Express interface was working, I connected to the Mongo shell inside the container and added some test data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nb"&gt;exec&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; mongo-database mongosh &lt;span class="nt"&gt;-u&lt;/span&gt; mongoadmin &lt;span class="nt"&gt;-p&lt;/span&gt; secret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside Mongo shell:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;use&lt;/span&gt; &lt;span class="nx"&gt;testdb&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testcollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insertOne&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bakre&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;skill&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cloud Engineering&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testcollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then came the real test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Delete the running container&lt;/span&gt;
docker &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; mongo-database

&lt;span class="c"&gt;# Recreate it with the same volume&lt;/span&gt;
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; mongo-database &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network&lt;/span&gt; jamiu-network &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 27017:27017 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; mongo-data:/data/db &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MONGO_INITDB_ROOT_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mongoadmin &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MONGO_INITDB_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secret &lt;span class="se"&gt;\&lt;/span&gt;
  mongo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Connected again...&lt;br&gt;
And guess what? 🎉&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testcollection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The data was still there. My volume was working perfectly. &lt;strong&gt;Data persisted!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&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%2Fwb1zgwjrj1zzqb67i2ru.png" alt="Image description" width="800" height="491"&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🚀 Final Thoughts: This Is Cloud Engineering
&lt;/h3&gt;

&lt;p&gt;This project was more than deploying containers. It was about thinking like a professional Cloud Engineer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building infrastructure with intention&lt;/li&gt;
&lt;li&gt;Debugging under pressure&lt;/li&gt;
&lt;li&gt;Validating persistence&lt;/li&gt;
&lt;li&gt;Embracing the long road for deeper mastery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every Founder, CTO, and DevOps team needs people who don’t just know tools, but understand &lt;em&gt;systems&lt;/em&gt;. If you're looking for someone who’s not afraid of broken logs, bad connections, or late-night debugging—I’m your guy.&lt;/p&gt;

&lt;p&gt;🔧 &lt;strong&gt;Cloud isn’t just my skillset. It’s my mindset.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s connect.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>docker</category>
      <category>mongodb</category>
      <category>mongoexpress</category>
    </item>
    <item>
      <title>🚀How I Achieved My Project: Deploying Docker Images to Amazon Elastic Container Registry (ECR)🐳 Part 2</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Wed, 30 Apr 2025 16:11:09 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/how-i-achieved-my-project-deploying-docker-images-to-amazon-elastic-container-registry-ecr-4mo3</link>
      <guid>https://forem.com/jamiu_cloud/how-i-achieved-my-project-deploying-docker-images-to-amazon-elastic-container-registry-ecr-4mo3</guid>
      <description>&lt;p&gt;&lt;em&gt;🚀 How I Achieved My Project: Deploying Docker Images to Amazon Elastic Container Registry (ECR)🐳&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through how I successfully pushed my Docker image to &lt;strong&gt;Amazon Elastic Container Registry (ECR)&lt;/strong&gt; and how Docker made the whole process incredibly seamless. This project involved leveraging Docker's simplicity to move an image from &lt;strong&gt;Docker Hub&lt;/strong&gt; to &lt;strong&gt;AWS ECR&lt;/strong&gt; and then deploying it onto an EC2 instance. Here’s how I did it.&lt;/p&gt;

&lt;p&gt;How Docker Streamlined the Project&lt;br&gt;
Docker revolutionizes application deployment by allowing developers to package their applications and all dependencies into containers, ensuring portability and consistency across environments. One of the key benefits of Docker is its ability to create reproducible environments, which makes deploying applications easier and more reliable.&lt;/p&gt;

&lt;p&gt;For this project, I used Docker to build my image and initially pushed it to Docker Hub. When it was time to transfer the image to AWS ECR, Docker’s straightforward commands allowed me to easily pull and push the image to ECR, making the process seamless.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;Steps to Achieve the Project&lt;/strong&gt;
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;1. Docker Installation and Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before starting, I made sure that &lt;strong&gt;Docker&lt;/strong&gt; and &lt;strong&gt;AWS CLI&lt;/strong&gt; were installed on my system. Here are the basic commands to get Docker running on an Ubuntu system:&lt;/p&gt;
&lt;h4&gt;
  
  
  Install Docker on Ubuntu:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;docker.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


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

&lt;p&gt;Check my previous post i.e &lt;a href="https://dev.to/jamiu_cloud/getting-started-with-docker-from-installation-to-pushing-images-to-docker-hub-4of6"&gt;Part 1&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Install AWS CLI:
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;awscli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


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

&lt;p&gt;Follow this official document &lt;a href="https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html" rel="noopener noreferrer"&gt;code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once installed, I configured the AWS CLI using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws configure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows you to set your AWS access key, secret access key, and default region.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;2. Authenticate Docker to AWS ECR&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Since my goal was to move the Docker image to AWS ECR, the next step was to authenticate Docker to AWS using the AWS CLI. The &lt;strong&gt;get-login-password&lt;/strong&gt; command simplifies this process by securely logging Docker into ECR.&lt;/p&gt;

&lt;p&gt;Authenticate Docker to ECR:&lt;/p&gt;

&lt;h4&gt;
  
  
  Authenticate Docker to ECR:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ecr get-login-password &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1 | docker login &lt;span class="nt"&gt;--username&lt;/span&gt; AWS &lt;span class="nt"&gt;--password-stdin&lt;/span&gt; 9111&lt;span class="k"&gt;****&lt;/span&gt;75.dkr.ecr.us-east-1.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command retrieves the authentication token from AWS and logs Docker into the specified ECR repository.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;3. Docker Image Build and Push to Docker Hub&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For this project, I started by pulling my image from Docker Hub. Once the image was pulled, I ran the container using the following command:&lt;/p&gt;

&lt;p&gt;Pull the Docker Image:&lt;/p&gt;

&lt;h4&gt;
  
  
  Pull the Docker Image:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull horlacloud/webapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command pulls the Docker image from Docker Hub.&lt;/p&gt;

&lt;p&gt;After pulling the image, I proceeded to push the container to AWS ECR so that it could be pulled from there later.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Tag the Docker Image for ECR&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;With Docker authenticated to ECR, I tagged my image to point to the correct repository in AWS ECR. The following command tags the image with the appropriate ECR repository URI:&lt;/p&gt;

&lt;h4&gt;
  
  
  Tag Docker Image:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker tag webapp:latest 9111&lt;span class="k"&gt;****&lt;/span&gt;75.dkr.ecr.us-east-1.amazonaws.com/webapp:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step prepares the image for pushing to ECR.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;5. Push the Image to ECR&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;After tagging the image, I pushed it to the AWS ECR repository using the command below:&lt;/p&gt;

&lt;h4&gt;
  
  
  Push Image to ECR:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker push 9111&lt;span class="k"&gt;****&lt;/span&gt;75.dkr.ecr.us-east-1.amazonaws.com/webapp:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command uploads the image to the Amazon ECR repository, making it available for further deployment.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;6. Running Docker Image on EC2&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To run the image on an EC2 instance, I executed the following commands. This involved pulling the image from ECR and running it on the instance.&lt;/p&gt;

&lt;h4&gt;
  
  
  Run the Docker Container:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:80 9111&lt;span class="k"&gt;***&lt;/span&gt;75.dkr.ecr.us-east-1.amazonaws.com/webapp:latest
4f04c29bffc5929f40306b0edd282464a9e23bdf5c24f42c1abdb4c84ea84043
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After executing the above command, my application was running on port 8080 on the EC2 instance. To access the application, I simply visited:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://&amp;lt;ec2-public-ip&amp;gt;:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Useful Docker Commands for the Project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here are a few &lt;strong&gt;helpful Docker commands&lt;/strong&gt; I used throughout the process:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Making the &lt;code&gt;ubuntu&lt;/code&gt; user a root user&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you want to add the &lt;code&gt;ubuntu&lt;/code&gt; user to the Docker group (so it can run Docker commands without &lt;code&gt;sudo&lt;/code&gt;), use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker ubuntu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, log out and log back in for the changes to take effect.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Check Docker Images&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To see the list of images on your system, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker image &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Removing Docker Images&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you need to remove an image, use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker rmi &amp;lt;image-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a container is using the image, stop and remove the container first with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stop &amp;lt;container-id&amp;gt;
docker &lt;span class="nb"&gt;rm&lt;/span&gt; &amp;lt;container-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;View Running Containers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To list all running containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Ff0gfimkmqzzaojol97ew.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%2Ff0gfimkmqzzaojol97ew.png" alt="Image description" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;




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

&lt;p&gt;Docker has significantly streamlined the process of moving containerized applications between environments. By pushing my Docker image to Docker Hub and pulling it into AWS ECR, I was able to quickly deploy my application on an EC2 instance with minimal configuration. Docker’s portability and ease of use make it an invaluable tool for cloud-native application deployments.&lt;/p&gt;

&lt;p&gt;With AWS ECR and Docker, I now have a robust and scalable containerization pipeline ready for future projects. Docker's simplicity makes managing and deploying applications easier and more efficient than ever.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>docker</category>
      <category>ecr</category>
      <category>awscli</category>
    </item>
    <item>
      <title>🚀 Getting Started with Docker: From Installation to Pushing Images to Docker Hub Part 1</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Tue, 29 Apr 2025 19:42:36 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/getting-started-with-docker-from-installation-to-pushing-images-to-docker-hub-4of6</link>
      <guid>https://forem.com/jamiu_cloud/getting-started-with-docker-from-installation-to-pushing-images-to-docker-hub-4of6</guid>
      <description>&lt;p&gt;If you're new to Docker or looking for a simple guide to go from setup to publishing your containerized app, this post is for you. In this tutorial, you'll learn how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Docker on Ubuntu
&lt;/li&gt;
&lt;li&gt;Build your first Docker image
&lt;/li&gt;
&lt;li&gt;Create and run a container
&lt;/li&gt;
&lt;li&gt;Tag and push your image to Docker Hub
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s get started.&lt;/p&gt;




&lt;h3&gt;
  
  
  🐳 Step 1: Install Docker on Ubuntu
&lt;/h3&gt;

&lt;p&gt;Open your terminal and run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;🔗 &lt;strong&gt;Alternative method:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For the latest version and installation options, check the official Docker install script:&lt;br&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://get.docker.com/" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;get.docker.com&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;To verify Docker is installed correctly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  📂 Useful Docker Commands
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;List Docker images&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker image &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;List Docker containers&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker container &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  🛠 Step 2: Build Your Docker Image
&lt;/h3&gt;

&lt;p&gt;Let’s use a static website as an example, such as one downloaded from &lt;a href="https://startbootstrap.com" rel="noopener noreferrer"&gt;startbootstrap.com&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;Dockerfile&lt;/code&gt; in your project directory:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano Dockerfile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Add the following content:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /usr/share/nginx/html&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; webapp:v1 &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To confirm the image was created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker image &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F0xeuxeq366wcfm1e0jda.jpeg" 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%2F0xeuxeq366wcfm1e0jda.jpeg" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🚀 Step 3: Run the Container
&lt;/h3&gt;

&lt;p&gt;Now let’s run your image in a Docker container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 80:80 &lt;span class="nt"&gt;--name&lt;/span&gt; websiteapp webapp:v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit &lt;code&gt;http://localhost:80&lt;/code&gt; (or your server’s public IP) to see your site live.&lt;/p&gt;

&lt;p&gt;To list running containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker container ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fbscfysw580ytcmw5bq39.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%2Fbscfysw580ytcmw5bq39.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  🔐 Step 4: Log in to Docker Hub
&lt;/h3&gt;

&lt;p&gt;If you don’t have a Docker Hub account, &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;sign up here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then log in from your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker login &lt;span class="nt"&gt;-u&lt;/span&gt; your_dockerhub_username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Ftwy298d54qk1n6t6xw0r.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%2Ftwy298d54qk1n6t6xw0r.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You’ll be asked to enter your password or a &lt;a href="https://hub.docker.com/settings/security" rel="noopener noreferrer"&gt;Personal Access Token (PAT)&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  📦 Step 5: Tag &amp;amp; Push Your Image to Docker Hub
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Tag the image:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker tag webapp:v1 your_dockerhub_username/webapp:v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Push the image:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker push your_dockerhub_username/webapp:v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fdku5d015m1p2o90mnyah.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%2Fdku5d015m1p2o90mnyah.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now visit your Docker Hub profile and view your pushed image:&lt;br&gt;&lt;br&gt;
👉 &lt;a href="https://hub.docker.com/repositories" rel="noopener noreferrer"&gt;https://hub.docker.com/repositories&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%2Fqizyljrirdqmdf39k26m.jpeg" 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%2Fqizyljrirdqmdf39k26m.jpeg" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;After Successful Push&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%2F61qn0xhk0tm9kt63e6qf.jpeg" 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%2F61qn0xhk0tm9kt63e6qf.jpeg" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Summary
&lt;/h3&gt;

&lt;p&gt;In this guide, you learned how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install Docker on Ubuntu
&lt;/li&gt;
&lt;li&gt;Build and run a Docker image
&lt;/li&gt;
&lt;li&gt;Host a simple static site using NGINX
&lt;/li&gt;
&lt;li&gt;Push your Docker image to Docker Hub
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This workflow forms the backbone of containerized development. You can now use these skills to automate deployments, integrate with CI/CD pipelines, or scale with orchestration tools like Kubernetes.&lt;/p&gt;




&lt;p&gt;💬 &lt;strong&gt;Have questions or want to learn how to automate deployment using GitHub Actions or AWS ECS? Leave a comment or reach out — I’d love to help!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>docker</category>
      <category>linux</category>
      <category>devops</category>
    </item>
    <item>
      <title>🚀 How I Deployed My Static Website Using GitHub Actions</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Thu, 24 Apr 2025 18:40:41 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/how-i-deployed-my-static-website-using-github-actions-52f5</link>
      <guid>https://forem.com/jamiu_cloud/how-i-deployed-my-static-website-using-github-actions-52f5</guid>
      <description>&lt;p&gt;Deploying a static website manually can be tedious, especially when you’re updating it frequently. That’s why I decided to automate my deployment process using &lt;strong&gt;GitHub Actions&lt;/strong&gt;—a powerful CI/CD tool built right into GitHub.&lt;/p&gt;

&lt;p&gt;In this post, I’ll walk you through &lt;strong&gt;how I deployed my static website automatically to an NGINX server using GitHub Actions&lt;/strong&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  🛠️ Tools I Used
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt; – to store my website’s source code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions&lt;/strong&gt; – to automate the deployment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ubuntu Server with NGINX&lt;/strong&gt; – to host the static site&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-Hosted GitHub Runner&lt;/strong&gt; – on the Ubuntu server&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  📁 Project Structure
&lt;/h3&gt;

&lt;p&gt;My website files are stored in this directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_work/ci-static-simple-website/ci-static-simple-website/
│
├── index.html
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ⚙️ Setting Up the GitHub Action
&lt;/h3&gt;

&lt;p&gt;I created a &lt;code&gt;.github/workflows/deploy.yml&lt;/code&gt; file in my repo to define the deployment pipeline.&lt;/p&gt;

&lt;p&gt;Here’s a simple version of my GitHub Actions workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Static Website&lt;/span&gt;

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

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;self-hosted&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout Code&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Copy index.html to NGINX Web Directory&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;cp _work/ci-static-simple-website/ci-static-simple-website/index.html /var/www/html/index.html&lt;/span&gt;
        &lt;span class="s"&gt;sudo systemctl reload nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fj1bji6w6zgix3wgzl6bt.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%2Fj1bji6w6zgix3wgzl6bt.png" alt="Image description" width="800" height="275"&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%2Fo68ptpjad30cgrcy5n7a.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%2Fo68ptpjad30cgrcy5n7a.png" alt="Image description" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After successfully testing my code.&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%2F5m2n0tluh2dylzyh9ylw.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%2F5m2n0tluh2dylzyh9ylw.png" alt="Image description" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Deploying my code to the Linux self-hosted server in process.&lt;/p&gt;




&lt;h3&gt;
  
  
  🔗 How It Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Every time I &lt;strong&gt;push to the &lt;code&gt;main&lt;/code&gt; branch&lt;/strong&gt;, the GitHub Action is triggered.&lt;/li&gt;
&lt;li&gt;The self-hosted runner on my Ubuntu server picks it up.&lt;/li&gt;
&lt;li&gt;It copies the &lt;code&gt;index.html&lt;/code&gt; file into &lt;code&gt;/var/www/html/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;It reloads NGINX to apply changes immediately.&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%2F3fmqffr9wosqme818jcc.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%2F3fmqffr9wosqme818jcc.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Successful deployed and it running fine.&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%2Fk2kx6pb74hvbgcucrjy6.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%2Fk2kx6pb74hvbgcucrjy6.png" alt="Image description" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My Code is running Live.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎉 Final Result
&lt;/h3&gt;

&lt;p&gt;Once the action runs, my static website is instantly live at my server’s public IP!&lt;/p&gt;




&lt;h3&gt;
  
  
  💡 Why This Is Awesome
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;I &lt;strong&gt;never have to manually copy files again&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;It works perfectly for &lt;strong&gt;personal portfolios&lt;/strong&gt;, &lt;strong&gt;landing pages&lt;/strong&gt;, or &lt;strong&gt;project demos&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Super fast and reliable!&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Let me know in the comments if you'd like a step-by-step guide to setting up your own self-hosted runner or customizing your deployment pipeline!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>githubactions</category>
      <category>cicd</category>
      <category>webdev</category>
    </item>
    <item>
      <title>PM2 Integration with Jenkins on Windows — Observations and Alternative Recommendations</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Thu, 17 Apr 2025 16:36:46 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/pm2-integration-with-jenkins-on-windows-observations-and-alternative-recommendations-4hl9</link>
      <guid>https://forem.com/jamiu_cloud/pm2-integration-with-jenkins-on-windows-observations-and-alternative-recommendations-4hl9</guid>
      <description>&lt;p&gt;Hit a wall trying to run PM2 within Jenkins on a Windows machine 😅 After testing PM2, Forever, NSSM, and Task Scheduler, it’s clear that Windows isn’t PM2’s playground. Sharing this to help anyone facing the same CI/CD challenge 💡&lt;/p&gt;

&lt;p&gt;Hello Developers,&lt;/p&gt;

&lt;p&gt;During my recent CI/CD pipeline implementation using Jenkins on a Windows environment, I attempted to integrate &lt;strong&gt;PM2&lt;/strong&gt; as a background process manager for a Node.js application. Despite successfully installing PM2 and validating it via CLI, I encountered issues running it persistently within the Jenkins pipeline.&lt;/p&gt;

&lt;p&gt;The process did not behave as expected — PM2 failed to run in the background through Jenkins, and the functionality was no different than invoking &lt;code&gt;node app.js&lt;/code&gt; directly. Extensive troubleshooting, including using &lt;code&gt;npx&lt;/code&gt;, global installs, and different execution flags (&lt;code&gt;--no-daemon&lt;/code&gt;, etc.), did not resolve the issue.&lt;/p&gt;

&lt;p&gt;I also explored potential Jenkins plugins for PM2 integration but confirmed that no native or community-supported plugins are currently available.&lt;/p&gt;

&lt;p&gt;As a result, I evaluated alternative Node.js process managers that support Windows environments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Forever&lt;/strong&gt; – lightweight but lacks advanced features like monitoring and clustering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NSSM (Non-Sucking Service Manager)&lt;/strong&gt; – effective for converting scripts to Windows services, though limited in logs and ecosystem integration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Windows Task Scheduler&lt;/strong&gt; – native but lacks real-time monitoring and isn't CI/CD friendly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unfortunately, none of the alternatives offer the robustness and features of PM2, particularly in CI/CD pipelines running on Windows.&lt;/p&gt;

&lt;p&gt;I’m sharing this update for awareness and future reference. If there’s a more effective service/process manager that supports background execution for Node.js apps within Jenkins on Windows, I’m open to exploring it and sharing further findings.&lt;/p&gt;

&lt;p&gt;Here is a snapshot of 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%2Flh5wvxpol3b8px6fgd1l.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%2Flh5wvxpol3b8px6fgd1l.png" alt="Image description" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks,&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Horla (Jahmeeu-Cloud)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Cloud &amp;amp; DevOps Engineer  &lt;/p&gt;

&lt;h1&gt;
  
  
  DevOps #CloudEngineering #CICD #Jenkins #NodeJS #Automation #ProcessManager #PM2 #WindowsDevOps #BuildInPublic #TechCommunity
&lt;/h1&gt;

</description>
      <category>node</category>
      <category>pm2</category>
      <category>jenkins</category>
      <category>processmanager</category>
    </item>
    <item>
      <title>Infrastructure as a Code (IaC); AWS CloudFormation: Automating Infrastructure Setup</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Tue, 08 Apr 2025 15:01:56 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/infrastructure-as-a-code-iac-aws-cloudformation-automating-infrastructure-setup-dnd</link>
      <guid>https://forem.com/jamiu_cloud/infrastructure-as-a-code-iac-aws-cloudformation-automating-infrastructure-setup-dnd</guid>
      <description>&lt;p&gt;AWS CloudFormation is a powerful tool that allows you to define and provision AWS infrastructure as code. In this blog post, I’ll walk you through setting up a complete infrastructure using CloudFormation, including a VPC, Subnet, Route Table, Security Group, and EC2 Instance. I’ll also demonstrate how CloudFormation detects drift when resources are modified outside of the stack.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;What I’ll Build&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Using CloudFormation, we’ll create:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;VPC&lt;/strong&gt; with DNS support enabled.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Subnet&lt;/strong&gt; within the VPC.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;Internet Gateway&lt;/strong&gt; and a &lt;strong&gt;Route Table&lt;/strong&gt; for public access.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Security Group&lt;/strong&gt; to allow SSH and HTTP traffic.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;EC2 Instance&lt;/strong&gt; running Amazon Linux 2.&lt;/li&gt;
&lt;li&gt;Drift detection to monitor changes made outside of CloudFormation.&lt;/li&gt;
&lt;/ul&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;CloudFormation Template&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Here’s the YAML template used to define the infrastructure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;AWSTemplateFormatVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2010-09-09"&lt;/span&gt;
&lt;span class="na"&gt;Description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;This is my first AWS CloudFormation template&lt;/span&gt;

&lt;span class="na"&gt;Resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;myVPC&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::VPC&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;CidrBlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;38.0.0.0/16&lt;/span&gt;
      &lt;span class="na"&gt;EnableDnsSupport&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;true'&lt;/span&gt;
      &lt;span class="na"&gt;EnableDnsHostnames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;true'&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stack&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;

  &lt;span class="na"&gt;mySubnet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::Subnet&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
      &lt;span class="na"&gt;CidrBlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;38.0.0.0/16&lt;/span&gt;
      &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;myVPC&lt;/span&gt;
      &lt;span class="na"&gt;AvailabilityZone&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;us-east-1a&lt;/span&gt;
      &lt;span class="na"&gt;MapPublicIpOnLaunch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;true'&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stack&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;

  &lt;span class="na"&gt;myInternetGateway&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::InternetGateway&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stack&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;

  &lt;span class="na"&gt;myInternetGatewayAttachment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::VPCGatewayAttachment&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;myVPC&lt;/span&gt;
      &lt;span class="na"&gt;InternetGatewayId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;myInternetGateway&lt;/span&gt;

  &lt;span class="na"&gt;myRouteTable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::RouteTable&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;myVPC&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stack&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;

  &lt;span class="na"&gt;myRoute&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::Route&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;RouteTableId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;myRouteTable&lt;/span&gt;
      &lt;span class="na"&gt;DestinationCidrBlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
      &lt;span class="na"&gt;GatewayId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;myInternetGateway&lt;/span&gt;

  &lt;span class="na"&gt;mySubnetRouteTableAssociation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::SubnetRouteTableAssociation&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;SubnetId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;mySubnet&lt;/span&gt;
      &lt;span class="na"&gt;RouteTableId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;myRouteTable&lt;/span&gt;

  &lt;span class="na"&gt;mySecurityGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::SecurityGroup&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;GroupDescription&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Allow SSH and HTTP access&lt;/span&gt;
      &lt;span class="na"&gt;VpcId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;myVPC&lt;/span&gt;
      &lt;span class="na"&gt;SecurityGroupIngress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;IpProtocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tcp&lt;/span&gt;
          &lt;span class="na"&gt;FromPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;
          &lt;span class="na"&gt;ToPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;22&lt;/span&gt;
          &lt;span class="na"&gt;CidrIp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;IpProtocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tcp&lt;/span&gt;
          &lt;span class="na"&gt;FromPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
          &lt;span class="na"&gt;ToPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
          &lt;span class="na"&gt;CidrIp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
      &lt;span class="na"&gt;SecurityGroupEgress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;IpProtocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
          &lt;span class="na"&gt;FromPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
          &lt;span class="na"&gt;ToPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-1&lt;/span&gt;
          &lt;span class="na"&gt;CidrIp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0.0.0.0/0&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stack&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;

  &lt;span class="na"&gt;myEC2Instance&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::EC2::Instance&lt;/span&gt;
    &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;InstanceType&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;t2.micro&lt;/span&gt;
      &lt;span class="na"&gt;ImageId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ami-00a929b66ed6e0de6&lt;/span&gt; 
      &lt;span class="na"&gt;SubnetId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;mySubnet&lt;/span&gt;
      &lt;span class="na"&gt;SecurityGroupIds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;mySecurityGroup&lt;/span&gt;
      &lt;span class="na"&gt;Tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Name&lt;/span&gt;
          &lt;span class="na"&gt;Value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;MyEC2Instance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2Fx0f8ye78vc19pn70879z.jpeg" 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%2Fx0f8ye78vc19pn70879z.jpeg" alt="Image description" width="800" height="340"&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%2Fssfxqenknck0u8ymigwo.jpeg" 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%2Fssfxqenknck0u8ymigwo.jpeg" alt="Image description" width="800" height="378"&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%2F9h06cf3tq7gict0vx57g.jpeg" 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%2F9h06cf3tq7gict0vx57g.jpeg" alt="Image description" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This snapshot shows; Deployment is completely created.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Deploying the Stack&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Save the template as &lt;code&gt;cloudformation-template.yml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use the AWS Management Console or CLI to deploy the stack:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   aws cloudformation create-stack &lt;span class="nt"&gt;--stack-name&lt;/span&gt; MyStack &lt;span class="nt"&gt;--template-body&lt;/span&gt; file://cloudformation-template.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Once deployed, you’ll see the resources in the &lt;strong&gt;Stack Resources&lt;/strong&gt; tab of the CloudFormation console.&lt;/li&gt;
&lt;/ol&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Snapshots of the Setup&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Table View&lt;/strong&gt;: The CloudFormation console provides a detailed table view of all resources created by the stack, including their status and logical IDs.&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%2Fiivxw8inl2xlpout3jet.jpeg" 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%2Fiivxw8inl2xlpout3jet.jpeg" alt="Image description" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;EC2 Instance Running&lt;/strong&gt;: After deployment, the EC2 instance will be running and accessible via SSH or HTTP, depending on the security group rules.&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%2Fdhcwyqbp5obdvmo7jicp.jpeg" 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%2Fdhcwyqbp5obdvmo7jicp.jpeg" alt="Image description" width="800" height="358"&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%2Fw6ysd7phs3tn5nktpsds.jpeg" 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%2Fw6ysd7phs3tn5nktpsds.jpeg" alt="Image description" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Canva View&lt;/strong&gt;: The CloudFormation Designer offers a visual representation of the stack, showing the relationships between resources.&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%2Fmualvxhgd70tds7bu6vr.jpeg" 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%2Fmualvxhgd70tds7bu6vr.jpeg" alt="Image description" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Drift Detection&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;CloudFormation Drift Detection is a feature that identifies changes made to stack resources outside of CloudFormation. For example, When I manually deleted the EC2 instance, CloudFormation will detect the drift.&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%2F96h4qinxzxxo4hirblye.jpeg" 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%2F96h4qinxzxxo4hirblye.jpeg" alt="Image description" width="800" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is when I purposely terminated to know if it will be drifted as you can see the snapshot.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Trigger Drift Detection&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the CloudFormation console.&lt;/li&gt;
&lt;li&gt;Select the stack and click &lt;strong&gt;Drift Detection&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Drifted Signal&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The EC2 instance is deleted, the stack will show a &lt;strong&gt;Drifted&lt;/strong&gt; status.&lt;/li&gt;
&lt;li&gt;The drift report will highlight the missing EC2 instance.&lt;/li&gt;
&lt;/ul&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%2F6bciuo5axr4ypvfamj3h.jpeg" 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%2F6bciuo5axr4ypvfamj3h.jpeg" alt="Image description" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is when it drifted as you can see the snapshot.&lt;/p&gt;




&lt;h4&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;AWS CloudFormation simplifies infrastructure management by allowing you to define resources as code. With features like drift detection, you can ensure your infrastructure remains consistent with your template. This setup is a great starting point for automating your AWS environment.&lt;/p&gt;

&lt;p&gt;Feel free to share your thoughts or ask questions in the comments below! 😊&lt;/p&gt;

&lt;h1&gt;
  
  
  AWS #CloudFormation #InfrastructureAsCode #DevOps #Automation #CloudComputing
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>cloudformation</category>
      <category>automation</category>
      <category>devops</category>
    </item>
    <item>
      <title>Budget Backup Buddy: Safeguarding Your Business, One File at a Time – A Real-Life Solution for SMEs and Freelancers</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Wed, 02 Apr 2025 11:28:39 +0000</pubDate>
      <link>https://forem.com/jamiu_cloud/budget-backup-buddy-safeguarding-your-business-one-file-at-a-time-a-real-life-solution-for-smes-1bad</link>
      <guid>https://forem.com/jamiu_cloud/budget-backup-buddy-safeguarding-your-business-one-file-at-a-time-a-real-life-solution-for-smes-1bad</guid>
      <description>&lt;p&gt;Greetings from My Blogspot! 🌥️ As a Professional Cloud Engineer, I’m excited to share a practical, real-world solution with you. Join me as we explore this journey together – be sure to read through to the end for the full insights! 🚀&lt;/p&gt;

&lt;p&gt;Excited to kick off Project Budget Backup Buddy this April – a game-changer for SMEs, freelancers, and startups! Over the next 30 days, I’m building an affordable, automated backup solution using AWS S3 and Lambda that keeps your data safe without breaking the bank (think under $5/month). Here’s why this matters and how it can help YOU. 💡&lt;/p&gt;

&lt;h3&gt;
  
  
  Real Life Scenario: The Freelance Photographer’s Rescue 📸
&lt;/h3&gt;

&lt;p&gt;Meet Sarah, a freelance photographer who runs her small business, Sarah’s Snaps, from her home. She takes stunning photos for weddings, family portraits, and local events. &lt;/p&gt;

&lt;p&gt;All her work – thousands of high-resolution images – lives on her aging laptop and an external hard drive she keeps in a drawer. One rainy afternoon, a power surge fries her laptop, and she discovers her hard drive got knocked off the table and won’t turn on. &lt;/p&gt;

&lt;p&gt;Months of client photos, her portfolio, and even her pricing spreadsheets are gone. Sarah’s devastated – she’s lost work, trust from clients, and hours of effort. No backups, no plan, just a sinking feeling. 😞&lt;/p&gt;




&lt;p&gt;Now, imagine Sarah had Budget Backup Buddy. &lt;/p&gt;

&lt;h3&gt;
  
  
  As a Cloud Engineer and Problem Solver, Here’s how I would have saved her: 🛠️
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Simple Setup:&lt;/strong&gt; Sarah signs up for AWS (free tier to start) and creates a “bucket” – think of it as a super-secure online folder called sarahs-snaps-backup. ☁️  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drag-and-Drop Magic:&lt;/strong&gt; She drags her photo folders into this bucket from her new laptop. No fancy tech skills needed – it’s like uploading to Google Drive. 📤  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation Kicks In:&lt;/strong&gt; The moment she uploads, a tiny program (Lambda) notices and logs it. She doesn’t even have to think about it – it’s automatic. ⚙️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost Slasher:&lt;/strong&gt; After 30 days, older photos slide into a cheaper storage spot (Glacier) – still safe, just costing her pennies instead of dollars. Her bill? Under $5 a month. 💵  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Peace of Mind:&lt;/strong&gt; Next time her laptop hiccups, Sarah logs into AWS, downloads her files, and keeps working. No tears, no lost clients. 💪&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;How It Benefits Sarah (and SMEs/Startups):&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Affordable:&lt;/strong&gt; At under $5/month, it’s cheaper than a coffee run – perfect for a freelancer or a startup watching every penny. ☕
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time-Saving:&lt;/strong&gt; No manual copying to USBs or worrying about hardware failing – it’s hands-off. ⏳
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trust Builder:&lt;/strong&gt; Clients love knowing their wedding pics or project files are safe, giving Sarah a professional edge. ✅
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalable:&lt;/strong&gt; As Sarah’s Snaps grows into a full studio, the system grows with her, handling more files without a fuss. 📈&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Technical Role:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;As a Professional Cloud Engineer, I’ll design, build, and deploy a cost-effective, automated backup system using AWS services. My role combines basic cloud architecture, scripting, and automation to create a solution tailored for SMEs, freelancers, and startups. 🖥️🔧&lt;/p&gt;




&lt;p&gt;For a layman like Sarah, this isn’t “cloud tech jargon” – it’s a lifeline. She doesn’t need to know Python or AWS lingo; she just needs her work protected. That’s what Budget Backup Buddy delivers – a simple, cheap, set-it-and-forget-it fix for real people with real businesses. 🌟&lt;/p&gt;

&lt;p&gt;Stay tuned for my next article, where I’ll walk you through the step-by-step process of setting up and deploying this project. As a professional cloud engineer, I’ll guide you in building and automating your own cost-effective backup solution using AWS services. Don’t miss out! 🚀💻☁️&lt;/p&gt;

&lt;h1&gt;
  
  
  cloudbackup #AWS #SMBsolutions #freelancers #startups #backupbuddy #cloudengineer #datarecovery #CloudComputing #AWS #DataBackup #CloudSolutions #SMEs #Freelancers #Startups #TechSolutions #Automation #CloudEngineering #BackupSolutions #DataSecurity #DisasterRecovery #TechForBusiness #SmallBusinessTech #Innovation #BusinessContinuity #TechForGood #DigitalTransformation #CostEffectiveTech #CloudArchitecture
&lt;/h1&gt;

</description>
      <category>aws</category>
      <category>awss3bucket</category>
      <category>awslambda</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
