<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: BAKRE JAMIU</title>
    <description>The latest articles on DEV Community by BAKRE JAMIU (@jamiu_cloud).</description>
    <link>https://dev.to/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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2032476%2F7b90aad0-a783-4dfa-aa65-4b7f12a24be4.jpg</url>
      <title>DEV Community: BAKRE JAMIU</title>
      <link>https://dev.to/jamiu_cloud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jamiu_cloud"/>
    <language>en</language>
    <item>
      <title>I’m Learning Kubernetes—Here Are the Mistakes I Made So You Don’t Have To</title>
      <dc:creator>BAKRE JAMIU</dc:creator>
      <pubDate>Sun, 30 Aug 2026 01:26:51 +0000</pubDate>
      <link>https://dev.to/jamiu_cloud/im-learning-kubernetes-here-are-the-mistakes-i-made-so-you-dont-have-to-e8i</link>
      <guid>https://dev.to/jamiu_cloud/im-learning-kubernetes-here-are-the-mistakes-i-made-so-you-dont-have-to-e8i</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;If you have ever stared at a Pod stuck in ContainerCreating and wondered what you did wrong, this one is for you. These are the mistakes I made while learning Kubernetes — and the lessons that finally clicked.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;There is a version of Kubernetes that exists in beginner tutorials, and there is the version you meet when you actually start using it. In the tutorial version, everything looks clean: create a Pod, expose a Service, scale replicas, move on. In real life, there are drivers that are missing, Docker permissions that block you, images that take time to pull, Services that do not exist yet, namespaces that quietly change what you are looking at, and Pods that disappear only to come back because Kubernetes is doing exactly what it was designed to do.&lt;/p&gt;

&lt;p&gt;This is not a story about becoming a Kubernetes expert overnight. It is a story about getting my hands dirty, making honest mistakes, troubleshooting them one by one, and gradually understanding why organizations trust Kubernetes to run production workloads.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faw4b22i400sq9p419cbz.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Faw4b22i400sq9p419cbz.png" alt=" " width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  1. My starting point
&lt;/h2&gt;

&lt;p&gt;I started by learning the foundations: what Kubernetes is, why companies use it, what a cluster is, the difference between the control plane and worker nodes, what nodes and Pods are, how containers differ from Pods, and how Docker and Kubernetes relate to each other. I also worked with &lt;code&gt;kubectl&lt;/code&gt;, Minikube, namespaces, Deployments, ReplicaSets, Services, scaling, Helm, and later Kubeshark.&lt;/p&gt;

&lt;p&gt;On paper, that list looked manageable. In practice, every concept became clearer only when it broke in front of me.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. What I thought Kubernetes was (and what I misunderstood)
&lt;/h2&gt;

&lt;p&gt;At the beginning, I thought Kubernetes was basically Docker at a bigger scale. That assumption did not survive long. The more I used it, the more I saw that Kubernetes is not mostly about starting containers. It is about describing a &lt;strong&gt;desired state and letting the cluster&lt;/strong&gt; keep moving toward that state.&lt;/p&gt;

&lt;p&gt;A few of my early wrong assumptions:&lt;/p&gt;

&lt;p&gt;Minikube would just start, without needing a supported driver or runtime such as Docker.&lt;br&gt;
A Pod in &lt;code&gt;ContainerCreating&lt;/code&gt; meant something was definitely broken.&lt;br&gt;
Deleting a Pod meant I had removed the application.&lt;br&gt;
I could use &lt;code&gt;minikube service&lt;/code&gt; before creating any Service.&lt;br&gt;
Every failure during Helm or Kubeshark setup had to be a Kubernetes problem.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. Setup: Minikube, Docker, and permissions
&lt;/h2&gt;

&lt;p&gt;One of my first real lessons came from setup. I tried &lt;code&gt;minikube start&lt;/code&gt; before having a supported driver installed. That reminded me: Kubernetes on a laptop still depends on what is underneath it. Minikube is not magic. It needs a runtime/driver to create and run the local cluster.&lt;/p&gt;

&lt;p&gt;Then came Docker permission issues, which led me to learn about the Docker group and why a user gets blocked from Docker commands until the right permissions are in place.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Early Cloud/DevOps lesson: when something “Kubernetes-related” fails, it is sometimes the environment around Kubernetes that needs attention first.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  4. My first Pod and the patience it taught me
&lt;/h2&gt;

&lt;p&gt;I created an &lt;strong&gt;NGINX Pod&lt;/strong&gt; and saw it sit in &lt;code&gt;ContainerCreating&lt;/code&gt;. My first instinct was that something was wrong. Eventually it became &lt;code&gt;Running&lt;/code&gt;. That moment sounded small, but it mattered. Container images may need to be downloaded, Internet access matters, and a Pod &lt;strong&gt;not&lt;/strong&gt; being ready immediately does not automatically mean failure.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The lesson: instead of treating every delay as an error, I started asking, “What is Kubernetes doing right now?”&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  5. Deployments, ReplicaSets, and reconciliation
&lt;/h2&gt;

