<?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: Shubham Tiwary</title>
    <description>The latest articles on DEV Community by Shubham Tiwary (@sardinessz).</description>
    <link>https://dev.to/sardinessz</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1481308%2F7f1f675d-3bae-4808-afdf-68805fbdd1c9.jpeg</url>
      <title>DEV Community: Shubham Tiwary</title>
      <link>https://dev.to/sardinessz</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sardinessz"/>
    <language>en</language>
    <item>
      <title>deploying a express.js + react web-app on vercel</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Fri, 14 Nov 2025 16:27:39 +0000</pubDate>
      <link>https://dev.to/sardinessz/deploying-a-expressjs-react-web-app-on-vercel-2k9</link>
      <guid>https://dev.to/sardinessz/deploying-a-expressjs-react-web-app-on-vercel-2k9</guid>
      <description>&lt;p&gt;Services like &lt;a href="https://vercel.com/uu-cscs-projects" rel="noopener noreferrer"&gt;Vercel&lt;/a&gt; and &lt;a href="https://render.com/" rel="noopener noreferrer"&gt;Render&lt;/a&gt; is pretty damn good for deploying your web-app especially if you have a low usage or for prototyping, and I recently had to get this done, so might as well document it here.&lt;/p&gt;

&lt;p&gt;First, let's start with the express.js backend.&lt;/p&gt;




&lt;h3&gt;
  
  
  Starting with the express.js backend
&lt;/h3&gt;

&lt;p&gt;Let's say you have a GitHub repo with backend/ folder having a npm package with your express app,&lt;br&gt;
where the &lt;code&gt;server.js&lt;/code&gt; is the main file to handle that, which should look like this:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;//all your middlewares, routes, controllers, etc...&lt;/span&gt;


&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of defining the port, just export the express app object, vercel handles running that.&lt;/p&gt;

&lt;p&gt;Then define a &lt;code&gt;vercel.json&lt;/code&gt; file to pinpoint the config that the &lt;code&gt;server.js&lt;/code&gt; file is the main source (same dir as package.json in backend/):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"builds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"use"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@vercel/node"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/(.*)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"dest"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"server.js"&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although vercel by &lt;strong&gt;default looks for index(.ts/.js) or server(.ts/.js)&lt;/strong&gt;, its better to be explicit about it.&lt;/p&gt;



&lt;p&gt;That's all the config you need, &lt;strong&gt;now just create a new project in your vercel account&lt;/strong&gt; (connect with GitHub first):&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%2Foci1jh8ur960eor6c303.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foci1jh8ur960eor6c303.png" alt="vercel new project define" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;There's three main config:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;framework preset&lt;/strong&gt;: choose express&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;build &amp;amp; output&lt;/strong&gt;: leave default&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;env&lt;/strong&gt;:  pass your &lt;code&gt;.env&lt;/code&gt; file details, that can be access in app as &lt;code&gt;process.env.&amp;lt;ENV&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And then test your application works!&lt;/p&gt;




&lt;h3&gt;
  
  
  React.js frontend deployment
&lt;/h3&gt;

&lt;p&gt;There's relatively little config needed for react, I'm using &lt;strong&gt;vite&lt;/strong&gt; here, but it's the for &lt;strong&gt;create react app&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Back on the vercel new project:&lt;/p&gt;

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

&lt;p&gt;Use the framework preset as react app/vite, it will handle the build output by itself (vite build or react build accordingly)&lt;/p&gt;

&lt;p&gt;Now for env, it's usually best practice to have the API endpoint address to backend in a env, so let's assume you have &lt;code&gt;API_URL&lt;/code&gt; as the API path to backend.&lt;/p&gt;

&lt;p&gt;From the express deployment earlier, get the address:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84q2jz0rbjtc0f9i6ssz.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F84q2jz0rbjtc0f9i6ssz.webp" alt="vercel project domains" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then pass inside "Environment Variables" the &lt;code&gt;API_URL&lt;/code&gt; while making the frontend deployment.&lt;/p&gt;

&lt;p&gt;Now test your apps and see if they both work well.. (mention below if they don't)&lt;/p&gt;




&lt;p&gt;Some good practices to just have for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;use &lt;strong&gt;CORS(cross origin) blocking&lt;/strong&gt; in your express server (in deployment mode), and &lt;strong&gt;whitelist apps that need access&lt;/strong&gt; like your react app, so user can't direct make API calls. Maybe have a &lt;strong&gt;"MODE" env&lt;/strong&gt; value for this logic handling.&lt;/li&gt;
&lt;li&gt;like mentioned, &lt;strong&gt;decouple variables like configs, addresses&lt;/strong&gt;, ports, etc into envs and pass em' later&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;use typescript instead&lt;/strong&gt;, will save you a lot of headache on issue you'll see in prod but not in dev, better to get way more possible errors than way less. &lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>vercel</category>
      <category>express</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Running a lightweight Kubernetes (K8s) cluster locally with K3s</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Mon, 27 Oct 2025 17:18:48 +0000</pubDate>
      <link>https://dev.to/sardinessz/running-local-kubernetes-k8s-cluster-with-k3s-2p8l</link>
      <guid>https://dev.to/sardinessz/running-local-kubernetes-k8s-cluster-with-k3s-2p8l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; This articles expects you already know bits about K8s and wanna setup local cluster with 1 or more node, but even if you aren't familiar with K8s, you can still follow along..&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Context on K3s
&lt;/h2&gt;

&lt;p&gt;Kubernetes is amazing to run with managed services like &lt;strong&gt;AWS EKS&lt;/strong&gt; or &lt;strong&gt;GCP GKE&lt;/strong&gt; in production, but making changes in production cluster directly might not be a good idea since:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Testing in a dev environment is much faster and better practice&lt;/li&gt;
&lt;li&gt;When learning K8s initially, it's better to avoid unnecessary cloud bills&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
So that's where K3s comes in, it can let you run local K8s clusters with &amp;gt;=1 node and give you consistent production like environment!&lt;br&gt;
There's also other tools like &lt;strong&gt;minikube&lt;/strong&gt;, &lt;strong&gt;kinD&lt;/strong&gt; that you'll find in the offical &lt;a href="https://kubernetes.io/docs/tasks/tools/" rel="noopener noreferrer"&gt;K8s tool guide&lt;/a&gt;&lt;br&gt;
but I'd still recommend this since:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;kinD&lt;/strong&gt; runs on your system's docker's daemon, not with K8s containerd runtime, it's better to have that seperate and not mixup your docker containers here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;minikube&lt;/strong&gt; has experimental support for multi node cluster&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;So how is K3s different from K8s&lt;/strong&gt;&lt;br&gt;
I built a &lt;a href="https://github.com/ShubhamTiwary914/logcore-v2" rel="noopener noreferrer"&gt;project here&lt;/a&gt; recently to deploy to GKE and tested with K3s locally first, so here's what I can say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KubeAPI metrics for K8s are all supported.&lt;/li&gt;
&lt;li&gt;All objects like pods,namespaces,service, everything is the same!&lt;/li&gt;
&lt;li&gt;Only difference is etcd store --&amp;gt; uses sqlite instead (which can also be configured to etcd, MySQL, etc)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;It's at the end of the day, a K8s binary for running even in low end devices like ARM based Pi, or normal x86.64 systems!&lt;/em&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Setup K3s in single node
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;K3s already installs dependencies like kubectl so you can follow along even if you may or may not already have that&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;&lt;strong&gt;Only if you have firewall rules enabled on local machine&lt;/strong&gt;&lt;br&gt;
To setup, we'll first need to allow some firewall rules to allow the socket for Kubernetes API server.&lt;/p&gt;

&lt;p&gt;I'm assuming you have &lt;strong&gt;ufw&lt;/strong&gt; or some other firewall tool, so here are the rules you need to enable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;6443/tcp                   ALLOW       Anywhere                   &lt;span class="c"&gt;# K8s API server&lt;/span&gt;
10250/tcp                  ALLOW       Anywhere                   &lt;span class="c"&gt;# K8s worker node kubelet metrics&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the install script for K3s from the &lt;a href="https://docs.k3s.io/installation/requirements" rel="noopener noreferrer"&gt;official k3s quick start guide&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-sfL&lt;/span&gt; https://get.k3s.io | sh -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, you should see a k3s daemon service running if you check with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;systemctl status k3s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What you should see (or something similar):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;● k3s.service - Lightweight Kubernetes
     Loaded: loaded &lt;span class="o"&gt;(&lt;/span&gt;/etc/systemd/system/k3s.service&lt;span class="p"&gt;;&lt;/span&gt; enabled&lt;span class="p"&gt;;&lt;/span&gt; preset: disabled&lt;span class="o"&gt;)&lt;/span&gt;
     Active: active &lt;span class="o"&gt;(&lt;/span&gt;running&lt;span class="o"&gt;)&lt;/span&gt; since Mon 2025-10-27 21:43:25 IST&lt;span class="p"&gt;;&lt;/span&gt; 32min ago
 Invocation: bb923ad8337d473da638169bbfe6867f
       Docs: https://k3s.io
    Process: 309939 &lt;span class="nv"&gt;ExecStartPre&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/sbin/modprobe br_netfilter &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0/SUCCESS&lt;span class="o"&gt;)&lt;/span&gt;
    Process: 309940 &lt;span class="nv"&gt;ExecStartPre&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/sbin/modprobe overlay &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;exited, &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0/SUCCESS&lt;span class="o"&gt;)&lt;/span&gt;
   Main PID: 309942 &lt;span class="o"&gt;(&lt;/span&gt;k3s-server&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;K3s also creates a kube-config file in &lt;code&gt;/etc/rancher/k3s/k3s.yaml&lt;/code&gt;. To use this cluster you have to make this path as &lt;code&gt;KUBECONFIG&lt;/code&gt;:&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 chown&lt;/span&gt; &lt;span class="nv"&gt;$USER&lt;/span&gt;:&lt;span class="nv"&gt;$USER&lt;/span&gt; /etc/rancher/k3s/k3s.yaml  &lt;span class="c"&gt;#(if user doesn't have permission)&lt;/span&gt;

&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;KUBECONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/etc/rancher/k3s/k3s.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check if it is working:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get ns

kubectl cluster-info

&lt;span class="c"&gt;#Expected log:&lt;/span&gt;
&lt;span class="c"&gt;#Kubernetes control plane is running at https://127.0.0.1:6443&lt;/span&gt;
&lt;span class="c"&gt;#CoreDNS is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy&lt;/span&gt;
&lt;span class="c"&gt;#Metrics-server is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/https:metrics-server:https/proxy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Testing with running a sample deployment
&lt;/h3&gt;

&lt;p&gt;Run a sample nginx deployment with 3 replicas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create deployment nginx &lt;span class="nt"&gt;--image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nginx &lt;span class="nt"&gt;--replicas&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3

kubectl get deploy
&lt;span class="c"&gt;#expected logs:&lt;/span&gt;
&lt;span class="c"&gt;#NAME    READY   UP-TO-DATE   AVAILABLE   AGE&lt;/span&gt;
&lt;span class="c"&gt;#nginx   3/3     3            3           16s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then expose the service with a ClusterIP:&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 deployment nginx &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80 &lt;span class="nt"&gt;--target-port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80 &lt;span class="nt"&gt;--type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ClusterIP

kubectl get svc

&lt;span class="c"&gt;#expected&lt;/span&gt;
&lt;span class="c"&gt;#NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE&lt;/span&gt;
&lt;span class="c"&gt;#kubernetes   ClusterIP   10.43.0.1    &amp;lt;none&amp;gt;        443/TCP   41m&lt;/span&gt;
&lt;span class="c"&gt;#nginx        ClusterIP   10.43.2.40   &amp;lt;none&amp;gt;        80/TCP    93s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the clusterIP is &lt;code&gt;10.43.2.40&lt;/code&gt; (could be different in yours).&lt;/p&gt;

&lt;p&gt;Let's try calling HTTP with curl onto that port 80:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl 10.43.2.40

&lt;span class="c"&gt;#&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;title&amp;gt;Welcome to nginx!&amp;lt;/title&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;style&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#html { color-scheme: light dark; }&lt;/span&gt;
&lt;span class="c"&gt;#body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; }&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;/style&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;body&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;h1&amp;gt;Welcome to nginx!&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;p&amp;gt;If you see this page, the nginx web server is successfully installed and working. Further configuration is required.&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;#&amp;lt;p&amp;gt;For online documentation and support please refer to&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;a href="http://nginx.org/"&amp;gt;nginx.org&amp;lt;/a&amp;gt;.&amp;lt;br/&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#Commercial support is available at&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;a href="http://nginx.com/"&amp;gt;nginx.com&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;&lt;/span&gt;

&lt;span class="c"&gt;#&amp;lt;p&amp;gt;&amp;lt;em&amp;gt;Thank you for using nginx.&amp;lt;/em&amp;gt;&amp;lt;/p&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;#&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Setup more nodes to connect to cluster (optional) - agent node
&lt;/h3&gt;

&lt;p&gt;So for this, setup any other machine you may have - VMs, physical machine that share a network interface.&lt;/p&gt;

&lt;p&gt;For example, let's say I have another machine connected in same wifi in &lt;code&gt;wlan0&lt;/code&gt; interface,&lt;/p&gt;

&lt;p&gt;And I get this machine's private IP as &lt;code&gt;10.158.66.194/24&lt;/code&gt; when I check with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ip &lt;span class="nt"&gt;-4&lt;/span&gt; addr show
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;K3s exposes a "node token" to connect to clusters, and needs the URL where the host node is, so:&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;export &lt;/span&gt;&lt;span class="nv"&gt;K3S_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://10.158.66.194:6443"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;K3S_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;sudo cat&lt;/span&gt; /var/lib/rancher/k3s/server/node-token&lt;span class="si"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the other machine you run for connecting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -sfL https://get.k3s.io | K3S_URL=https://10.158.66.194:6443 K3S_TOKEN=mynodetoken sh -
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: &lt;code&gt;10.158.66.194&lt;/code&gt; is just a dummy IP for example, check and use what was there for your interface.&lt;/p&gt;

&lt;p&gt;Then check the nodes with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;k8s get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;While in terms of setup, yes &lt;a href="https://kind.sigs.k8s.io/" rel="noopener noreferrer"&gt;kinD&lt;/a&gt; and &lt;a href="https://minikube.sigs.k8s.io/docs/" rel="noopener noreferrer"&gt;minikube&lt;/a&gt; might be easier to configure initially, but once this setup is done, its rather easy to manage and relieves you of all the headaches you may have of "it works locally but not in production".&lt;/p&gt;



&lt;p&gt;If you liked this, give feedback since I write a lot of stuff on my obsidian that I translate and write here, so I can go on more about K8s, devops and other stuff..&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloud</category>
      <category>programming</category>
    </item>
    <item>
      <title>Shrinking docker image size over 100x in just 2 steps</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Mon, 02 Jun 2025 17:47:29 +0000</pubDate>
      <link>https://dev.to/sardinessz/shrinking-docker-image-size-over-100x-in-just-2-steps-3dhj</link>
      <guid>https://dev.to/sardinessz/shrinking-docker-image-size-over-100x-in-just-2-steps-3dhj</guid>
      <description>&lt;p&gt;&lt;strong&gt;Smaller image size helps you:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;make faster builds on your CI&lt;/li&gt;
&lt;li&gt;testing containers becomes faster&lt;/li&gt;
&lt;li&gt;less cost for build jobs / container space &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
. . .&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Here's some quick hacks I found after playing around for a while with docker images&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In this example, I'm &lt;strong&gt;shrinking an image of about ~900 MB to around ~8 MB&lt;/strong&gt; (as tested on my docker)&lt;/p&gt;

&lt;p&gt;For reference, I'll take this simple sample 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; golang&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; main.go .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; server
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; [ "/app/server" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which simply builds a go program, and runs it.&lt;/p&gt;

&lt;p&gt;This sizes around &lt;strong&gt;946 MB&lt;/strong&gt; after building &lt;/p&gt;




&lt;h3&gt;
  
  
  1 - Base Image as Alpine
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Alpine is a very small Linux distro used for containers&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So most images you want to run, will have an alpine base equivalent of them. Where to find them?&lt;/p&gt;

&lt;p&gt;For example, for the golang image from dockerhub:&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%2Fgikd0nr4yoytw6ns361r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgikd0nr4yoytw6ns361r.png" alt="golang dockerhub" width="800" height="825"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can choose the tags here to choose an alpine image.&lt;/p&gt;

&lt;p&gt;So the Dockerfile with alpine base will be:&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; golang:1.24-alpine  #just any alpine tag from the tag list&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; go.mod .&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; main.go .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; server &lt;span class="nt"&gt;-buildvcs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; 
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; [ "/app/server" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this, the image build takes around &lt;strong&gt;353MB&lt;/strong&gt; size &lt;strong&gt;(3x smaller already)&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  2 - Multi Stage builds
&lt;/h3&gt;

&lt;p&gt;I like to think of this like a:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;multistage rocket, where there's multiple sections and after certain intervals, the sections push the rest, cutting itself off, one by one, until there's one final portion left.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;Similarly, suppose in our go-program, &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;we need the go compiler to build it first of all&lt;/li&gt;
&lt;li&gt;once its build, only the executable is needed (compiler or dependencies not needed during runtime may be dropped off)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's look at this with a Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;
&lt;span class="c"&gt;# Stage 1: build&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.24-alpine&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder-stage&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; go.mod .&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; main.go .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; server &lt;span class="nt"&gt;-buildvcs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt; 


&lt;span class="c"&gt;# Stage-2: run&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; scratch&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; --from=builder-stage /app/server /app&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; [ "/app/server" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;In stage-1 -&amp;gt; we build the "server" executable and it will be placed at /app/server  (call this "builder" stage&lt;/li&gt;
&lt;li&gt;Then in 2nd stage -&amp;gt; take that executable from builder stage and simply run it.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;In the 2nd stage, a base image called "scratch" is used, it is even more lightweight than alpine. But only used for cases like this, where there's literally no dependencies needed, just to run.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After this build, only the 2nd stage remains as final image.&lt;/p&gt;

&lt;p&gt;Once we build this, the image size shrinks to &lt;strong&gt;8.15MB&lt;/strong&gt;! &lt;strong&gt;(almost 300x)&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Limitations
&lt;/h3&gt;

&lt;p&gt;This seems too good to be true, and it is yeah. Not for all cases can we optimize up to this extent.&lt;/p&gt;

&lt;p&gt;Some cases, we simply need all the dependencies in run time as in compile time too (ex: interpreted languages like Python - although there's build tools for that, but limited), so it's tricky to use multi stage builds.&lt;/p&gt;



&lt;p&gt;Repositories like Dockerhub also have compression on their end to optimize the size during deployments.&lt;/p&gt;

&lt;p&gt;Even in the case of base image as alpine, some tools might not have great support in alpine &lt;/p&gt;




&lt;h3&gt;
  
  
  Trying it yourself
&lt;/h3&gt;

&lt;p&gt;To replicate the following on your own,&lt;/p&gt;

&lt;p&gt;Here's command to build the Dockerfile:&lt;br&gt;
&lt;/p&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; &amp;lt;image-name:tag&amp;gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the go program I used for this (a very simple HTTP server):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hello world&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;greet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Starting server at port 8090&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;":8090"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






</description>
      <category>docker</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>devops</category>
    </item>
    <item>
      <title>Deploying a Web service with GCP compute &amp; Terraform</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Thu, 29 May 2025 20:44:49 +0000</pubDate>
      <link>https://dev.to/sardinessz/deploying-a-web-service-with-gcp-compute-terraform-nko</link>
      <guid>https://dev.to/sardinessz/deploying-a-web-service-with-gcp-compute-terraform-nko</guid>
      <description>&lt;p&gt;Let's start off with something simple: &lt;br&gt;
&lt;strong&gt;GCP Compute&lt;/strong&gt; is an on-cloud VM to run everything like your own machine.&lt;/p&gt;

&lt;p&gt;We'll deploy a simple http web server container and make it accessible from anywhere.&lt;/p&gt;


&lt;h4&gt;
  
  
  Pre-Requisites:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;GCP account (with Compute API enabled + get your projectID)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://cloud.google.com/sdk/docs/install" rel="noopener noreferrer"&gt;Gcloud CLI&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.hashicorp.com/terraform/install" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Provision a GCP Compute Virtual Machine
&lt;/h2&gt;

&lt;p&gt;We'll use terraform to quickly set this up. Terraform configs are written with &lt;strong&gt;"*.tf"&lt;/strong&gt; &lt;br&gt;
It contains information such as what resources (services) to run and what provider (service provider) to use.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
.&lt;/p&gt;

&lt;p&gt;First, make a &lt;strong&gt;"config.tf"&lt;/strong&gt; file (or whatever you want, doesn't matter), and write these:&lt;/p&gt;

&lt;p&gt;Define GCP to be the provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;google&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/google"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"6.8.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform acts as a middleman, where its:  us &amp;lt;-&amp;gt; terraform &amp;lt;-&amp;gt; aws/gcp/etc&lt;/p&gt;

&lt;p&gt;So we ask it to use the terraform provider SDK for GCP services to be setup, this is the terraform block&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
.&lt;/p&gt;

&lt;p&gt;Then pass some configuration for the GCP project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"google"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;project&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;your-gcp-project-id&amp;gt;"&lt;/span&gt; 
  &lt;span class="nx"&gt;region&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"asia-south2"&lt;/span&gt;   &lt;span class="c1"&gt;#delhi&lt;/span&gt;
  &lt;span class="nx"&gt;zone&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"asia-south2-b"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm using my project ID and closer region, use whatever is closer to you. You can &lt;a href="https://cloud.google.com/compute/docs/regions-zones" rel="noopener noreferrer"&gt;check regions and zones for GCP here&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Then make another &lt;strong&gt;"main.tf"&lt;/strong&gt; file in same dir (any name works just like before although).&lt;/p&gt;

&lt;p&gt;Now, this is the main thing, the &lt;strong&gt;resource block&lt;/strong&gt;, every service is defined in this order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"google_compute_instance"&lt;/span&gt; &lt;span class="s2"&gt;"vm-instance"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vm-instance-tf"&lt;/span&gt;
  &lt;span class="nx"&gt;machine_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"f1-micro"&lt;/span&gt;
  &lt;span class="nx"&gt;zone&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"asia-south2-b"&lt;/span&gt;

  &lt;span class="nx"&gt;boot_disk&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;initialize_params&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ubuntu-os-cloud/ubuntu-2204-lts"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; 

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"allow-web-ssh"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This defines a resource block for making a f1-micro (the smallest VM) with ubuntu-22 OS&lt;/p&gt;

&lt;p&gt;How to actually format these reources blocks in terraform can be &lt;a href="https://registry.terraform.io/providers/hashicorp/google/latest/docs" rel="noopener noreferrer"&gt;referenced from here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The format for a resource block is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "&amp;lt;type&amp;gt;" "&amp;lt;name-for-terraform&amp;gt;" {
   name = "&amp;lt;name-for-gcp&amp;gt;"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just don't get confused between the names here (will come handy later)&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
.&lt;/p&gt;

&lt;p&gt;Now, VMs are like our local machines, the only difference being the Network configuration we have to setup to make it accessible. So let's do that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"google_compute_network"&lt;/span&gt; &lt;span class="s2"&gt;"vpc_network"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"terraform-network"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"google_compute_firewall"&lt;/span&gt; &lt;span class="s2"&gt;"vm-firewall"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vm-firewall"&lt;/span&gt;
  &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;google_compute_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;

  &lt;span class="nx"&gt;allow&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;protocol&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tcp"&lt;/span&gt;
    &lt;span class="nx"&gt;ports&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"22"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"80"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"443"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"8080"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;#access from anywhere (dev mode)&lt;/span&gt;
  &lt;span class="nx"&gt;source_ranges&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"0.0.0.0/0"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;target_tags&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"allow-web-ssh"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Define a network firewall resource (just like compute), similarly, any roles, properties to be added are also made into individual resources.&lt;/p&gt;

&lt;p&gt;And add this to update the VM resource block for access in these ports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"google_compute_instance"&lt;/span&gt; &lt;span class="s2"&gt;"vm-instance"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vm-instance-tf"&lt;/span&gt;
  &lt;span class="nx"&gt;machine_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"f1-micro"&lt;/span&gt;
  &lt;span class="nx"&gt;zone&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"asia-south2-b"&lt;/span&gt;

  &lt;span class="nx"&gt;boot_disk&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;initialize_params&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ubuntu-os-cloud/ubuntu-2204-lts"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;network_interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;network&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;google_compute_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
    &lt;span class="nx"&gt;access_config&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"allow-web-ssh"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;In Terraform, to provision, we have the init -&amp;gt; plan -&amp;gt; apply process.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Init&lt;/strong&gt;:  setup dependencies, providers, etc (run first time)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt;:  make changes (after any change in config)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply&lt;/strong&gt;: apply those changes planned.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, regardless of what filenames you have, as long as they end in "*.tf", it'll be counted in this.&lt;/p&gt;

&lt;p&gt;So perform these commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform plan  &lt;span class="c"&gt;#check and confirm the changes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform apply  &lt;span class="c"&gt;#see whether it passes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Setup Web Server on this GCP VM
&lt;/h3&gt;

&lt;p&gt;After setup is successful, ssh into the machine with gcloud (will work after doing gcloud auth, if failing, do that first):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud compute ssh vm-instance-tf &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-zone&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, quickly setup Docker (go checkout &lt;a href="https://dev.to/sardinessz/series/31630"&gt;my series on docker for more detail&lt;/a&gt;) or by following the guide in &lt;a href="https://docs.docker.com/engine/install/ubuntu/" rel="noopener noreferrer"&gt;this link&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;And run this custom container for testing a web app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d --name test-go-web-app -p 8080:8080 sardinesszsz/go-hello:v2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the web app should run, test it with a HTTP GET request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -X GET http://localhost:8080/  #returns Hello-World!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each VM has a ephemeral IP which is public for access, since we made port 8080 accessible, we can use this IP for HTTP calls on port 8080 to call this web server.&lt;/p&gt;

&lt;p&gt;Get the public IP of this VM with gcloud again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcloud compute instances describe vm-instance-tf &lt;span class="nt"&gt;--zone&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;your-zone&amp;gt; &lt;span class="nt"&gt;--format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'get(networkInterfaces[0].accessConfigs[0].natIP)'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose you got &lt;strong&gt;10.10.10.10&lt;/strong&gt; as the IP, then make a call on this IP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; GET http://10.10.10.10:8080/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That should successfully retrieve the response, if not follow this through, and try seeing what the issue could be or doubts in the comments are welcome!&lt;/p&gt;




&lt;p&gt;So with Terraform, you didn't even have to go to GCP cloud console! Everything is done here in terminal with very less friction once one gets used to it.&lt;/p&gt;

&lt;p&gt;This was a lot to take it (if you're new to Terraform or GCP), but slowly, I'll try to cover more so it can sink in well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S:&lt;/strong&gt; for destroying the service, make sure to go into the dir with the terraform files and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>terraform</category>
      <category>devops</category>
      <category>cloud</category>
      <category>programming</category>
    </item>
    <item>
      <title>5 developer tools to really step up your workflow</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Thu, 15 May 2025 19:45:01 +0000</pubDate>
      <link>https://dev.to/sardinessz/5-developer-tools-to-really-step-up-your-workflow-2f1o</link>
      <guid>https://dev.to/sardinessz/5-developer-tools-to-really-step-up-your-workflow-2f1o</guid>
      <description>&lt;p&gt;Here's some few developer tools I've used quite a lot these past few months that has made my workflow way more fast &amp;amp; smooth.&lt;/p&gt;




&lt;h3&gt;
  
  
  Lazygit
&lt;/h3&gt;

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

&lt;p&gt;Most people choose the git cli over GitHub Desktop.&lt;br&gt;
But this is a &lt;strong&gt;TUI (Terminal UI)&lt;/strong&gt;, so you can easily add changes, make commits, deal with branches, revert &amp;amp; rollbacks, etc.&lt;/p&gt;

&lt;p&gt;And if you have a server running Git (&lt;strong&gt;server with TTY - no GUI&lt;/strong&gt;), you can easily set lazygit up and use it on the go.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Checkout &lt;a href="https://github.com/jesseduffield/lazygit?tab=readme-ov-file" rel="noopener noreferrer"&gt;lazygit github&lt;/a&gt; for some more idea&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  LazyDocker
&lt;/h3&gt;

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

&lt;p&gt;Similar to lazygit, &lt;strong&gt;a TUI manager for docker&lt;/strong&gt;.&lt;br&gt;
This is my favourite TUI so far, I have it open in my other workspace most of the time.&lt;br&gt;
.&lt;br&gt;
Checking which containers are running, images available, logs, metrics, volumes, etc, there's everything.&lt;/p&gt;




&lt;h3&gt;
  
  
  Vim Keybindings / Neovim
&lt;/h3&gt;

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

&lt;p&gt;After using VScode for years now, I tried using Neovim. &lt;br&gt;
Since I was really familiar with VScode's environment, I did revert back to that.&lt;br&gt;
.&lt;br&gt;
But one thing that I took back with me was Vim keybindings, its amazing!&lt;/p&gt;

&lt;p&gt;If you've heard about Vim, it is notorious for being overly complicated for no reason.&lt;br&gt;
That's what I thought too, until I just took it slowly, first learning basics like only operations like: &lt;strong&gt;write, quit, copy, paste&lt;/strong&gt;. &lt;br&gt;
Then moving onto things like &lt;strong&gt;macros&lt;/strong&gt;.&lt;br&gt;
.&lt;br&gt;
Once you get the hang of it, its really fun to navigate and play around with.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you wanna test out vim, would recommend &lt;a href="https://vimschool.netlify.app/introduction/vimtutor/" rel="noopener noreferrer"&gt;Vim Tutor&lt;/a&gt; tool&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
There's extensions in Vscode and other IDEs for vim support, or you can go with Neovim (which provides IDE features like linters, syntax highlight, LSP, etc)&lt;/p&gt;




&lt;h3&gt;
  
  
  Obsidian
&lt;/h3&gt;

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

&lt;p&gt;While this is not technically a developer tool, anybody can use it.&lt;/p&gt;

&lt;p&gt;After jumping from one note to google docs to Notion, I settled into obsidian.&lt;/p&gt;

&lt;p&gt;Its free, has amazing plugin support, and you get this graph of all the notes you have, that's really cool to watch.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
If you're familiar with Notion's syntax of markdown or GitHub readme docs, its a good fit for you. (markdown is really easy even in case you don't know, pretty easy to learn)&lt;/p&gt;




&lt;h3&gt;
  
  
  Tmux
&lt;/h3&gt;

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

&lt;p&gt;Tmux is a "Terminal Multiplexer", so &lt;em&gt;suppose you have ssh-ed into a machine, and want to run two foreground process.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you do that, both in the same terminal?&lt;/strong&gt;&lt;br&gt;
So you gotta make another terminal with ssh, but instead with tmux, you can make a "&lt;strong&gt;pseudo terminal&lt;/strong&gt;".&lt;/p&gt;



&lt;p&gt;That's just one example. &lt;br&gt;
But in general, if you need &amp;gt;1 terminal, just run a tmux command to split it up!&lt;/p&gt;

&lt;p&gt;Then switch between these terminals with keybindings, which you can customize.&lt;/p&gt;




&lt;p&gt;Which one of these do you already use? or suggest more under-rated tools in your arsenal.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>development</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>GCP + Terraform: Intro</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Tue, 13 May 2025 18:24:54 +0000</pubDate>
      <link>https://dev.to/sardinessz/gcp-terraform-intro-352o</link>
      <guid>https://dev.to/sardinessz/gcp-terraform-intro-352o</guid>
      <description>&lt;p&gt;&lt;strong&gt;Google Cloud Platform (GCP)&lt;/strong&gt; provides tons of services like storage, compute, databases, etc.. and it's a mess to go through all of them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Terraform&lt;/strong&gt; is a IAC (infrastructure as code) tool, so you write config (similar to Dockerfile for example), and define what services you need, so it creates that service on your account.&lt;/p&gt;

&lt;p&gt;Using them together is a superpower, Terraform works with major providers like Azure, AWS &amp;amp; GCP so anything works.&lt;/p&gt;




&lt;p&gt;So let's start with understanding some basic services, later I'll show how to use them in detail, but fundamentals are important.&lt;/p&gt;

&lt;p&gt;There's hundreds of services, but I'll go through only the main ones, after that the rest is similar and easy to get used to when needed.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
.&lt;/p&gt;
&lt;h2&gt;
  
  
  GCP Services
&lt;/h2&gt;

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

&lt;p&gt;Every server, client or any type of machine is a computer. This is the most basic thing you can get, a machine you get access to, where you can run any type of service, just like your local machine.&lt;/p&gt;

&lt;p&gt;There's different family such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;E2&lt;/strong&gt; – cost-effective, good for general workloads.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;N2 / N2D&lt;/strong&gt; – better performance than E2, with N2D offering AMD CPUs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;N1&lt;/strong&gt; – older generation, still widely used.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C3&lt;/strong&gt; – Newest, highest performance &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;You don't really need to remember this by the way, just an overview&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Depending on your task, you can choose the physical requirements, the memory, CPU cores, disk, etc.. you're in full control.&lt;/p&gt;




&lt;h4&gt;
  
  
  2. Storage Bucket
&lt;/h4&gt;

&lt;p&gt;Think of it as Google Drive for your backend. Used to store any kind of static assets – images, videos, logs, backups, etc. Fully managed, cheap, and scalable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can set permissions, make files public, and connect it to a CDN.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Great for serving assets or storing backups/logs.&lt;/p&gt;




&lt;h4&gt;
  
  
  3. Cloud Run -&amp;gt; serverless execution
&lt;/h4&gt;

&lt;p&gt;Let’s you run containers without managing any servers. You just give it a Docker image, and it handles the rest – scaling, routing, and more.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Pay-per-use. No traffic? No cost.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Good for APIs, webhooks, or any small backend service.&lt;/p&gt;




&lt;h4&gt;
  
  
  4.. Firestore -&amp;gt; NoSQL DB
&lt;/h4&gt;

&lt;p&gt;A scalable NoSQL document database. Stores data in collections of documents (like JSON).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Best for quick-moving apps where you don’t need SQL.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  What Terraform does?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6telxe4pma2kvgiorxi3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6telxe4pma2kvgiorxi3.png" alt="terraform architecture" width="800" height="290"&gt;&lt;/a&gt;&lt;br&gt;
Initially, you have the &lt;a href="https://console.cloud.google.com" rel="noopener noreferrer"&gt;cloud console&lt;/a&gt;, but using the web console when a lot of services comes to be, its hard to manage. &lt;/p&gt;

&lt;p&gt;With terraform you have three steps only:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Init&lt;/strong&gt;: Install the provider support (in our case, GCP)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt;:  Similar to commit in git, mark changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apply&lt;/strong&gt;:  pretty self-explanatory, no?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simply by writing config such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"google_compute_instance"&lt;/span&gt; &lt;span class="s2"&gt;"vm-instance"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"vm-instance-tf"&lt;/span&gt;
    &lt;span class="nx"&gt;machine_type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"f1-micro"&lt;/span&gt;
    &lt;span class="nx"&gt;zone&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"asia-south2-a"&lt;/span&gt;

    &lt;span class="nx"&gt;boot_disk&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;initialize_params&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;image&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ubuntu-os-cloud/ubuntu-2204-lts"&lt;/span&gt;  
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;network_interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;google_compute_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;vpc_network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
      &lt;span class="nx"&gt;access_config&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"allow-web-ssh"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and using this, you can just create a service easily (this is for a compute engine).&lt;br&gt;
Updating, deleting, making changes also becomes very easy.&lt;/p&gt;




&lt;p&gt;For now, let's do setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install terraform tool for your system from here:  &lt;a href="https://developer.hashicorp.com/terraform/tutorials/gcp-get-started/install-cli" rel="noopener noreferrer"&gt;Install&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sign-up on &lt;a href="https://console.cloud.google.com/welcome?inv=1&amp;amp;invt=AbxTbQ&amp;amp;project=credible-bridge-416420" rel="noopener noreferrer"&gt;GCP console&lt;/a&gt; - you can choose to have a 90 days trial where you get $300 credits free.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;This was to just get familiar with what is what, I'll show a hands on with compute engine + terraform in the next one!&lt;/p&gt;

</description>
      <category>googlecloud</category>
      <category>cloudcomputing</category>
      <category>devops</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Dockerize mutliple containers with compose</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Fri, 09 May 2025 20:00:38 +0000</pubDate>
      <link>https://dev.to/sardinessz/dockerize-mutliple-container-with-compose-3628</link>
      <guid>https://dev.to/sardinessz/dockerize-mutliple-container-with-compose-3628</guid>
      <description>&lt;h3&gt;
  
  
  Use case - what it solves
&lt;/h3&gt;

&lt;p&gt;So If you're familiar with docker containers so far (if not, read my previous two articles on this),&lt;/p&gt;

&lt;p&gt;When there's more than 1 container, and they have to interact, there's some things you have to repeat, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pulling image &amp;amp; creating a container.&lt;/li&gt;
&lt;li&gt;allocate volumes, pass ENV args, etc to container&lt;/li&gt;
&lt;li&gt;have all containers running in same network&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;.&lt;/p&gt;

&lt;p&gt;Now if there's 3,4,5,.. or more, it gets more hectic, see where this is going? Docker compose solves that, by "composing" up your containers config in a file type called &lt;strong&gt;"yaml"&lt;/strong&gt; (its similar to json - a data format, usually for configs).&lt;/p&gt;

&lt;p&gt;You still have things like Dockerfile and concepts of containers are the same, its just the process that's simpler.&lt;/p&gt;




&lt;h3&gt;
  
  
  Let's compose it up
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;A quick example of 3 containers rolling up using docker compose.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So here's what we wanna setup:&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%2F0e9lgrn8px973rlyd33f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0e9lgrn8px973rlyd33f.png" alt="docker-compose system" width="563" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A node js server that writes random key, values to Redis DB&lt;/li&gt;
&lt;li&gt;Then we check the changes from Redis Insight.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Let's start by writing code for this node.js server:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Initialize a npm package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;express redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Code for node.js server:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;redis&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;REDIS_URL&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`key_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;randomValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`value_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;randomKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;randomValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`stored random K-V pair: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;randomKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;randomValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Server running on port 3000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Then writing up a Dockerfile to make this into a container:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18&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; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["node", "server.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Now finally, make a "docker-compose.yaml" file:&lt;/strong&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="s2"&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;api&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;3000:3000"&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;REDIS_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis://redis:6379&lt;/span&gt;

  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;6379:6379"&lt;/span&gt;

  &lt;span class="na"&gt;redisinsight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis/redisinsight:latest&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5540:5540"&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read through this, you'll notice that you still have the same concepts, such as a Dockerfile, ports and environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And what about Network between these containers?&lt;/strong&gt; Since we had to do that manually earlier, docker-compose puts all of these in a same network, so you don't have to deal with that.&lt;/p&gt;

&lt;p&gt;The way one container refers to another is still the same, &lt;strong&gt;for example&lt;/strong&gt;, &lt;em&gt;redis-insight will refer to redis contaner as redis://6379&lt;/em&gt;&lt;/p&gt;



&lt;p&gt;Then, run this with the 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;-d&lt;/span&gt;  &lt;span class="c"&gt;#d means run in background (detached mode)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Now let's try testing this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, make call to &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt; (node.js):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl http://localhost:3000 #via curl
wget http://localhost:3000 #via wget
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Or just use your browser &lt;/p&gt;
&lt;/blockquote&gt;



&lt;ul&gt;
&lt;li&gt;Then check in redis-insight:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Make connection to the redis instance:&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
&lt;p&gt;See the random key-value pairs being added:&lt;/p&gt;
&lt;/blockquote&gt;

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




&lt;p&gt;For more reference on the docker-compose yaml config, &lt;a href="https://docs.docker.com/reference/compose-file/" rel="noopener noreferrer"&gt;check this&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Try making more containers with docker compose, to get some hands on experience, you can try making:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A CRUD App:&lt;/strong&gt; make a node.js + react app with some DB(PG, Mysql, Redis) &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A Db monitor&lt;/strong&gt;: PG DB, use PG exporter for prometheus, with prometheus &amp;amp; grafana. So PG -&amp;gt; exporter -&amp;gt;  prometheus -&amp;gt; grafana (and some server to make writes to PG)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyways, that's about it.&lt;br&gt;
Maybe I'll cover more things with docker, with some examples, or talk about docker swarm in the next one!&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>webdev</category>
      <category>development</category>
    </item>
    <item>
      <title>2 years of using Linux: why you may consider the switch</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Thu, 08 May 2025 21:21:19 +0000</pubDate>
      <link>https://dev.to/sardinessz/2-years-of-using-linux-why-you-may-consider-the-switch-15hf</link>
      <guid>https://dev.to/sardinessz/2-years-of-using-linux-why-you-may-consider-the-switch-15hf</guid>
      <description>&lt;p&gt;As a 2003 kid, I loved playing World of Warcraft, Age of Empires, PVZ and all the old school games in Windows. &lt;/p&gt;

&lt;p&gt;Back then, gaming in linux was.. not a good experience. 20+ years into the future, companies like Steam are actively advocating for Stream Deck (which uses Arch Linux), over 90% of servers &amp;amp; embedded systems run linux of some sort.&lt;/p&gt;

&lt;p&gt;Here, &lt;strong&gt;I want to convince you why you may want to consider switching&lt;/strong&gt; to linux even as a tech or non tech person.&lt;/p&gt;




&lt;h4&gt;
  
  
  Gaming experience
&lt;/h4&gt;

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

&lt;p&gt;Okay let's get this out of the way first. Linux gaming isn't perfect. &lt;br&gt;
The main reason? &lt;strong&gt;driver support for Nvidia based GPUs aren't the best&lt;/strong&gt;, while &lt;strong&gt;for AMD that's not really an issue&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;However, if you're a gamer and would like to give linux a shot, I'd recommend going with &lt;a href="https://linuxmint.com/" rel="noopener noreferrer"&gt;linux mint&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Dev experience
&lt;/h4&gt;

&lt;p&gt;This is a middle ground, I've never had any tools that worked in windows that didn't on linux here. &lt;br&gt;
I mainly use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VScode/Vim&lt;/li&gt;
&lt;li&gt;Docker&lt;/li&gt;
&lt;li&gt;VirtualBox&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;for tools like Docker &amp;amp; VBox -- you usually need &lt;a href="https://learn.microsoft.com/en-us/windows/wsl/about" rel="noopener noreferrer"&gt;WSL&lt;/a&gt; (for context: its like a linux emulator for windows)&lt;/p&gt;

&lt;p&gt;I hate that setup, its way easier to setup tools like this on linux. &lt;br&gt;
And with things like work-spaces (windows also has this) easily accessible by keybindings (like Ctrl + Alt + left/right) to have multiple windows! &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%2Flu8efbpm2n9jphe8noff.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flu8efbpm2n9jphe8noff.png" alt="linux workspaces" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Customization
&lt;/h4&gt;

&lt;p&gt;This is the best part! You can literally change everything, on your own need.&lt;/p&gt;

&lt;p&gt;This is my setup (Arch Linux + Hyprland):&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%2Fyea69z9ht67hxjnd0vi9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyea69z9ht67hxjnd0vi9.png" alt="arch linux setup" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's key bindings like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Super + R:  app drawer&lt;/li&gt;
&lt;li&gt;Super + num: workspace tab&lt;/li&gt;
&lt;li&gt;Super + Shift + L: lock screen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can add key bindings (3rd party) and customize (limited) on windows, but linux takes it to the next level.&lt;/p&gt;

&lt;p&gt;Not sold? Here's some other &lt;strong&gt;"ricing"&lt;/strong&gt; setup (ref: &lt;a href="https://www.reddit.com/r/unixporn/" rel="noopener noreferrer"&gt;r/unixporn&lt;/a&gt; subreddit):&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%2F9mxqs3ov9t1rlu0pqywo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9mxqs3ov9t1rlu0pqywo.png" alt="linux ricing 1" width="800" height="449"&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%2Fhgwguspfegwbwn6hn34o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhgwguspfegwbwn6hn34o.png" alt="linux ricing 2" width="800" height="900"&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%2F3o0szfgvpvysdmyy1w3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3o0szfgvpvysdmyy1w3r.png" alt="linux ricing 3" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Downsides
&lt;/h3&gt;

&lt;p&gt;Its not all sunshine in the penguin kingdom. Some problems you'll find are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mainly Designers&lt;/strong&gt;: tools like adobe suite, or windows office suite won't work.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nvidia GPUs support&lt;/strong&gt;: even though support has improved, there might still be some issues in some softwares.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning curve&lt;/strong&gt;:  most people see OS as a tool to work, not play around with, and that's fine, It also may be more difficult to transition coming from a non-tech or depending on distro you choose.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  You should switch if
&lt;/h3&gt;

&lt;p&gt;If you fall into these categories, I'd recommend first dual booting a shot, or run on Virtual Box accordingly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;for devs&lt;/strong&gt;: ubuntu, debian, nixos (mostly used in servers)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;for gamers&lt;/strong&gt;: mint, popOS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;for hackers&lt;/strong&gt;:  kali, parrot&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;for customization&lt;/strong&gt;:  any (depends more on &lt;a href="https://wiki.archlinux.org/title/Window_manager%20or%20[Desktop%20Environment](https://wiki.archlinux.org/title/Desktop_environment)" rel="noopener noreferrer"&gt;Window Manager&lt;/a&gt; than distro&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's a lot more I can cover like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;networking linux machines to setup a home-lab&lt;/li&gt;
&lt;li&gt;ricing (customizing) linux guide&lt;/li&gt;
&lt;li&gt;linux commands for getting started.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do share what more I should get more into!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>programming</category>
      <category>tutorial</category>
      <category>development</category>
    </item>
    <item>
      <title>Everything to get started with Docker! - I've compiled this into a 2 part series, so check it out..</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Fri, 07 Mar 2025 20:04:09 +0000</pubDate>
      <link>https://dev.to/sardinessz/everything-to-get-started-with-docker-ive-compiled-this-into-a-2-part-series-so-check-it-out-59i8</link>
      <guid>https://dev.to/sardinessz/everything-to-get-started-with-docker-ive-compiled-this-into-a-2-part-series-so-check-it-out-59i8</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/sardinessz" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1481308%2F7f1f675d-3bae-4808-afdf-68805fbdd1c9.jpeg" alt="sardinessz"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/sardinessz/use-docker-no-more-setup-hell-part-1-f65" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Use Docker, No more setup Hell! (Part-1)&lt;/h2&gt;
      &lt;h3&gt;Shubham Tiwary ・ Mar 7&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#docker&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#devops&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#programming&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#learning&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
      <category>docker</category>
      <category>devops</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>Docker continued - Volumes &amp; Network (part-2)</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Fri, 07 Mar 2025 20:02:36 +0000</pubDate>
      <link>https://dev.to/sardinessz/docker-continued-volumes-network-part-2-fpd</link>
      <guid>https://dev.to/sardinessz/docker-continued-volumes-network-part-2-fpd</guid>
      <description>&lt;p&gt;In case you haven't followed up, first go through the &lt;a href="https://dev.to/sardinessz/use-docker-no-more-setup-hell-part-1-f65"&gt;Docker Part-1&lt;/a&gt;, this is a continued series from that previous iteration..&lt;/p&gt;



&lt;h3&gt;
  
  
  Volumes in Docker
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Previously, we see that docker containers are "stateless", they can be exposed to outside world, but don't have state persisting, or interaction between containers.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;With volumes, you have a directory bind between one in docker container to your system.&lt;br&gt;
So you can do things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;make code changes in your machine &lt;code&gt;/dir&lt;/code&gt; and it appears on the container where that's bind to. (no need to re-build image+container on code changes)&lt;/li&gt;
&lt;li&gt;delete container and the data in your system still exists.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Assigning volumes to our container
&lt;/h3&gt;

&lt;p&gt;Back to our &lt;a href="https://dev.to/sardinessz/use-docker-no-more-setup-hell-part-1-f65#writing-our-own-custom-docker-image"&gt;express image from previous part&lt;/a&gt;, we attach a volume&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run -d --name express-app-vol -v /home/dev/work/tests/demo:/app -p 3000:3000 express-dummy:v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have my contents of express app in &lt;code&gt;/home/dev/work/tests/demo&lt;/code&gt;, which i attach to the &lt;code&gt;/app&lt;/code&gt; in container (yours might be different)&lt;/p&gt;

&lt;p&gt;Now let's make a simple change in our code (&lt;code&gt;/home/dev/work/tests/demo/index.js&lt;/code&gt; in my case) :&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;!!!!`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="err"&gt;##&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;--&lt;/span&gt; &lt;span class="nx"&gt;added&lt;/span&gt; &lt;span class="nx"&gt;some&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;!!!!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server connected at port: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these code changes, lets stop &amp;amp; restart container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker stop express-app-vol
docker start express-app-vol
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And response should be something like:&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%2Fa1j3by2pxqtt25so34fd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa1j3by2pxqtt25so34fd.png" alt="volume-container-response" width="388" height="201"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Container Networks.
&lt;/h3&gt;

&lt;p&gt;Suppose there's two containers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Redis container running on port 6379&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redis-Insight container running on port 5540&lt;/strong&gt; (connect to redis &amp;amp; test on a GUI in browser)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run them as follows:&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;--name&lt;/span&gt; redis-container &lt;span class="nt"&gt;-p&lt;/span&gt; 6379:6379 &lt;span class="nt"&gt;-d&lt;/span&gt; redis
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; redisinsight &lt;span class="nt"&gt;-p&lt;/span&gt; 5540:5540 redis/redisinsight:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;With this setup, let's try testing redis from redis-insight:&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%2Fjzqctfzwo46jiwuvu0ro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjzqctfzwo46jiwuvu0ro.png" alt="redis-insight-fail" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So this is redis insight, and it seems to not find any redis DB on port 6379, why is that?&lt;br&gt;
Since the network environment is different for these containers.&lt;/p&gt;



&lt;p&gt;Try running 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;docker network &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It lists down all network present, you'll see these by default:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;bridge&lt;/code&gt;: default network driver.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;host&lt;/code&gt;: between container and the docker host.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;none&lt;/code&gt;: completely isolated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Checking the containers inside the bridge network (default):&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 inspect bridge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go down to the "containers" in the response:&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%2Fohjkle03glxun07nmwji.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fohjkle03glxun07nmwji.png" alt="bridge-containers" width="800" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;you'll notice the redis &amp;amp; redis-insight container, they can talk with your machine but not with each other!&lt;/p&gt;




&lt;h4&gt;
  
  
  Our Custom Network Group.
&lt;/h4&gt;

&lt;p&gt;Let's create our own custom network (we'll place our containers here afterwards):&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;#network called "redis-line"&lt;/span&gt;
docker network create redis-line 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, let's add the two containers here:&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;#add redis-container &amp;amp; redisinsight (the containers) into redis-line network&lt;/span&gt;
docker network connect redis-line redis-container
docker network connect redis-line redisinsight
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let's inspect the network 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 network inspect redis-line
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll notice the containers added inside the "Containers" parameter.&lt;/p&gt;

&lt;p&gt;Now see the "Name", i.e: "redisinsight" &amp;amp; "redis-container". So now when you have to refer to other container, instead of putting an ip, you use these names, example:&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%2Ffzxcn4j4uy549kqf3vjl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffzxcn4j4uy549kqf3vjl.png" alt="redis-insight-connected" width="800" height="592"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So here in the "host", we put "redis-container" which is like its domain in that network.&lt;/p&gt;

&lt;p&gt;And from that, it is connected and works!&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%2Fvfpul9rojjn3z1lze4ga.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfpul9rojjn3z1lze4ga.png" alt="redis-workbench" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Just reading through these isn't enough, what might work here might not for you, so its best you try these on your own..&lt;/p&gt;

</description>
      <category>programming</category>
      <category>docker</category>
      <category>devops</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Use Docker, No more setup Hell! (Part-1)</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Fri, 07 Mar 2025 07:53:55 +0000</pubDate>
      <link>https://dev.to/sardinessz/use-docker-no-more-setup-hell-part-1-f65</link>
      <guid>https://dev.to/sardinessz/use-docker-no-more-setup-hell-part-1-f65</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fryv1nu50335o0dpzeh21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fryv1nu50335o0dpzeh21.png" alt="docker-dashboard" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  A case scenario - setup hell
&lt;/h4&gt;

&lt;p&gt;This are the docker containers I'm currently running on my PC. &lt;br&gt;
Earlier, I'd have to setup manually which'd look something like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the official site, get hit with the register, verify account &amp;amp; login (forgot you password? another mess to recover that)&lt;/li&gt;
&lt;li&gt;After that, turns out it doesn't work: go to reddit, find some solution from 7 years ago, a 50/50 hit or miss it does work (bless those guys though)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Another case scenario - "But It works on my machine"
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;You got a windows PC, your friend got a linux/mac, and you wanna deploy to AWS, so there's something like AMI.&lt;/li&gt;
&lt;li&gt;Code is simple, use git. Wanna share &amp;amp; deploy your local dependencies? good luck testing on each platform &amp;amp; writing README files for "how to run" (realize nobody actually reads that)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Creating a container
&lt;/h2&gt;

&lt;p&gt;First, let's see how easy it is to create a container &lt;/p&gt;

&lt;p&gt;Let's go to &lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;Docker Hub&lt;/a&gt;, a repository for docker "images". Think of images like blueprints to make a "container".&lt;/p&gt;

&lt;p&gt;We'll try to setup a simple nginx container:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vr3or46y0pejua7chr5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vr3or46y0pejua7chr5.png" alt="docker-hub-nginx" width="800" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's instructions on how to use this in the same page:&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%2Fizhxxwks4gko2ll5q1ux.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fizhxxwks4gko2ll5q1ux.png" alt="nginx-docker-use" width="800" height="611"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running the command to start the container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --name nginx-dummy -d -p 8080:80 some-content-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open your web-browser at &lt;code&gt;localhost:8080&lt;/code&gt;, and you'll see the following:&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%2Fjw26wg3gdp56j47p1erg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjw26wg3gdp56j47p1erg.png" alt="nginx-browser-ui" width="728" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;See? It's pretty easy once you get the hang of it, you can do the same for things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;setting up a database locally like redis, postgres, mongoDB&lt;/li&gt;
&lt;li&gt;setting up services like nginx, grafana, selenium, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Now let's set this up on your machine, come back and try running this nginx container later after docker installation!&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Docker Installation
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Skip if you already have this done.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What you wanna install is "Docker Desktop", docker in itself is a collection of tools such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker engine.&lt;/li&gt;
&lt;li&gt;Docker CLI.&lt;/li&gt;
&lt;li&gt;Docker daemon.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Docker desktop has all these packaged, so install only that and you're set to go.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For Windows:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go &lt;a href="https://docs.docker.com/desktop/setup/install/windows-install/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and follow the steps&lt;/li&gt;
&lt;li&gt;Note that for windows, you have to setup &lt;strong&gt;WSL&lt;/strong&gt; (windows support for a linux like environment) - I'll like up to &lt;a href="https://youtu.be/vxTW22y8zV8?si=gSC4U6j2HUhxJwbY" rel="noopener noreferrer"&gt;this really great tutorial &lt;/a&gt;here for this one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For Linux:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;For a GUI based environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go &lt;a href="https://docs.docker.com/desktop/setup/install/linux/" rel="noopener noreferrer"&gt;here&lt;/a&gt;, same as windows, setup docker desktop based on your distro.&lt;/li&gt;
&lt;li&gt;Pre-requisite:  setup KVM (virtualization) on your system (how to do so present in the same link above)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For a TTY environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In systems like AMI, ubuntu server, you may not have a GUI, and it's more suited to setup docker engine (comes with docker cli)&lt;/li&gt;
&lt;li&gt;Go &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;here&lt;/a&gt; and check your distro.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;So far, I've tested it in these environments:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows (with WSL)&lt;/li&gt;
&lt;li&gt;Ubuntu (gnome)&lt;/li&gt;
&lt;li&gt;Arch (hyprland - wayland)&lt;/li&gt;
&lt;li&gt;Ubuntu Server.&lt;/li&gt;
&lt;li&gt;AMI (amazon machine image)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  After setup:
&lt;/h4&gt;

&lt;p&gt;Try using the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker --help
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;To start creating and using docker containers, note that you'll have to turn on the "docker daemon", how to do that? Since docker desktop already has everything, just open the desktop app, and you'll see a whale icon on top right screen, then try again.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The basis: Images &amp;amp; Containers
&lt;/h2&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Gotta get a little bit theoretical on this part&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;u&gt;Docker has two fundamental components:&lt;/u&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Containers&lt;/strong&gt; are services that are isolated, like &lt;a href="https://cloud.google.com/learn/what-is-a-virtual-machine" rel="noopener noreferrer"&gt;virtual machines&lt;/a&gt;, they provide a isolated environment where you can run, test, do anything like its a whole new system inside it. These containers don't persist data in your disk like a normal service, delete a container and all it's data goes with it, it is therefore: &lt;strong&gt;stateless&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Advantage?&lt;/strong&gt; You can create/destroy containers at ease. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problem?&lt;/strong&gt; The isolation can cut itself off from others (we'll learn about controlling isolation with volumes &amp;amp; networks in next part!)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Images&lt;/strong&gt; are blueprints to creating these container. An example of image can be set of instructions like:

&lt;ul&gt;
&lt;li&gt;Clone a repository, install its dependencies.&lt;/li&gt;
&lt;li&gt;Run the main service (ex: express) on port 3000.
Containers replicate this formula, so you can create any service into a image --&amp;gt; and then make a container from that image!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;So basically, &lt;strong&gt;&lt;a href="https://hub.docker.com/" rel="noopener noreferrer"&gt;docker-hub&lt;/a&gt; (from nginx example)&lt;/strong&gt; is just a central registry to host these images!&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Writing our own custom Docker Image
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create some random directory, initialize node-js project &amp;amp; setup express:
&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;mkdir test&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd test
&lt;/span&gt;npm init &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install &lt;/span&gt;express dotenv
&lt;span class="nb"&gt;touch &lt;/span&gt;index.js 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Make up a simple &lt;code&gt;index.js&lt;/code&gt; script for the express server:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;express&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;express&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;num&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Server connected at port: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;We write the image's recipe in a "Dockerfile", which looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;#needs a "base image", we have an express app, so base will be nodejs image. &lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:18   &lt;/span&gt;

&lt;span class="c"&gt;#inside container, make a /app folder to store our project files&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app  &lt;/span&gt;
&lt;span class="c"&gt;#indicate that port 3000 is running the service(doesn't actually expose it, just a indicator)&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;span class="c"&gt;#env variable used in the script    &lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; num=10   &lt;/span&gt;

&lt;span class="c"&gt;#now copy our index.js + package.json to the /app folder for use&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; index.js /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json /app&lt;/span&gt;

&lt;span class="c"&gt;#run command in workdir(/app in this case), install packages from package.json (i.e: express &amp;amp; dotenv)&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; 
&lt;span class="c"&gt;#start the application from&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["node", "index.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;p&gt;Now let's create the image from this dockerfile:&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;#run the dockerfile residing in this directory (assuming you are in same directory as dockerfile)&lt;/span&gt;
docker build &lt;span class="nt"&gt;-t&lt;/span&gt; express-image:v1 &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm this image is 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;You should notice an &lt;strong&gt;"express-image:v1"&lt;/strong&gt; image in the list.&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Now, image is set, create container from that:&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 run &lt;span class="nt"&gt;--name&lt;/span&gt; express-app &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 3000:3000 express-dummy:v1 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;-p 3000:3000&lt;/code&gt;? Remember the &lt;code&gt;EXPOSE 3000&lt;/code&gt; line back when we wrote the dockerfile, here &lt;code&gt;-p &amp;lt;my-port&amp;gt;:&amp;lt;container-port&amp;gt;&lt;/code&gt; maps our PC's port 3000 to container port 3000.&lt;br&gt;
So example: if you do &lt;code&gt;-p 8080:3030&lt;/code&gt;, our port 8080 will act like container's port 3000!&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Since we set port 3000:3000 mapping, make a request in &lt;code&gt;localhost:3000&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should get an "index.html" file with contents:  "Hello 10"&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
We used an environment variable "num" earlier but that was static, let's try passing a new value for the env variable:&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 run &lt;span class="nt"&gt;--name&lt;/span&gt; express-app-2 &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;num&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50 &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:3000 express-dummy:v1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this new container from same image, we pass the num variable from &lt;code&gt;-e key=value&lt;/code&gt; flag.&lt;br&gt;
And this should run in your &lt;code&gt;localhost:8080&lt;/code&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%2Fvxrx2vb55mosgxkp30jt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxrx2vb55mosgxkp30jt.png" alt="hello-50" width="181" height="91"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I honestly don't remember all the syntax for docker-file, so using something like the &lt;a href="https://docs.docker.com/reference/dockerfile/" rel="noopener noreferrer"&gt;dockerfile reference&lt;/a&gt; is recommended &lt;/p&gt;




&lt;h4&gt;
  
  
  Summary
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;This is just the basics, but you should be able to use these as basis to start using containers, easily setting them up or even making your own containers, but there's many more things remaining:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Containers are isolated, so how do we let multiple containers connect? So far we've connected our PC to the container. - &lt;strong&gt;docker network&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;These containers drop everything when removed, what about - containers running DBs? we would want some to persist state right. - &lt;strong&gt;docker volumes&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Is there any simpler way to handle multiple containers? - &lt;strong&gt;docker compose&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Next Part:  &lt;a href="https://dev.to/sardinessz/docker-continued-volumes-network-part-2-fpd"&gt;Docker continued - Volumes &amp;amp; Network (part-2)&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>programming</category>
      <category>learning</category>
    </item>
    <item>
      <title>Building a custom HTTP server from scratch</title>
      <dc:creator>Shubham Tiwary</dc:creator>
      <pubDate>Thu, 27 Feb 2025 20:52:45 +0000</pubDate>
      <link>https://dev.to/sardinessz/building-a-custom-http-server-5aip</link>
      <guid>https://dev.to/sardinessz/building-a-custom-http-server-5aip</guid>
      <description>&lt;p&gt;I've built APIs and played around with virtual machines for a long time now, and if you've done similar things&lt;br&gt;
You know It's always followed by some protocol:  &lt;strong&gt;http, web-sockets, ssh, ...&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;So today I wanna breakdown some mysteries on how things work behind the scenes just a little bit. Covering one of the most used protocols, HTTP &lt;br&gt;&lt;br&gt;
&lt;strong&gt;For context&lt;/strong&gt;: a "protocol" is just like a dialect between computers, so different systems can talk in a common manner &lt;br&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;References (sources you may wanna check after reading this):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hpbn.co/" rel="noopener noreferrer"&gt;High Performace browser networking (book)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://datatracker.ietf.org/doc/html/rfc2616" rel="noopener noreferrer"&gt;HTTP 1.1 RFC (documentation on how HTTP is implemented)&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ShubhamTiwary914/tcp-http-1.1-server/" rel="noopener noreferrer"&gt;Github source code (implemtation in golang)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
.&lt;/p&gt;
&lt;h3&gt;
  
  
  Inside the engine - TCP
&lt;/h3&gt;

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

&lt;p&gt;Now networks are unreliable, data may be lost in between, or take too much time to do so. &lt;br&gt;
&lt;strong&gt;TCP was built for this, &lt;em&gt;to provide a reliable connection on a unreliable network&lt;/em&gt;&lt;/strong&gt; &lt;br&gt;&lt;/p&gt;

&lt;p&gt;Suppose there's two devices on a network, these devices have some address (their IP), and a process running (on a port), that's all you need for TCP.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;It let's the devices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;send data in order (in chunks called "segments") --&amp;gt; like a queue.&lt;/li&gt;
&lt;li&gt;if any data is load, retransmission is performed (ensures data reaches)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;How do devices know if the other has received or not? Simple, just send an "ACK" (acknowledgement) to confirm, if there's no response after some time, assume it is lost.&lt;br&gt;
Anyways, this in itself is a large topic, so we'll get to HTTP&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
Now, like HTTP, TCP also has underlying &lt;a href="https://www.geeksforgeeks.org/client-server-model/" rel="noopener noreferrer"&gt;client-server&lt;/a&gt; model&lt;/p&gt;

&lt;p&gt;And here's how the process kind of turns out to be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;So let's say server has an &lt;strong&gt;address (2.2.2.2)&lt;/strong&gt; &amp;amp; running a TCP service on &lt;strong&gt;port (3000)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Client sends a TCP request here, first these devices has to do a "handshake" process (before they start actually sending data)&lt;/li&gt;
&lt;li&gt;The handshake process goes as follows:  &lt;strong&gt;client --&amp;gt; server(ACK) --&amp;gt; back to client (they exchange info needed during actual transmission of data later)&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Once client receives data back from server, it starts sending data to server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every chunk of data after that, is a client --&amp;gt; server and followed by an ACK received back&lt;/strong&gt;. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
.&lt;/p&gt;
&lt;h3&gt;
  
  
  A look at HTTP
&lt;/h3&gt;

&lt;p&gt;Now we've understood TCP a bit, let's look at the data being sent after the handshake.&lt;/p&gt;

&lt;p&gt;HTTP is nothing more than just a format on how data should be present (same goes for most protocols).&lt;/p&gt;

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

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

&lt;p&gt;When you use something like &lt;strong&gt;express, fastapi, flask&lt;/strong&gt; to make a backend service, their implementation may be different but all of them expect the request in this format!&lt;/p&gt;

&lt;p&gt;So the idea is to parse them in order that they are supposed to be and process them, then send a response, which also is in the same format.&lt;/p&gt;



&lt;p&gt;Try using the following command in your terminal/command prompt (check if you have wget or not, most systems always has it beforehand):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; wget --server-response --debug --post-data="test" --header="Content-Type: text/plain" https://jsonplaceholder.typicode.com/posts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will retrieve some json responses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In the example, it's a simple "Hello world" (a string), but you can send a lot more like: html, json, assets, blobs, etc&lt;/p&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
.&lt;/p&gt;

&lt;p&gt;Honestly, these are more than enough to start building a HTTP server.&lt;br&gt;
Like I said, the implementation can be different, but the protocol is the same, so here's some guide I'll give you to follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;First try establishing a TCP connection, send some dummy data back &amp;amp; forth (you'll need a TCP server &amp;amp; a TCP client - check your language's docs - ex:  &lt;strong&gt;go - net &amp;amp; nodejs - Net&lt;/strong&gt;)'&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Seperate into modules &amp;amp; test indivually:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Parser"&lt;/strong&gt; --&amp;gt; breaks down request into info, header &amp;amp; body.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Router"&lt;/strong&gt; --&amp;gt; like express, fastapi, or any server side framework handles "routing" i.e:  check type of request (POST, GET) &amp;amp; path to assign a callback function &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Composer"&lt;/strong&gt; --&amp;gt; after processing the callback function, get response from the handler (callback function), and respond to client.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;br&gt;&lt;br&gt;
.&lt;br&gt;
This was just a basic overview, this is definitely not something you wanna be using in prod.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;But making things from ground up does give you a really good perspective on how things are, and change the way you look at problems, so you know not only how to do it, but also why.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can follow &lt;a href="https://github.com/ShubhamTiwary914/tcp-http-1.1-server/" rel="noopener noreferrer"&gt;my implementation at Github&lt;/a&gt; (it's in golang, but still you can use as reference to implement in your favourite language). &lt;br&gt;&lt;/p&gt;

&lt;p&gt;(There's more to be added in the future in this implementation probably, so I'll share updates here if I do make some changes)&lt;/p&gt;

</description>
      <category>programming</category>
      <category>go</category>
      <category>networking</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