&lt;p&gt;The biggest “click” moment came when I deleted a Pod and watched Kubernetes recreate it. I had deleted a Pod that was managed by a Deployment. The Deployment still wanted the desired number of replicas, so the cluster created another Pod to bring the state back in line.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F784kfjau939pg7v7m094.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F784kfjau939pg7v7m094.png" alt=" " width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That single experience taught me more than several pages of explanation could. It made Deployments, ReplicaSets, and reconciliation feel real.&lt;/p&gt;
&lt;h2&gt;
  
  
  6. Services — and how I learned what &lt;code&gt;SVC_NOT_FOUND&lt;/code&gt; really means
&lt;/h2&gt;

&lt;p&gt;Services answered a question I kept running into: how do I reliably reach an application when Pods are temporary? A Pod can be recreated and get a different IP. A Service gives that changing set of Pods a stable endpoint.&lt;/p&gt;

&lt;p&gt;I learned this 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;minikube service nginx &lt;span class="nt"&gt;-n&lt;/span&gt; development
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;before I had created any Service. The response was SVC_NOT_FOUND. My assumption was the bug, not Minikube. The fix was to create the Service explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl expose pod nginx &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NodePort &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  7. Scaling
&lt;/h2&gt;

&lt;p&gt;Scaling replicas sounds simple when you read it, but it becomes more meaningful when you watch it happen. Increasing replica count means the Deployment updates the ReplicaSet, and the ReplicaSet creates more Pods until the cluster reaches the new desired count. That is when Kubernetes starts feeling less like manual container management and more like orchestration.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Troubleshooting  🛠️
&lt;/h2&gt;

&lt;p&gt;The most valuable part of this journey has been troubleshooting. Good troubleshooting is not random trial and error. It is a sequence:&lt;/p&gt;

&lt;p&gt;Read the error.&lt;br&gt;
Question the assumption behind the step.&lt;br&gt;
Inspect the cluster state.&lt;br&gt;
Compare expected behavior with actual behavior.&lt;br&gt;
Isolate the real cause.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fid2yoe26j3apaxksto7d.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fid2yoe26j3apaxksto7d.png" alt=" " width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Helm &amp;amp; Kubeshark — and the layer-aware lesson
&lt;/h2&gt;

&lt;p&gt;Helm clicked for me as a package manager for Kubernetes. Then came Kubeshark. I ran into repository connectivity problems and almost blamed Kubernetes immediately. The more useful question was: is this a cluster problem, or is the repository itself unreachable from my environment?&lt;/p&gt;

&lt;p&gt;curl -I &lt;a href="https://helm.kubeshark.com/index.yaml" rel="noopener noreferrer"&gt;https://helm.kubeshark.com/index.yaml&lt;/a&gt;&lt;br&gt;
curl -I &lt;a href="https://google.com" rel="noopener noreferrer"&gt;https://google.com&lt;/a&gt;&lt;br&gt;
curl -I &lt;a href="https://github.com" rel="noopener noreferrer"&gt;https://github.com&lt;/a&gt;&lt;br&gt;
curl -I &lt;a href="https://raw.githubusercontent.com" rel="noopener noreferrer"&gt;https://raw.githubusercontent.com&lt;/a&gt;&lt;br&gt;
That comparison mattered. It helped me distinguish between “my Kubernetes or Helm setup is broken” and “this particular external repository cannot be reached.” Systems fail in layers. Good troubleshooting means identifying which layer is actually failing.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Mistakes I made — and what each one taught me
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;MISTAKE&lt;/th&gt;
&lt;th&gt;LESSON&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Starting Minikube without a supported driver&lt;/td&gt;
&lt;td&gt;Kubernetes tools still depend on the host environment. Drivers, runtimes, and permissions matter.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Treating &lt;code&gt;ContainerCreating&lt;/code&gt; as immediate failure&lt;/td&gt;
&lt;td&gt;Sometimes the image is still downloading. Read the state in context and inspect events before panicking.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trying &lt;code&gt;minikube service&lt;/code&gt; before creating a Service&lt;/td&gt;
&lt;td&gt;A Pod is not automatically a Service. Reachability needs to be defined explicitly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deleting a Pod and expecting the app to be gone&lt;/td&gt;
&lt;td&gt;Deployments preserve the desired replica count. Delete the Deployment if you want the managed Pods to stop returning.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Working in the wrong namespace&lt;/td&gt;
&lt;td&gt;Always confirm the namespace context. Resources can be healthy while you are looking in the wrong place.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Assuming every Helm/Kubeshark issue was a Kubernetes issue&lt;/td&gt;
&lt;td&gt;Sometimes the real problem is repository/network access outside the cluster. Verify the failing layer.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  11. Commands that actually helped me
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;minikube start
kubectl get pods &lt;span class="nt"&gt;-A&lt;/span&gt;
kubectl get deployments &lt;span class="nt"&gt;-A&lt;/span&gt;
kubectl get services &lt;span class="nt"&gt;-A&lt;/span&gt;
kubectl describe pod &amp;lt;pod-name&amp;gt;
kubectl logs &amp;lt;pod-name&amp;gt;
kubectl get deployment nginx-deployment &lt;span class="nt"&gt;-o&lt;/span&gt; yaml
kubectl expose pod nginx &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;NodePort &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80
minikube service &amp;lt;service-name&amp;gt; &lt;span class="nt"&gt;--url&lt;/span&gt;
curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://helm.kubeshark.com/index.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  12. Lessons for other beginners
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Do not rush past the basic architecture. Knowing the relationship between Deployments, ReplicaSets, Pods, and Services saves time later.&lt;/li&gt;
&lt;li&gt;Read the exact error message before trying random commands.&lt;/li&gt;
&lt;li&gt;Check namespaces early. It is one of the easiest ways to eliminate confusion.&lt;/li&gt;
&lt;li&gt;If a Pod is managed by a Deployment, deleting the Pod is not the same as deleting the application.&lt;/li&gt;
&lt;li&gt;When troubleshooting, identify the failing layer: local machine, Docker runtime, Minikube, Kubernetes resource, network access, or external repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I now understand
&lt;/h2&gt;

&lt;p&gt;Kubernetes is not about micromanaging containers. It is about declaring state, letting the cluster maintain it, and using higher-level abstractions to make applications resilient and reachable.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6juf8hiv5c8an50zmdum.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6juf8hiv5c8an50zmdum.png" alt=" " width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I still need to learn
&lt;/h2&gt;

&lt;p&gt;There is still a lot ahead: Ingress, ConfigMaps, Secrets, persistent storage, observability, production-grade networking, security, and more advanced debugging patterns. The basics are no longer abstract terms — they now connect to things I have actually seen fail and recover.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next stop: Kubernetes Ingress 🚦
&lt;/h2&gt;

&lt;p&gt;Ingress is the natural next topic because it ties everything together. Pods run the application, Services give a stable way to reach those Pods inside the cluster, and Ingress sits above that to route external HTTP/HTTPS traffic to the right Service. If Services help internal reachability, Ingress helps organize external access more cleanly.&lt;/p&gt;

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

&lt;p&gt;Every time Minikube refused to start, every time a Pod sat in &lt;code&gt;ContainerCreating&lt;/code&gt;, every time a Service did not exist yet, every time a namespace caused confusion, every time a Pod came back after I deleted it — Kubernetes was teaching me something useful.&lt;/p&gt;

&lt;p&gt;I thought learning Kubernetes would mostly be about commands. I was wrong. It has been more about systems thinking, careful troubleshooting, and learning how to ask better questions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Next stop:&lt;/strong&gt; Kubernetes Ingress — understanding how external traffic reaches Services, and through them, the Pods behind the application.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kubernetes</category>
      <category>docker</category>
      <category>kubeshark</category>
      <category>containers</category>
    </item>
    <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://dev.to/jamiu_cloud/ansible-learning-journey-from-manual-ssh-to-automation-thinking-2a2o</link>
      <guid>https://dev.to/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://dev.to/jamiu_cloud/my-ongoing-cloud-migration-journey-3i1a</link>
      <guid>https://dev.to/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://dev.to/jamiu_cloud/building-a-scalable-aws-e-learning-platform-for-government-use-hb5</link>
      <guid>https://dev.to/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://dev.to/jamiu_cloud/optimizing-costs-without-downtime-my-hands-on-experience-downgrading-aws-lightsail-a-jaf</link>
      <guid>https://dev.to/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://dev.to/jamiu_cloud/how-i-deployed-a-python-flask-app-with-docker-and-troubleshot-my-way-to-victory-1io5</link>
      <guid>https://dev.to/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://dev.to/jamiu_cloud/from-concept-to-container-my-journey-deploying-mongodb-mongo-express-with-docker-no-docker-3ec5</link>
      <guid>https://dev.to/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://dev.to/jamiu_cloud/how-i-achieved-my-project-deploying-docker-images-to-amazon-elastic-container-registry-ecr-4mo3</link>
      <guid>https://dev.to/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://dev.to/jamiu_cloud/getting-started-with-docker-from-installation-to-pushing-images-to-docker-hub-4of6</link>
      <guid>https://dev.to/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://dev.to/jamiu_cloud/how-i-deployed-my-static-website-using-github-actions-52f5</link>
      <guid>https://dev.to/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://dev.to/jamiu_cloud/pm2-integration-with-jenkins-on-windows-observations-and-alternative-recommendations-4hl9</link>
      <guid>https://dev.to/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://dev.to/jamiu_cloud/infrastructure-as-a-code-iac-aws-cloudformation-automating-infrastructure-setup-dnd</link>
      <guid>https://dev.to/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>
  </channel>
</rss>
