<?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: Rajdip Bhattacharya</title>
    <description>The latest articles on DEV Community by Rajdip Bhattacharya (@thecodersden).</description>
    <link>https://dev.to/thecodersden</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%2F1134388%2Fd425799e-a6b4-4cb8-a76a-6c947f333f15.jpg</url>
      <title>DEV Community: Rajdip Bhattacharya</title>
      <link>https://dev.to/thecodersden</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thecodersden"/>
    <language>en</language>
    <item>
      <title>Design Decision for Role-Based Access Control (RBAC)</title>
      <dc:creator>Rajdip Bhattacharya</dc:creator>
      <pubDate>Wed, 21 Jan 2026 14:14:29 +0000</pubDate>
      <link>https://dev.to/thecodersden/design-decision-for-role-based-access-control-rbac-1b28</link>
      <guid>https://dev.to/thecodersden/design-decision-for-role-based-access-control-rbac-1b28</guid>
      <description>&lt;p&gt;Every organization uses a set of SaaS products for their daily operations. Every such product is responsible for sheltering data and performing operations at large scale. So there should be appropriate checks as to who can do what with the data. And that's where &lt;strong&gt;Role-Based Access Control&lt;/strong&gt; comes into play. &lt;/p&gt;

&lt;h2&gt;
  
  
  A bit about RBAC
&lt;/h2&gt;

&lt;p&gt;Before we dig in, a bit of an explainer will help us start off at the same page. &lt;strong&gt;RBAC is a 1-1 mirror of how organizations work IRL&lt;/strong&gt;. You as an employee will have a job role, and with your role, comes responsibilities and permissions. An employee who is an accountant will have access to the debit/credit book of the company. A DevOps engineer will be heading the pipeline development of the products. And so on. &lt;/p&gt;

&lt;p&gt;Similarly in SaaS products, &lt;strong&gt;to control the access of users to specific actions and data&lt;/strong&gt;, we put RBAC in place. Project admins (ofter the person who signed up for the product) creates teams, roles and assigns them to certain users within the product. &lt;/p&gt;

&lt;h2&gt;
  
  
  Whom this article is not for
&lt;/h2&gt;

&lt;p&gt;Unconventional way to start, but since I'm writing this to address a very niche, I would like to set the expectations for the readers in here.&lt;/p&gt;

&lt;p&gt;This article &lt;strong&gt;is not for you&lt;/strong&gt; if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You are looking for a Node-based RBAC implementation&lt;/li&gt;
&lt;li&gt;Yes that's just about it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But, &lt;strong&gt;you should read it&lt;/strong&gt; if you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Are a beginner and trying to grasp the fundamentals of RBAC&lt;/li&gt;
&lt;li&gt;Trying to debug what went wrong in your design, or, attempting to improve your design&lt;/li&gt;
&lt;li&gt;Need a handbook for initial steps&lt;/li&gt;
&lt;li&gt;Please your seniors with a weekend blog reflection&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  RBAC Designs
&lt;/h2&gt;

&lt;p&gt;The most basic form of RBAC system will almost always have these entities in some form or the other:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Organization:&lt;/strong&gt; The unit under which users, resources, and roles reside. This is where the action takes places.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User:&lt;/strong&gt; The actors, using the platform and taking actions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource:&lt;/strong&gt; Items which are being acted upon by the users. It can be docs, VMs, databases, etc. These are what we protect using roles.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Role:&lt;/strong&gt; The gatekeeper, preventing/allowing users' access to resources.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permission:&lt;/strong&gt; Associated with roles, define what a role will permit its users to do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User Group:&lt;/strong&gt; Optionally present in infrastructures with massive number of resources. It associates with multiple roles and users.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Design
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;An organization is the host. Everything in our infrastructure (except &lt;code&gt;permissions&lt;/code&gt;) are tied up with the organization.&lt;/li&gt;
&lt;li&gt;An organization can have multiple users → &lt;code&gt;1 x N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;An organization can have multiple roles → &lt;code&gt;1 x N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;An organization can have multiple resources → &lt;code&gt;1 x N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;An organization can have multiple user groups → &lt;code&gt;1 x N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A role can be associated with multiple permissions, and permission can be associated with multiple roles → &lt;code&gt;M x N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A role can be associated with multiple users, and a user can be associated with multiple roles → &lt;code&gt;M x N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A role can be associated with multiple resources, and a resource can be tied up with multiple roles → &lt;code&gt;M x N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A role can be tied up with multiple user groups, and a user group can be tied up with multiple roles → &lt;code&gt;M x N&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;A user can be tied up with multiple user groups, and a user group can be tied up with multiple users → &lt;code&gt;M x N&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;High-level diagram:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Detailed diagram:&lt;/strong&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Design Outcomes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Having a separate table for &lt;code&gt;permissions&lt;/code&gt; is purely a design choice, and not a mandate. Having a separate permission table allows you to scope permissions for specific resources. For example, the role &lt;code&gt;ORGANIZATION_ADMIN&lt;/code&gt; won't be applicable to a &lt;code&gt;Document&lt;/code&gt; resource. So, you could have an optional list of acceptable/unacceptable resource types per resource.&lt;/li&gt;
&lt;li&gt;A user can be tied up with both roles and user groups simultaneously. &lt;/li&gt;
&lt;li&gt;User groups are never tied with resources directly.&lt;/li&gt;
&lt;li&gt;There can be roles, that may not be tied with any resources at all. For example, a role having &lt;code&gt;ADMIN&lt;/code&gt; would imply administrative access over the organization, and hence won't have any resource mapping.&lt;/li&gt;
&lt;li&gt;We could have chosen a higher order join-table, but having binary join-tables provide a ton of flexibility at the cost of some data repetition.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Least Privilege model
&lt;/h2&gt;

&lt;p&gt;Usually, this is where I conclude my blogs with a &lt;strong&gt;Conclusion&lt;/strong&gt;, but I thought about making this section a bit more informative. This is not related to how you should implement a RBAC system, but how you should use it properly.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.cyberark.com/what-is/least-privilege/" rel="noopener noreferrer"&gt;Least Privilege Model&lt;/a&gt; states that actors should be granted the least possible set of permissions required for it to operate efficiently. &lt;/p&gt;

&lt;p&gt;Consider you have created a pipeline that will fetch your code from your SCM, build an artifact, and deploy it to AWS Lambda. So collectively, it will require the following permissions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Read repository on SCM&lt;/li&gt;
&lt;li&gt;Pull code from SCM&lt;/li&gt;
&lt;li&gt;Push deployment to AWS Lambda&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how you build a restrictive system with the least access. &lt;/p&gt;

&lt;p&gt;Why does this matter? — Say that your deployment script gets a new change that was pushed unchecked. This can now affect other resources without your knowledge.&lt;/p&gt;

&lt;p&gt;The only takeaway from this section would be this: your home-brewed RBAC system should be fine-grained enough so that users relying on your product can apply this principle.&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>programming</category>
      <category>backend</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Managing Secrets in Dev Tools Without Getting Yelled At</title>
      <dc:creator>Rajdip Bhattacharya</dc:creator>
      <pubDate>Tue, 09 Sep 2025 06:46:15 +0000</pubDate>
      <link>https://dev.to/thecodersden/managing-secrets-in-dev-tools-without-getting-yelled-at-2npm</link>
      <guid>https://dev.to/thecodersden/managing-secrets-in-dev-tools-without-getting-yelled-at-2npm</guid>
      <description>&lt;p&gt;Good day geeks! It has been a long time since I dropped my last article, so I thought about coming back with one that would actually be helpful to all sorts of developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  So what's this blog about?
&lt;/h2&gt;

&lt;p&gt;If you are reading this, chances are that you have already understood what this is about just by glancing at the title. If not, well that's what I am writing this about! &lt;/p&gt;

&lt;p&gt;We developers have a bad habit of hard-coding secrets into our codebase, just o make sure that the bigger picture works. "It's on dev, we'll remove it before it hits our repository", we say. And then, it turns out that we never really got rid of it. The hardcoded secrets hit our SCM, stays there unnoticed, and ultimately lands in the hands of a malicious actor.&lt;/p&gt;

&lt;p&gt;Project onboarding is surely painstaking. We add a teammate, and now we have to send them the &lt;code&gt;.env&lt;/code&gt; file - over email / discord / slack / teams, and sometimes even over messages. That's not a very secure practice. And the problem doesn't end there. What if we update the &lt;code&gt;OPEN_AI_API_KEY&lt;/code&gt;? We would now need to broadcast this to the entire team, and also hand them the secrets. Our servers would need the latest values too, so that we don't start hitting &lt;code&gt;500&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  But why does it really matter?
&lt;/h2&gt;

&lt;p&gt;You might be wondering that these are just stupid mistakes we developers do. That PR reviews should be more vigilant, that there should be to-and-fro communication whenever something fails. But hey, we are humans, and humans will make mistakes.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI won't be so stupid!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;True, but what if the person sitting behind that prompts isn't as experienced? What if they don't understand how sensitive the contents of a &lt;code&gt;.env&lt;/code&gt; are?&lt;/p&gt;

&lt;p&gt;If you have read so far, that means I have been successfully able to glue your attention to the screen, and you might be expecting a solution. And in case you are not impressed, let me drop some numbers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.gitguardian.com/state-of-secrets-sprawl-report-2025" rel="noopener noreferrer"&gt;GitGuardian's The State of Secret Sprawl 2025&lt;/a&gt; quotes a whooping &lt;strong&gt;23 million plaintext secrets&lt;/strong&gt; detected in GitHub commits, &lt;strong&gt;70%&lt;/strong&gt; of which are valid and exists till date. And the numbers are still increasing! It shot up to &lt;strong&gt;23.8M in 2024&lt;/strong&gt; from the &lt;strong&gt;19.1M in 2023&lt;/strong&gt;. The potential breaches resulting from such leaks can amount up to &lt;strong&gt;$4.4 million&lt;/strong&gt;, as stated by IBM's &lt;a href="https://www.ibm.com/reports/data-breach" rel="noopener noreferrer"&gt;Cost of a Data Breach Report 2025&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As you can see, that's enough to cripple an organization to its knees. &lt;/p&gt;

&lt;h2&gt;
  
  
  And now, the solution!
&lt;/h2&gt;

&lt;p&gt;All's not lost! Problems are why engineers exist in the first place, and this is where I would like to introduce you to Keyshade&lt;/p&gt;

&lt;h2&gt;
  
  
  Keyshade?
&lt;/h2&gt;

&lt;p&gt;Yep! &lt;a href="https://keyshade.xyz" rel="noopener noreferrer"&gt;Keyshade&lt;/a&gt; is an &lt;a href="https://github.com/keyshade-xyz/keyshade" rel="noopener noreferrer"&gt;open-source&lt;/a&gt; secret and configuration management platform, built with a security-first and developer friendly mindset. &lt;/p&gt;

&lt;h3&gt;
  
  
  But why would I store MY SECRETS somewhere else?
&lt;/h3&gt;

&lt;p&gt;Good question! Well, there are a lot of reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Forget "Hey bro, can you DM me the .env file?". Keyshade helps you to &lt;strong&gt;stay in sync&lt;/strong&gt;. You upload your configurations to your project, and your entire developer team taps into this project.&lt;/li&gt;
&lt;li&gt;Data ownership is a big concern. Keyshade's approach to solve this problem is unique. It &lt;strong&gt;uses public key encryption to store your secrets&lt;/strong&gt;, which means even keyshade won't be able to decrypt your secrets. You hold access to the private key, and you decide to share it with your teammates.&lt;/li&gt;
&lt;li&gt;Your hosted applications get to use your configurations aswell! You could do so by using their platform-specific integrations or their CLI.&lt;/li&gt;
&lt;li&gt;And the best part? &lt;strong&gt;It's a drop-in replacement&lt;/strong&gt;. You don't need to change a single line in your codebase to adapt to keyshade. It just works. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They offer a generous free-tier for you to play around with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo time!
&lt;/h2&gt;

&lt;p&gt;Well, enough talking. Let's see how it actually works. I would be using a simple NextJS application to demonstrate the platform.&lt;/p&gt;

&lt;p&gt;First, head over to &lt;a href="https://app.keyshade.xyz" rel="noopener noreferrer"&gt;app.keyshade.xyz&lt;/a&gt; and get yourself an account. &lt;/p&gt;

&lt;p&gt;You would land up in a page like this:&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%2Fprwqfsjk848jbwlzu1ms.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fprwqfsjk848jbwlzu1ms.png" alt="keyshade dashboard" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's a bit on the terminology that keyshade uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workspaces:&lt;/strong&gt; Consider these as organizations.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Projects:&lt;/strong&gt; This is what houses your secrets, variables, and environments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secrets:&lt;/strong&gt; Sensitive stuff from your .env file. These are always stored in an encrypted form. For example&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Variables:&lt;/strong&gt; Not so sensitive stuff. For example, port number.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Environments:&lt;/strong&gt; Think of them as development environments. For example, dev, prod, stage, uat, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Install the CLI
&lt;/h3&gt;

&lt;p&gt;Keyshade has it's dedicated CLI to perform all operations on the platform, and also to use your configurations in your local development environment. We would need that for our demo. Here's how to install the CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-g&lt;/span&gt; @keyshade/cli 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once successful, you should be able to use:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting up a profile
&lt;/h3&gt;

&lt;p&gt;Profiles can be considered as your identity to access keyshade. The possibilities are many, but we will stick to the most basic use. &lt;/p&gt;

&lt;p&gt;First stop, head over to &lt;strong&gt;Dashboard&lt;/strong&gt; → &lt;strong&gt;Profile Dropdown&lt;/strong&gt; → &lt;strong&gt;Profile&lt;/strong&gt; → &lt;strong&gt;API Keys&lt;/strong&gt;. Now, hit &lt;strong&gt;Add API Key&lt;/strong&gt; and create a key for yourself. For demo purposes, select all the authorities.&lt;/p&gt;

&lt;p&gt;Once generated, you should get an API key. Take a note of that. &lt;/p&gt;

&lt;p&gt;Open up your favourite terminal, and issue 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;keyshade profile create &lt;span class="nt"&gt;-n&lt;/span&gt; my_key &lt;span class="nt"&gt;-a&lt;/span&gt; &amp;lt;your key&amp;gt; &lt;span class="nt"&gt;--set-default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once done, you should be able to see it using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;keyshade profile list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it! You have now successfully logged on to keyshade from your local machine. To verify everything works, try listing your workspaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;keyshade workspace list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The NextJS project
&lt;/h3&gt;

&lt;p&gt;This is what I have in my project:&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%2Fbu970z00pboevs27az4x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbu970z00pboevs27az4x.png" alt="NextJS boilerplate" width="702" height="782"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;src/app/page.tsx&lt;/code&gt;, I have the following content. You can replace yours with mine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"bg-white h-screen w-screen text-center text-black flex flex-col"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"font-bold"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Secret (NEXT_PUBLIC_API_KEY):&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&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;NEXT_PUBLIC_API_KEY&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"font-bold"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Variable (NEXT_PUBLIC_PORT):&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;span&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="si"&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;NEXT_PUBLIC_PORT&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;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;&lt;strong&gt;Things to note:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I don't have a &lt;code&gt;.env&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;We are reading &lt;code&gt;NEXT_PUBLIC_API_KEY&lt;/code&gt; and &lt;code&gt;NEXT_PUBLIC_PORT&lt;/code&gt; from the environment. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you fire up this project now using &lt;code&gt;npm run dev&lt;/code&gt;, and head over to &lt;a href="https://localhost:3000" rel="noopener noreferrer"&gt;https://localhost:3000&lt;/a&gt;, you would see something like this:&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%2Fqmuo9jix9jnx0a7q68yf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqmuo9jix9jnx0a7q68yf.png" alt="updated project" width="800" height="163"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Create a project
&lt;/h3&gt;

&lt;p&gt;To start adding secrets and variables, we would first need to create a project. Head over to &lt;strong&gt;Dashboard&lt;/strong&gt; → &lt;strong&gt;Create Project&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Access level:&lt;/strong&gt; Defines who get to see this project. Since it's just you who would be seeing it, set it to &lt;code&gt;PRIVATE&lt;/code&gt; (default)&lt;br&gt;
&lt;strong&gt;Store private key:&lt;/strong&gt; This is what gives you ownership. Keyshade recommends you to &lt;strong&gt;not store your private key with them&lt;/strong&gt;. Set the slider to off (default)&lt;br&gt;
&lt;strong&gt;Environments:&lt;/strong&gt; We won't need too many environments, so this is good. &lt;/p&gt;

&lt;p&gt;It should ultimately look like this:&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%2Fk29ybntg2zxcqpc4tobg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk29ybntg2zxcqpc4tobg.png" alt="Create project" width="800" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After hitting &lt;strong&gt;Create Project&lt;/strong&gt;, you would be greeted with a new dialog. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Copy the command&lt;/li&gt;
&lt;li&gt;Head over to your local project&lt;/li&gt;
&lt;li&gt;Fire up your terminal &lt;/li&gt;
&lt;li&gt;Paste it and hit enter&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Wallah! Now you have successfully tied up your local project with keyshade.&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating secrets and variables
&lt;/h3&gt;

&lt;p&gt;We are all set. The last lego block would be to add in the values for &lt;code&gt;NEXT_PUBLIC_API_KEY&lt;/code&gt; and &lt;code&gt;NEXT_PUBLIC_PORT&lt;/code&gt;. As the name suggests, the first one would be a secret (secure by nature), and the second is a variable (not so secure)&lt;/p&gt;
&lt;h4&gt;
  
  
  Adding &lt;code&gt;NEXT_PUBLIC_API_KEY&lt;/code&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Head over to your project&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Secret&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;Add Secret&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Set the name as &lt;code&gt;NEXT_PUBLIC_API_KEY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Fill the &lt;strong&gt;Note&lt;/strong&gt; if you want to, i'll leave it blank&lt;/li&gt;
&lt;li&gt;Enter &lt;code&gt;abc&lt;/code&gt; as the value for &lt;code&gt;default&lt;/code&gt; (the environment we selected when creating the project)&lt;/li&gt;
&lt;li&gt;Hit &lt;strong&gt;Add Secret&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should see something like this:&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%2Fk9zrnl2zxms38sdrwkll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk9zrnl2zxms38sdrwkll.png" alt="keyshade secrets" width="800" height="225"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  Adding &lt;code&gt;NEXT_PUBLIC_PORT&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;The steps are exactly the same, just that you would be adding this one under &lt;strong&gt;Variable&lt;/strong&gt; tab. I'll be using &lt;code&gt;1234&lt;/code&gt; as the value for &lt;code&gt;default&lt;/code&gt;. Once you are done, you should be able to see this:&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%2Fzsyy4ft5dquej5lzxae6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzsyy4ft5dquej5lzxae6.png" alt="keyshade variables" width="800" height="221"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Seeing the magic in action
&lt;/h3&gt;

&lt;p&gt;To harness the power of keyshade, we need to use their CLI to run our scripts. So,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;would now become&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;keyshade run &lt;span class="nt"&gt;--&lt;/span&gt; npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see this in your terminal:&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%2F81p9f005kolaiohk3pc7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81p9f005kolaiohk3pc7.png" alt="keyshade run" width="800" height="537"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;From the output, note that keyshade has fetched the secret and variable that we created in the project before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ℹ️ INFO: Fetched 2 configurations &lt;span class="o"&gt;(&lt;/span&gt;1 secrets, 1 variables&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So now, when you head over to &lt;a href="https://localhost:3000" rel="noopener noreferrer"&gt;https://localhost:3000&lt;/a&gt;, you get to see the actual values for your configurations!&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%2Fwx4ovh31fiapi554og58.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwx4ovh31fiapi554og58.png" alt="keyshade in action" width="800" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;I'm sure you might have found this article useful, especially if you and your team have been struggling with secrets management. Keyshade covers up for most of the problems we developers face in our day-to-day jobs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When should you not use keyshade?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You might have got the intuition that this platform is pretty useless if you are a solo developer, working on a project locally. Keyshade also isn't helpful if your are building CLI applications, or mobile applications, or anything that would be running on an external environment (the client's device). &lt;/p&gt;

</description>
      <category>programming</category>
      <category>devops</category>
      <category>security</category>
      <category>opensource</category>
    </item>
    <item>
      <title>How keyshade employs the use of sockets in distributed environment</title>
      <dc:creator>Rajdip Bhattacharya</dc:creator>
      <pubDate>Mon, 06 May 2024 17:30:21 +0000</pubDate>
      <link>https://dev.to/keyshade/how-keyshade-employs-the-use-of-sockets-in-distributed-environment-2b0l</link>
      <guid>https://dev.to/keyshade/how-keyshade-employs-the-use-of-sockets-in-distributed-environment-2b0l</guid>
      <description>&lt;p&gt;Any web application that wants to integrate real-time responsiveness into their operations, will surely use web sockets in some way or the other. Socket programming is, nonetheless, difficult to implement, hence a library of softwares exist to ease our life a little bit.&lt;/p&gt;

&lt;p&gt;But there are scenarios when you can't use these tools due to the lack of flexibility, and you need to manually write your socket code. &lt;/p&gt;

&lt;p&gt;We were challenged with a similar problem at keyshade!&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;At the very core of our project, we have real-time notifications to client applications. This means, if your application is configured with keyshade, it will receive live updates regarding changes that happen in your configurations. This implies that your application will need to maintain a socket connection to our servers, which, by no means, is feasible (even if possible) to externalize our sockets. And so, our sockets are home baked.&lt;/p&gt;

&lt;p&gt;But, the plot thickens further!&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding to the problem
&lt;/h2&gt;

&lt;p&gt;But before we could implement this, we were met by yet another (major) blocker. Consider this scenario:&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%2Fe1429maa08jgr2k3debz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe1429maa08jgr2k3debz.png" alt="websocket-flow-1" width="800" height="925"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We are having an API cluster that has 3 instances. This cluster sits behind a load balancer, through which all connections are multiplexed (which I have dropped deliberately to reduce complexity). &lt;/p&gt;

&lt;p&gt;In this case, your client application (where you want to get live configuration updates) has connected to &lt;code&gt;Server A&lt;/code&gt;. But, when you are making changes, they are sent to &lt;code&gt;Server C&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This raises the concern about the scalability of web sockets in a distributed environment. As you can infer, sockets that are connected to &lt;code&gt;Server A&lt;/code&gt; won't receive any updates from &lt;code&gt;Server C&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;This brings us to our next section: the solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;After spending an entire day searching for the correct solution, I found none. There was not a single way on that I could "share" socket connections among various servers. So, we brought &lt;strong&gt;Redis' PubSub&lt;/strong&gt; into the picture.&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%2Fiha7ev973yfjt5bvnefs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiha7ev973yfjt5bvnefs.png" alt="redis pubsub" width="800" height="980"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The very fundamental of this approach was this: whenever a server started up, we would make it register to the &lt;code&gt;change-notifier&lt;/code&gt; topic of Redis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;afterInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logger&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="s1"&gt;Initialized change notifier socket gateway&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;redisSubscriber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change-notifier&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notifyConfigurationUpdate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&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;Next up, whenever a configuration's (secret or variable) value was changed, we would push an even to this channel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&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;publish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;change-notifier&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;environmentId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;variable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environmentId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;variable&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="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;isSecret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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 flow allowed us to achieve an architecture that is both scalable and ensures high availability!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>systemdesign</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Contributing to the cause: Doing it the open-source way</title>
      <dc:creator>Rajdip Bhattacharya</dc:creator>
      <pubDate>Sun, 24 Dec 2023 18:20:38 +0000</pubDate>
      <link>https://dev.to/thecodersden/contributing-to-the-cause-doing-it-the-open-source-way-3f1</link>
      <guid>https://dev.to/thecodersden/contributing-to-the-cause-doing-it-the-open-source-way-3f1</guid>
      <description>&lt;p&gt;Hello there!&lt;/p&gt;

&lt;p&gt;Lately, I have been getting quite a few messages about how one should get started with developing open source projects, or contributing to projects out there. This blog aims to address those queries with the fullest of my knowledge! I tend to clarify the what's and why's of open-source development before actually jumping into the action.&lt;/p&gt;

&lt;p&gt;Happy reading! &lt;/p&gt;

&lt;h2&gt;
  
  
  Intro
&lt;/h2&gt;

&lt;p&gt;One of the most important rule of software development (and any other kind for that matter) is this - &lt;strong&gt;Do not re-invent the wheel&lt;/strong&gt;. This means, we should stay away from working on developing something that already exists, and should reuse it. Therefore, developers often find themselves using a plethora of tools along with their projects to make their work (and lives) easier!&lt;/p&gt;

&lt;p&gt;But have you ever wondered where these tools come from? We surely don't pay for using any of these development tools (at-least most of them!). &lt;/p&gt;

&lt;p&gt;Well, these code (and also the binaries, sometimes) for these tools are hosted in a free, available to all and developer friendly space called &lt;strong&gt;Open Source&lt;/strong&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  So, what's Open Source?
&lt;/h2&gt;

&lt;p&gt;If you do a Google search, it will give you the following answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;denoting software for which the original source code is made freely available and may be redistributed and modified&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, if you have eagle eyes and can understand what that means, feel free to move on to the next section :D, For the likes of me (affinity towards elaborations), do follow on.&lt;/p&gt;

&lt;p&gt;Breaking down the definition, it tells us these few things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can host our software code in a "space"&lt;/li&gt;
&lt;li&gt;This "space" is free to use and available to the world&lt;/li&gt;
&lt;li&gt;Our code (and the software) can be distributed among other people, and also be reused by them.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, I'll be honest, this is too much an abstraction to build our understanding on. So let us give some life to it.&lt;/p&gt;

&lt;p&gt;The "space" that we have been referring to, can be any of the following: &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://gitlab.com/" rel="noopener noreferrer"&gt;GitLab&lt;/a&gt;, &lt;a href="https://bitbucket.org/" rel="noopener noreferrer"&gt;BitBucket&lt;/a&gt;, and many more. For this blog, we will stick to GitHub, since that's more beginner-friendly.&lt;/p&gt;

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

&lt;p&gt;GitHub is a place where developers can create their accounts and host their code, completely free of cost. Other users (and non-users) would also be able so see the code (until and unless you make it private). It is highly recommended that you check out their platform (and preferably create an account) before you move any further.&lt;/p&gt;

&lt;p&gt;Now that we have the stage set up (literally!), we are ready to delve deep into the "why's".&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use Open Source?
&lt;/h2&gt;

&lt;p&gt;So why all of this fuss, you might ask. To be very honest, this was my first question when I was introduced to open source. &lt;/p&gt;

&lt;p&gt;Setting up the scene: Before I started using Open Source to develop my tools, I used to do the following: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write and save my code locally.&lt;/li&gt;
&lt;li&gt;Whenever I had to make any major changes to the codebase, I used to make an archive of the existing code, give it some version number, and then get started with writing the updates.&lt;/li&gt;
&lt;li&gt;I used to share the zip files with my friends (who were from non-CS backgrounds) and asked them to MANUALLY set it up using the instructions.&lt;/li&gt;
&lt;li&gt;When it came to deployment, I used to upload the code to the server manually and make the deployment run there.&lt;/li&gt;
&lt;li&gt;And lastly, I was storing all of these zip files in my Google Drive&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, any novice can see that there is too much of a manual intervention required in all the steps. To be precise, here are the drawbacks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reverting the codebase is impossible if you don't create the versions MANUALLY.&lt;/li&gt;
&lt;li&gt;Distributing your code is a cumbersome task.&lt;/li&gt;
&lt;li&gt;Collaborating with your friends is next to impossible.&lt;/li&gt;
&lt;li&gt;Visibility of code is as poor as the fog in winter.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Back then, I believed that these were more than enough reasons for me to switch my old habits and learn something new. Not to mention, in the longer run, I found the switch helpful in more ways than I could possibly imagine.&lt;/p&gt;

&lt;p&gt;Here are a few solutions that Open Source development gives you for the above problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All open sourced software use &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt;, a tool (which is &lt;strong&gt;open-sourced&lt;/strong&gt; as well) that helps you in keeping a track of all the changes, giving you the ability to roll back, reset and fast forwards to any point of time.&lt;/li&gt;
&lt;li&gt;Since open sourced software are hosted free of cost, everyone is able to view your code.&lt;/li&gt;
&lt;li&gt;Collaboration is a cakewalk: git gives you the ability to develop your features on separate branches, while keeping the rest of the code intact.&lt;/li&gt;
&lt;li&gt;Additionally, it provides us with automated notifications, builds and releases if we decide to opt into it.&lt;/li&gt;
&lt;li&gt;Many companies open source their software to create a level of transparency with their user base. This helps them to gain trust.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If it's still unclear as to why people choose to develop their software for free, out in the open: It is because of the support of developer pool that you get &lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;I'm quite sure that you must be wanting to get your hands dirty, now that you have came across all of it. But, before you could move any further, you should be familiar with the concepts of &lt;strong&gt;Git&lt;/strong&gt;. It is the building block of every open source project. Now, since this blog isn't explicitly about git, I will attach a few links for you to get started: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/doc" rel="noopener noreferrer"&gt;https://git-scm.com/doc&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.atlassian.com/git" rel="noopener noreferrer"&gt;https://www.atlassian.com/git&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.w3schools.com/git/" rel="noopener noreferrer"&gt;https://www.w3schools.com/git/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that you are well versed with some of the git terminologies, let's proceed to the actual stuff!&lt;/p&gt;

&lt;h3&gt;
  
  
  Finding your repository
&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%2Fqxfzy3lnjyh27566dykh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxfzy3lnjyh27566dykh.png" alt="GitHub trending" width="800" height="523"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first step of this journey is to find yourself a decent project. You can search these projects from any of the following links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/trending" rel="noopener noreferrer"&gt;GitHub trending&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/search/advanced" rel="noopener noreferrer"&gt;GitHub advanced search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://starter-hive.vercel.app/projects" rel="noopener noreferrer"&gt;Starter Hive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://up-for-grabs.net/#/filters?tags=aws%2Ccloud%2Cjava%2Cjavascript%2Ctypescript%2Cweb" rel="noopener noreferrer"&gt;Up for grabs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To be very honest, selecting a project can be very tricky. There are a multitude of ways to shortlist a project, but here are some ways that I use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Look for the programming stack they use. Are you comfortable with it? Do you have any prior hands-on experience with it?&lt;/li&gt;
&lt;li&gt;Does the project align with your interest? Is it a tool, or a platform? Does using it feels good? - This matters because the emotional attachment with a project will stir a natural will in you to contribute to it.&lt;/li&gt;
&lt;li&gt;Is it being actively developed? - Active projects will give faster feedbacks, and your work will be known to the people.&lt;/li&gt;
&lt;li&gt;Are there any active issues in the &lt;strong&gt;Issues&lt;/strong&gt; tab? If no, you might consider moving on to another project.&lt;/li&gt;
&lt;li&gt;Can you understand the documentation? - You would be expected to set up the entire project locally without any help (most of the time). So it is super important that you can understand the docs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Getting accustomed to the project
&lt;/h3&gt;

&lt;p&gt;After you have made a decision, it is now time to start developing. Almost all the repositories follow the same pattern, and I will outline it for you.&lt;/p&gt;

&lt;h4&gt;
  
  
  The flow
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fork&lt;/strong&gt; the repository into your account&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%2Fa8qz8r5sv71zcmxn716s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa8qz8r5sv71zcmxn716s.png" alt="Fork" width="595" height="140"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clone&lt;/strong&gt; the fork into your local device&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%2Ff2srv5w03fo3p5l9fkho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff2srv5w03fo3p5l9fkho.png" alt="Clone" width="430" height="405"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Create&lt;/strong&gt; a new branch like: &lt;code&gt;feat/feature-name&lt;/code&gt; or &lt;code&gt;fix/fix-name&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git checkout -b feat/add-logout-button
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Develop&lt;/strong&gt; on the new branch&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first step is to set up the project. All projects vary in this step, but gladly there is a common thread:&lt;br&gt;
    - Go through the &lt;strong&gt;README.md&lt;/strong&gt; file. Most of the time it contains info about quick setup.&lt;br&gt;
    - Go through the &lt;strong&gt;CONTRIBUTIONS.md&lt;/strong&gt; file. This will contain detailed information about the setup, and might also provide links to other docs.&lt;br&gt;
    - Lastly, scan for a &lt;strong&gt;docs/&lt;/strong&gt; folder, this might contain all the help you will ever need.&lt;/p&gt;

&lt;p&gt;The next step would be to familiarize yourself with the codebase. Most of the repositories use &lt;a href="https://monorepo.tools/" rel="noopener noreferrer"&gt;monorepos&lt;/a&gt; for organizing and managing their code. A rule of the thumb here would be to make yourself familiar with what component lies in which place. It is next to impossible to understand the entire codebase at once. For starters, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand how the environmental variables are used&lt;/li&gt;
&lt;li&gt;Where does the UI/API/SDKs live&lt;/li&gt;
&lt;li&gt;Where does the project fetch its configs from&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Making your contributions
&lt;/h3&gt;

&lt;p&gt;Now, we are ready to head over to the issues of the project. Start small - pick up issues that have a relatively smaller scope of impact, like updating something in the docs, making minor UI fixes, making changes in the file names, etc. Some projects use the &lt;code&gt;good first use&lt;/code&gt; label to track such issues.&lt;/p&gt;

&lt;p&gt;After you have picked your issue, now it's time for you to get assigned to it. For this, consider joining the community of the project - Discord / Slack / Telegram. Many projects encourage you to ask the maintainer to assign you to an issue before you start working on it. Many ask you to put up a PR directly. Most of this is mentioned in the &lt;code&gt;CONTRIBUTIONS.md&lt;/code&gt; file. Again, the rule of the thumb in this step is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search for an issue&lt;/li&gt;
&lt;li&gt;Ask the maintainers to assign it to you over the issue comments.&lt;/li&gt;
&lt;li&gt;Optionally, you can provide a suggested way to fix the issue (this increases your chances of getting assigned)&lt;/li&gt;
&lt;li&gt;Once done, start following the code guidelines and doing what you do best!&lt;/li&gt;
&lt;li&gt;Always remember, deciding on the features with the help of the maintainers is a BIG PLUS. Although, &lt;strong&gt;keep in mind that you should not spam them.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Submitting a PR
&lt;/h3&gt;

&lt;p&gt;After you feel that the feature is working as expected, you should always add tests or update them. Making sure your tests are up-to-date and passing makes the merge process effortless. Before you commit the code, do make sure you have gone through the &lt;strong&gt;commit guidelines&lt;/strong&gt; of the project. Almost all projects use &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;this&lt;/a&gt; pattern.&lt;/p&gt;

&lt;p&gt;Finally, it is the time that you make the &lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#:~:text=Pull%20requests%20let%20you%20tell,merged%20into%20the%20base%20branch." rel="noopener noreferrer"&gt;pull request (PRs)&lt;/a&gt;. This is how you submit your code. To do this,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to your &lt;strong&gt;fork&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make sure your code is not outdated &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%2F8zgmajczm3ztjc2z16xd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8zgmajczm3ztjc2z16xd.png" alt="Sync branch" width="274" height="119"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the branch that you were working on&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%2F8d66xzm3uf7fkgk5czj5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8d66xzm3uf7fkgk5czj5.png" alt="branch" width="328" height="324"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Make the PR from under the contribute section.&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%2Fmjoflgukhi86ee3p7nso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmjoflgukhi86ee3p7nso.png" alt="Contribute" width="267" height="265"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This stage requires the least effort. Generally, if you have communicated your way through the implementation, your PR should be merged in a short time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Your gain from open-source
&lt;/h2&gt;

&lt;p&gt;We humans are outcome-oriented creatures. So, for every action that we do, we expect some sort a reward. And, in case of open-source there are "many" rewards.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You will be surrounding yourself with a like minded peer group who think and act alike. This will enhance your skill set and also, help you become a better human.&lt;/li&gt;
&lt;li&gt;You get to showcase your merged PRs on your portfolio! They will give you an upper hand in your itnerviews.&lt;/li&gt;
&lt;li&gt;You can get an offer from any of the project you are working on. Most of the open-sourced companies look for full time employees from their pool of open source contributors. Although a bit difficult to achieve, it is certainly possible!&lt;/li&gt;
&lt;li&gt;Lastly, you can go for bounties! Yes, bounties! Once you have quiet familiar with contributing, head over to &lt;a href="//algora.io"&gt;Algora&lt;/a&gt; and start getting paid for your work! &lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;To wrap up, I would say that, open-source is an ability that only software developers have. You get the opportunity to work with top class engineers, developing industry grade applications, all while improving your network. No hassle of interviews, no rat-race, no nothing! All that's needed is your time and dedication. &lt;/p&gt;

&lt;h2&gt;
  
  
  P.S.
&lt;/h2&gt;

&lt;p&gt;A note that I would like to leave here on behalf of all the maintainers out there, which I believe most will be in unison with - When a regular developer thinks about making himself a maintainer of a project, the responsibility comes with a great many challenges. That person is responsible for not only developing the crucial aspects of the project, but also in managing a swarm of developers. Not to mention the fact that, the maintainer choose to open source their product so that world can see and lend a hand in its growth (also, making it free to use). It is my request to all of you who's reading this, to treat them with the respect they are deserving of. Open source is not all about being good at coding, it is also about becoming a better human, and to develop a deeper sense of understanding and sharing responsibilites.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>programming</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Open source, AI, and CodiumAI's PR-Agent</title>
      <dc:creator>Rajdip Bhattacharya</dc:creator>
      <pubDate>Sat, 09 Dec 2023 06:10:14 +0000</pubDate>
      <link>https://dev.to/thecodersden/open-source-ai-and-codiumais-pr-agent-4pgc</link>
      <guid>https://dev.to/thecodersden/open-source-ai-and-codiumais-pr-agent-4pgc</guid>
      <description>&lt;p&gt;Hola geeks!&lt;/p&gt;

&lt;p&gt;Development, undoubtably, is a vast ocean. We can barely define a starting point and definitely no ending point. Like we all know, "Necessity is the mother of all inventions", our journey this far is no exception either. It all started with Sir Charles Babbage inventing the first computer, followed by a massive breakthrough when Sir Alan Turing developed the &lt;strong&gt;Turingery&lt;/strong&gt; during WWII to decipher the &lt;strong&gt;Enigma&lt;/strong&gt; code. This decade and the last have seen the creation of the most prolific systems and pieces of software that lay the foundation of modern day computing and software development. Throughout this entire journey, we have always been, and are, fascinated by one technology in particular - &lt;strong&gt;Artificial Intelligence&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;In our day-to-day lives, we interact with multiple software that employ AI to ease our work. Not only that, developers have put in efforts to bring AI to our loved IDEs for our ease of development! &lt;/p&gt;

&lt;p&gt;Undeniably, most of the development happen on &lt;strong&gt;GitHub&lt;/strong&gt;. Every developer in his/her life has come across GitHub to look for a solution or look at the code of some of the greatest &lt;strong&gt;open-source&lt;/strong&gt; repositories. GitHub says that there are a whooping &lt;strong&gt;94 million&lt;/strong&gt; developers who are actively contributing and developing in the open-source industry!&lt;/p&gt;

&lt;p&gt;This brings us to an important concept - a &lt;strong&gt;PR&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So what's a PR?
&lt;/h2&gt;

&lt;p&gt;For any developer out there, who is a contributor to any &lt;strong&gt;OSS&lt;/strong&gt;, certainly know about &lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#:~:text=Pull%20requests%20let%20you%20tell,merged%20into%20the%20base%20branch." rel="noopener noreferrer"&gt;&lt;strong&gt;pull requests (PRs)&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In case you heard this term for the first time (or perhaps you want a refresher), whenever we &lt;strong&gt;contribute&lt;/strong&gt; any changes to an open source project, we do it via a pull request (PR). For doing this, you first write your code in a separate branch, then you head over to the repository to create a PR. This is done with the intention of giving the maintainers a glance into the changes you made and test the correctness/feasibility of your changes. &lt;/p&gt;

&lt;p&gt;This brings us to a gradual conclusion that, for our PRs to be accepted, we need the maintainers to have a full picture of the changes we made. As humans, we are bound to make mistakes, the top ones being:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inaccurate/incomplete description about the changes you made&lt;/li&gt;
&lt;li&gt;Bugs/errors/potential security issues in your code base&lt;/li&gt;
&lt;li&gt;And most importantly, the lack of energy to write a concise PR.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These errors are mostly fixable, but there's someone (some"thing") that could make our lives a lot easier: &lt;strong&gt;CodiumAI's PR-Agent&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A quick glance into CodiumAI
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.codium.ai/" rel="noopener noreferrer"&gt;CodiumAI&lt;/a&gt; is an AI based product that helps developers in doing their stuff. Their plugins sit inside your IDEs, helping you out in your code by doing a significant heavy lifting. They provide automated tests for your code, that not only makes your code more resilient, but also aids in ramping up your efficiency and productivity. And the best part is, &lt;strong&gt;CodiumAI is entirely &lt;a href="https://github.com/Codium-ai" rel="noopener noreferrer"&gt;open-sourced&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  PR-Agent by CodiumAI
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://www.codium.ai/products/git-plugin/" rel="noopener noreferrer"&gt;PR-Agent&lt;/a&gt; is an AI-based Git plugin developed by CodiumAI. It helps us in our open-source journey by accomplishing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Auto-Description:&lt;/strong&gt; Automatically generating the description about the entire PR that includes name, summary and code walkthrough.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt; PR Review:&lt;/strong&gt; Automated smart feedbacks about possible errors or bugs in our code&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Question Answering:&lt;/strong&gt; Helps us in querying the different aspects of the PR.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code Suggestion:&lt;/strong&gt; Suggestions about possible improvement scope for our code to polish our PR.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Finally, the hands-on!
&lt;/h2&gt;

&lt;p&gt;Skills are pointless until and unless you practice using them for your own good! And the fact that we are learning about an absolute game changer, this blog would be incomplete without a hands-on section.&lt;/p&gt;

&lt;p&gt;We would take a wild ride doing the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installing PR-Agent&lt;/li&gt;
&lt;li&gt;Creating a pull request&lt;/li&gt;
&lt;li&gt;Creating a detailed description of what the PR is about.&lt;/li&gt;
&lt;li&gt;Tagging our PR&lt;/li&gt;
&lt;li&gt;We will ask the PR-Agent to give us a review on our PR (oh, how badly I strive to get a review!)&lt;/li&gt;
&lt;li&gt;Of course, we are bound to make mistakes. We will detect the errors in our code.&lt;/li&gt;
&lt;li&gt;We will take a glance into how PR-Agent helps us in fixing the error. &lt;/li&gt;
&lt;li&gt;Making further improvements by adding documentation.&lt;/li&gt;
&lt;li&gt;Generating a CHANGELOG&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can follow this &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/TOOLS_GUIDE.md" rel="noopener noreferrer"&gt;article&lt;/a&gt; throughout the blog to have a reference. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE: Custom configs to be covered in the later half!&lt;/strong&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  Installing PR-Agent
&lt;/h3&gt;

&lt;p&gt;Here is the nice part about PR-Agent: It enables you to use the tool without even any installation. All you need to do is &lt;code&gt;@CodiumAI-Agent &amp;lt;command&amp;gt;&lt;/code&gt; (commands to be discussed later), and it will do its magic! &lt;/p&gt;

&lt;p&gt;But there are some drawbacks as well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The first being, you have to put a mention tag (@CodiumAI-Agent) in front of every command.&lt;/li&gt;
&lt;li&gt;Not all commands will work with the mention tag. 
That being said, it's safe to say that you get a sort of "trial" of the tool without installing it. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, to further extend its capabilities, an installation is necessary. For doing that, head over to this &lt;a href="https://github.com/marketplace/codiumai-pr-agent" rel="noopener noreferrer"&gt;link&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%2Fh08otl64jv4hcs3737zc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh08otl64jv4hcs3737zc.png" alt="PR-Agent marketplace" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One important thing, before you proceed, make sure you are logged on to GitHub.&lt;/p&gt;

&lt;p&gt;As you can see, it's free for individual developers! Next, scroll down and hit on &lt;strong&gt;Install it for free&lt;/strong&gt;&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%2Fia51fcr0jt0bnpyw39h0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fia51fcr0jt0bnpyw39h0.png" alt=" " width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will take you to a billing page, where you have to enter your billing details. Rest assured, you won't have to add any banking details, nor will you be charged a single penny. &lt;/p&gt;

&lt;p&gt;Once everything is successful, you would be redirected to the integration page of your GitHub profile.&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%2F00tgbvzuf2i908cly1nv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F00tgbvzuf2i908cly1nv.png" alt="GitHub integrations" width="800" height="751"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In case you want to visit this page later on for some reason, you can do it by visiting &lt;strong&gt;Profile Icon&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Settings&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Integrations&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Applications&lt;/strong&gt; -&amp;gt; &lt;strong&gt;CodiumAI PR-Agent&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Creating the PR
&lt;/h3&gt;

&lt;p&gt;There are numerous ways to get started with this. I won't be digging into creating the PR, but here's an article that will help you to follow along: &lt;a href="https://docs.github.com/en/desktop/working-with-your-remote-repository-on-github-or-github-enterprise/creating-an-issue-or-pull-request-from-github-desktop" rel="noopener noreferrer"&gt;https://docs.github.com/en/desktop/working-with-your-remote-repository-on-github-or-github-enterprise/creating-an-issue-or-pull-request-from-github-desktop&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the context, I have created a PR to my own portfolio repository, where I have intended to add some code to include my Twitter account in my portfolio. Again, the code base doesn't matter, since the PR-Agent works with any and every code base.&lt;/p&gt;

&lt;p&gt;Here is a glimpse of the initial PR:&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%2Fs57yh7ecevau3xa1fjt1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs57yh7ecevau3xa1fjt1.png" alt="PR" width="800" height="229"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It looks pretty empty (and useless). Let's give it the shine it deserves.&lt;/p&gt;
&lt;h3&gt;
  
  
  Describing the scope of the PR. (&lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/DESCRIBE.md" rel="noopener noreferrer"&gt;/describe&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;As you saw in the above image, our PR looks pretty barren. Creating PRs have a sole purpose of integrating the changes we made into the existing code base. For that to happen, we want our reviewers to have a clear understanding of what the PR does. Thankfully, our AI buddy makes it a breeze of an effort! Let's see how.&lt;/p&gt;

&lt;p&gt;Head over to the comment section, and enter:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If you have set up everything correctly, Codium-AI will "see" your comment (literally). Notice the "eyes" reaction:&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%2F8t3we77khdvk2u6xsy55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8t3we77khdvk2u6xsy55.png" alt="/describe comment" width="800" height="154"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, the tool will do the following things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Add a comment stating it has updated the PR description and title&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%2F8noqqzfasb82lb7h3gst.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8noqqzfasb82lb7h3gst.png" alt="/describe update notification" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add the PR description and change the PR title&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%2F9gmawr8rglpz3l3p8i6k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9gmawr8rglpz3l3p8i6k.png" alt="/describe updated PR description and title" width="800" height="677"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Tagging our PR (&lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/GENERATE_CUSTOM_LABELS.md" rel="noopener noreferrer"&gt;/generate_labels&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;GitHub (and every other platform) provides us with the ability to search issues and pull requests using tags. Tags help us categorize the issues. Here is a glimpse of the PR-Agent issues in GitHub.&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%2F7z9wcny2mvb4wrn9ptxk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7z9wcny2mvb4wrn9ptxk.png" alt="codium ai pr agent issues" width="800" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PR Agent gives us the ability to generate meaningful labels of our PRs. Here's how you do it:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmolhqzvyt6wficgqfgju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmolhqzvyt6wficgqfgju.png" alt="/generate label output" width="800" height="190"&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%2F663nefqtilnkm5kfk0zm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F663nefqtilnkm5kfk0zm.png" alt="/generate label output" width="326" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the label &lt;strong&gt;enhancement&lt;/strong&gt; was inferred from the changes we made.&lt;/p&gt;

&lt;p&gt;This doesn't end here, as we can inform the AI to use custom labels for pre-defined changes. More on that later.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feedbacks are important (&lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/REVIEW.md" rel="noopener noreferrer"&gt;/review&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;Often times you will find yourself struggling to get a concise feedback on your work. Feedbacks enable us to further improve on our code and make it much more efficient. Along with it, you also get to know about the compatibility of the new features that you introduced with the existing code. &lt;/p&gt;

&lt;p&gt;However challenging this might sound, fear not, because our AI partner has got our backs!&lt;/p&gt;

&lt;p&gt;All you need to do is, type in:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;p&gt;As you can see, the review cover a great details. It has even got the &lt;strong&gt;Estimated effort to review [1-5]&lt;/strong&gt; scale that comes in super handy to the maintainers.&lt;/p&gt;

&lt;p&gt;Now that we got a brief about the internals of the code, let's see if our code works as expected or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Looking for scopes of improvement (&lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/IMPROVE.md" rel="noopener noreferrer"&gt;/improve&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;As humans, we tend to make mistakes. The PR-Agent gives us a handle &lt;code&gt;/improve&lt;/code&gt; to scan for possible errors / bugs.&lt;/p&gt;

&lt;p&gt;We run this, (and all of the commands to follow) in the same way we ran the previous command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzt3andne9hd44aiil78.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbzt3andne9hd44aiil78.png" alt="/improve 1" width="800" height="593"&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%2Fg2svwuxlsjb8f1x6qgxu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg2svwuxlsjb8f1x6qgxu.png" alt="/improve 2" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we do have issues in our codebase! I have mistakenly (deliberately) used the wrong URL for my twitter account.&lt;/p&gt;

&lt;p&gt;Now, let's see how we can fix them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Got questions? All you need to do is &lt;code&gt;/ask&lt;/code&gt;!
&lt;/h3&gt;

&lt;p&gt;Although we got the error, we still don't know what's causing it, or what we should do to fix it. In such scenarios, we can use the &lt;code&gt;ask&lt;/code&gt; command. The usage of this command is similar to the previous one, just that it takes a question as the parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/ask &amp;lt;your question&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, let's ask our AI buddy "how should we fix this?"&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%2Fl5op8bpp2g55bumrbptf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl5op8bpp2g55bumrbptf.png" alt="/ask output" width="800" height="630"&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%2F3pp7do2u8mbtg4j0vp1p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pp7do2u8mbtg4j0vp1p.png" alt="/ask output" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And we see a neatly formatted and concise message, explaining us what we should do to fix our issue.&lt;/p&gt;

&lt;p&gt;Now we can fix the errors, and can make a push.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  Scope for adding documentation (&lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/ADD_DOCUMENTATION.md" rel="noopener noreferrer"&gt;/add_docs&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;Documenting our code, although might seem boring, but is an extremely important task in software development. Generally, any software that gets written, has a bulk of documentation associated with it. &lt;/p&gt;

&lt;p&gt;Often times, while implementing some fix or adding some feature, we miss out on docs. PR Agent helps us in finding those spots where we can add documentation.&lt;/p&gt;

&lt;p&gt;We do this by:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmlftoqol0luzgtmy7z7z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmlftoqol0luzgtmy7z7z.png" alt="/add_docs 1" width="800" height="708"&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%2F1gx46c88x9u1kxdxgmre.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1gx46c88x9u1kxdxgmre.png" alt="/add_docs 2" width="800" height="592"&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%2Fxf68d1ulghjganshl0en.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf68d1ulghjganshl0en.png" alt="/add_docs 3" width="800" height="583"&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%2Frn1suytj8pkpqfh0mosh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frn1suytj8pkpqfh0mosh.png" alt=" " width="800" height="605"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the tool gives us a bunch of things that can be documented.&lt;/p&gt;

&lt;p&gt;Now, I am that lazy developer who never writes the docs. So I'll as my AI buddy to do it for me :D&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%2Fi840rlgf8j72wejmz8sl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi840rlgf8j72wejmz8sl.png" alt="ask for docs" width="800" height="150"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;And as you can see, it gave me the things I need to change, all I need to do is copy and paste.&lt;/p&gt;

&lt;h3&gt;
  
  
  Generating a CHANGELOG (&lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/UPDATE_CHANGELOG.md" rel="noopener noreferrer"&gt;/update_changelog&lt;/a&gt;)
&lt;/h3&gt;

&lt;p&gt;Every project has a file called &lt;code&gt;CHANGELOG.md&lt;/code&gt;. In case you are wondering what that is, it is a ledger that keeps track of all the changes that were made in a specific version. It mosly contains these things in this format&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[version]&lt;/span&gt;

&lt;span class="err"&gt;-&lt;/span&gt; &lt;span class="err"&gt;things&lt;/span&gt; &lt;span class="err"&gt;added&lt;/span&gt;
&lt;span class="err"&gt;-&lt;/span&gt; &lt;span class="err"&gt;things&lt;/span&gt; &lt;span class="err"&gt;fixed&lt;/span&gt;
&lt;span class="err"&gt;-&lt;/span&gt; &lt;span class="err"&gt;things&lt;/span&gt; &lt;span class="err"&gt;removed&lt;/span&gt;
&lt;span class="err"&gt;-&lt;/span&gt; &lt;span class="err"&gt;anything&lt;/span&gt; &lt;span class="err"&gt;else&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Changelog is an important component that helps us in visibility, hence it becomes extremely important to manage it properly. &lt;/p&gt;

&lt;p&gt;PR Agent helps us in this by generating a CHANGELOG for all the changes made in the particular PR. We do it by:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;p&gt;We do have a small change that we made, and hence the log file is small, but this does demonstrate us the capability of the tool in assessing our file!&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom configuration - going a step further
&lt;/h2&gt;

&lt;p&gt;We have already crossed two big steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using the commands via @CodiumAI-Agent mention&lt;/li&gt;
&lt;li&gt;Using the commands via local installation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While we feel we might have everything that we need, this approach might not fit bigger projects. Such projects have a more "focused" way of tracking their changes, and might want the PR-Agent to be customized as per their wishes. &lt;/p&gt;

&lt;p&gt;But fear not, because we do have complete authority over how and what CodiumAI PR Agent does!&lt;/p&gt;

&lt;p&gt;The local installation comes with a pre-defined configuration file (&lt;code&gt;.pr_agent.toml&lt;/code&gt;) that hosts all the settings that PR Agent will use. &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/Usage.md#working-with-github-app" rel="noopener noreferrer"&gt;This&lt;/a&gt; article explains you how you can get a customized PR Agent at your fingertips.&lt;/p&gt;

&lt;p&gt;Since the article covers a lot, and the configurations can seem overwhelming at the beginning, I will try to break it down to you by demonstrating how to generate custom labels based on the changes you made (now we're getting at it!).&lt;/p&gt;

&lt;p&gt;One important note, you might have to close your existing PR before your do this. PR Agent expects you have your configurations in place before you make the PR. (Gah... sorry for breaking it to you this late). &lt;/p&gt;

&lt;h3&gt;
  
  
  Customize your AI buddy
&lt;/h3&gt;

&lt;p&gt;We will get started by creating a &lt;code&gt;.pr_agent.toml&lt;/code&gt; file in the root directory of the project. Note that this should be the &lt;strong&gt;main&lt;/strong&gt; branch of your project.&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%2Fo712fm06c2y3x39yfa72.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo712fm06c2y3x39yfa72.png" alt="project root" width="800" height="568"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the custom configurations are mentioned in the individual &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/TOOLS_GUIDE.md" rel="noopener noreferrer"&gt;tool guides&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We want to do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Label our PR as &lt;strong&gt;Link Update&lt;/strong&gt; if any link is updated in our code&lt;/li&gt;
&lt;li&gt;Label our PR as &lt;strong&gt;Code Update&lt;/strong&gt; if any code changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Head over to the &lt;a href="https://github.com/Codium-ai/pr-agent/blob/main/docs/GENERATE_CUSTOM_LABELS.md" rel="noopener noreferrer"&gt;custom labels&lt;/a&gt; guide to see what all things you can change. We will insert these configs into our &lt;code&gt;.pr_agent.toml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[config]&lt;/span&gt;
&lt;span class="py"&gt;enable_custom_labels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="nn"&gt;[custom_labels."Link Update"]&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Whenever any link in the code is updated"&lt;/span&gt;

&lt;span class="nn"&gt;[custom_labels."Code Update"]&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Whenever any code is updated"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's break this down.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[config]&lt;/span&gt;
&lt;span class="py"&gt;enable_custom_labels&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells the PR Agent that we want to use custom labels. What this means to the tool is, besides using its own rules for evaluating our PR labels, it will also look throught the &lt;code&gt;.pr_agent.toml&lt;/code&gt; file to find user-defined rules for generating labels. User-defined labels have higher priority, which mean, given 2 rules - user-defined and pre-defined, PR Agent will use our rule for generating the labels.&lt;/p&gt;

&lt;p&gt;The next two blocks have a simple format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[custom_labels."Assign this label"]&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"When this condition satisfies"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[custom_labels."Link Update"]&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Whenever any link in the code is updated"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This block tells the PR Agent to assign the &lt;strong&gt;Link Update&lt;/strong&gt; label whenever any link in the code is updated.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[custom_labels."Code Update"]&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Whenever any code is updated"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This block tells the PR Agent to assign the &lt;strong&gt;Code Update&lt;/strong&gt; label whenever any code is updated.&lt;/p&gt;

&lt;p&gt;Once you have committed the changes to the main branch, you can open up another PR to test these settings.&lt;/p&gt;

&lt;p&gt;Let's give it a run:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpp49oyw1goiyo73gh65.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flpp49oyw1goiyo73gh65.png" alt="custom generate_labels" width="800" height="196"&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%2Fhguy1qk69zdfl7t12bgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhguy1qk69zdfl7t12bgb.png" alt="custom generate_labels" width="310" height="85"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we were successful in generating custom labels for us.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;PR-Agent is certainly a game changer in the world of open source (and also closed source). It is an all-in-one package for developers and maintainers, allowing us to lift the weight of manual review and documentation off our shoulders. Doing this gives our productivity an extra polish, thereby leading us to develop with speed and accuracy.&lt;/p&gt;

&lt;p&gt;The fact that the plugin is open-source and free of cost is a cherry on the top, setting no bounds for developers.&lt;/p&gt;

&lt;p&gt;But why stop in using the tool? Why not contribute to the cause? &lt;a href="https://github.com/Codium-ai/pr-agent" rel="noopener noreferrer"&gt;Jump right in!&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>github</category>
      <category>development</category>
    </item>
    <item>
      <title>Automating Python Deployments with GitHub Actions, AWS ECR, and AWS Lambda</title>
      <dc:creator>Rajdip Bhattacharya</dc:creator>
      <pubDate>Sat, 14 Oct 2023 07:38:03 +0000</pubDate>
      <link>https://dev.to/thecodersden/automating-python-deployments-with-github-actions-aws-ecr-and-aws-lambda-1d62</link>
      <guid>https://dev.to/thecodersden/automating-python-deployments-with-github-actions-aws-ecr-and-aws-lambda-1d62</guid>
      <description>&lt;p&gt;Greetings everyone!&lt;/p&gt;

&lt;p&gt;Welcome to the second part of this &lt;a href="https://dev.to/thecodersden/building-serverless-python-apps-with-aws-lambda-and-docker-3ab2"&gt;blog&lt;/a&gt;. As promised earlier, I told you that I'll be setting up a deployment pipeline using &lt;strong&gt;GitHub Actions&lt;/strong&gt; for our Python code. And here we are!&lt;/p&gt;

&lt;h2&gt;
  
  
  A brief revisit
&lt;/h2&gt;

&lt;p&gt;For those, who haven't read the &lt;a href="https://dev.to/thecodersden/building-serverless-python-apps-with-aws-lambda-and-docker-3ab2"&gt;previous blog&lt;/a&gt; or would just like to brush up their knowledge, here is what we have built so far:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A python code base specialized for a lambda function that extracts a field called &lt;code&gt;name&lt;/code&gt; from the &lt;strong&gt;lambda event&lt;/strong&gt; and returns us a greeting.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Dockerfile&lt;/strong&gt; for containerizing our code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS ECR&lt;/strong&gt; for hosting our image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Lambda&lt;/strong&gt; for hosting our function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, we employed the use of Terraform as IaC to deploy our AWS infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;p&gt;This part covers just a single, but a critical aspect - creating the build and deploy pipeline for our Python code. Here's what we are going to do: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a GitHub repository&lt;/li&gt;
&lt;li&gt;Write the code for our pipeline&lt;/li&gt;
&lt;li&gt;Configure the secrets in our repository&lt;/li&gt;
&lt;li&gt;Push the code, sit back, and watch the magic in action&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the code for this blog in &lt;a href="https://github.com/rajdip-b/python-ecr-lambda-tf" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So, let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a GitHub repository
&lt;/h2&gt;

&lt;p&gt;I shouldn't be saying this, but, you do need to have a GitHub account to continue further. Once you have it, go &lt;a href="https://github.com/new" rel="noopener noreferrer"&gt;here&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%2Fb9dxxtos9tyxaf93q96n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb9dxxtos9tyxaf93q96n.png" alt="GitHub create repository" width="779" height="890"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'll be using the above configurations to get started.&lt;/p&gt;

&lt;p&gt;Next, you should have a brand-new repository ready at your disposal!&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%2F14x7my79rpgcfh3f2vrr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F14x7my79rpgcfh3f2vrr.png" alt="GitHub repository" width="800" height="402"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Building our pipeline
&lt;/h2&gt;

&lt;p&gt;This is perhaps the most critical part. For getting started, we need to create a file in our project as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.github/workflows/ecr-lambda.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The folder naming convention is necessary since GitHub treats all files under the &lt;code&gt;workflows&lt;/code&gt; folder as a pipeline.&lt;/p&gt;

&lt;p&gt;Next, we create the pipeline.&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;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;master&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Lambda ECR Deployment&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/master'&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to ECR and update Lambda&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

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

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure AWS credentials&lt;/span&gt;
              &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v1&lt;/span&gt;
              &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;aws-access-key-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.ACCESS_KEY }}&lt;/span&gt;
                  &lt;span class="na"&gt;aws-secret-access-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SECRET_KEY }}&lt;/span&gt;
                  &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ap-south-1&lt;/span&gt;

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Login to Amazon ECR&lt;/span&gt;
              &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;login-ecr&lt;/span&gt;
              &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/amazon-ecr-login@v1&lt;/span&gt;

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build, tag, and push the image to Amazon ECR&lt;/span&gt;
              &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build-image&lt;/span&gt;
              &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
                  &lt;span class="s"&gt;# Build a docker container and push it to ECR &lt;/span&gt;
                  &lt;span class="s"&gt;echo "Registry: ${{ vars.ECR_REGISTRY }}"&lt;/span&gt;
                  &lt;span class="s"&gt;aws ecr get-login-password --region ap-south-1 | docker login --username AWS --password-stdin ${{ vars.ECR_REGISTRY }}&lt;/span&gt;
                  &lt;span class="s"&gt;docker build -t ${{ vars.ECR_REGISTRY }}/${{ vars.ECR_REPOSITORY }}:latest .&lt;/span&gt;
                  &lt;span class="s"&gt;echo "Pushing image to ECR..."&lt;/span&gt;
                  &lt;span class="s"&gt;docker push ${{ vars.ECR_REGISTRY }}/${{ vars.ECR_REPOSITORY }}:latest&lt;/span&gt;
                  &lt;span class="s"&gt;echo "name=image::${{ vars.ECR_REGISTRY }}/${{ vars.ECR_REPOSITORY }}:latest" &amp;gt;&amp;gt; $GITHUB_OUTPUT&lt;/span&gt;

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update AWS Lambda function&lt;/span&gt;
              &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;update-lambda&lt;/span&gt;
              &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
                  &lt;span class="s"&gt;aws lambda update-function-code --function-name ${{ vars.LAMBDA_FUNCTION_NAME }} --image-uri ${{ vars.ECR_REGISTRY }}/${{ vars.ECR_REPOSITORY }}:latest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'll explain what this code does step-by-step. It is recommended that you copy and paste the code into an IDE to follow along the description, as I will be using line numbers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Lines 1-3 specify which branch this pipeline would activate on. Right now, the pipeline will be activated only when we &lt;strong&gt;push&lt;/strong&gt; to the &lt;strong&gt;master&lt;/strong&gt; branch.&lt;/li&gt;
&lt;li&gt;Line 5 states the name of the pipeline&lt;/li&gt;
&lt;li&gt;Lines 7-42 define the jobs that will run&lt;/li&gt;
&lt;li&gt;Line 8 defines the only job that will be run by this pipeline.&lt;/li&gt;
&lt;li&gt;Line 9 ensures to run this pipeline only when the code is pushed into the master branch.&lt;/li&gt;
&lt;li&gt;Line 13 lists the steps to be followed in this job&lt;/li&gt;
&lt;li&gt;Line 15 uses the community GitHub checkout action to check out the repository on the pipeline whenever a new push is made.&lt;/li&gt;
&lt;li&gt;Lines 18-26 tries to log into our AWS account using the credentials provided in lines 20-22.&lt;/li&gt;
&lt;li&gt;Lines 31-37 builds, tags, and pushes the docker image to the ECR repository.&lt;/li&gt;
&lt;li&gt;Line 42 updates the lambda function's code to deploy the most recent version of our code. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Configuring our GitHub repository
&lt;/h2&gt;

&lt;p&gt;Note that in our workflow file, we have used some special syntax like &lt;code&gt;${{vars.ECR_REGISTRY}}&lt;/code&gt; and &lt;code&gt;${{secrets.ACCESS_KEY}}&lt;/code&gt;. These are GitHub Action Secret and Environmental variables. Using this approach gives us two benefits: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We don't need to change our code when some configuration changes.&lt;/li&gt;
&lt;li&gt;Our secrets stay safe when it's not in the code. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To add your own secrets and environmental variables, head over to your repository and then go to &lt;strong&gt;Settings-&amp;gt;Secrets and Variables-&amp;gt;Actions&lt;/strong&gt;. Here, we find 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%2Ftc52kmk8jj874ibh9jt5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftc52kmk8jj874ibh9jt5.png" alt="GitHub actions" width="783" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next step, add the secret (ACCESS_KEY, SECRET_KEY) in the &lt;strong&gt;Secrets&lt;/strong&gt; tab and the rest in the &lt;strong&gt;Variables&lt;/strong&gt; tab like this:&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%2Fzfyequh6bdja4l02dams.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzfyequh6bdja4l02dams.png" alt="GitHub Action Secrets" width="792" height="658"&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%2Fhvwhfiihn56fs6r7ipey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhvwhfiihn56fs6r7ipey.png" alt="GitHub Action Variables" width="792" height="749"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are some limitations on using the &lt;strong&gt;Variables&lt;/strong&gt; though, you can read about them from &lt;a href="https://docs.github.com/en/actions/learn-github-actions/variables" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Showdown
&lt;/h2&gt;

&lt;p&gt;Now that we have all the bits in their places, we are ready to jump into action.&lt;/p&gt;

&lt;p&gt;To do this,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initialize a git repository in your project&lt;/li&gt;
&lt;li&gt;Make sure you refactor/remove the access and secret keys from your Terraform config (Only if you have been following since the last blog).&lt;/li&gt;
&lt;li&gt;Push the code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After a successful push, you can head over to your repository and click on the &lt;strong&gt;Actions&lt;/strong&gt; tab. Here, you will find your pipelines.&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%2F0m2gjjhg4d5an7cn3ava.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0m2gjjhg4d5an7cn3ava.png" alt="GitHub Action pipelines" width="800" height="403"&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%2Fcwk7qgvz9c2exqspru4q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcwk7qgvz9c2exqspru4q.png" alt="Pipeline details" width="800" height="403"&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%2Fcscb04w1kmbzdapm7i7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcscb04w1kmbzdapm7i7k.png" alt="Step details" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, whenever you make a change to your python code, your changes would be automatically deployed into AWS Lambda when you push your code into the repository!&lt;/p&gt;

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

&lt;p&gt;With that, we come to the end of this blog. I hope you have enjoyed reading through this and didn't actually fall asleep. I hope to bring more such blogs related to DevOps very frequently, so, I would encourage you nice readers to ping my up with ideas that you would like to see in action! Until the next time, happy hacking!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>python</category>
      <category>cloud</category>
      <category>aws</category>
    </item>
    <item>
      <title>Building Serverless Python Apps with AWS Lambda and Docker</title>
      <dc:creator>Rajdip Bhattacharya</dc:creator>
      <pubDate>Mon, 09 Oct 2023 14:52:38 +0000</pubDate>
      <link>https://dev.to/thecodersden/building-serverless-python-apps-with-aws-lambda-and-docker-3ab2</link>
      <guid>https://dev.to/thecodersden/building-serverless-python-apps-with-aws-lambda-and-docker-3ab2</guid>
      <description>&lt;p&gt;Greetings geeks!&lt;/p&gt;

&lt;p&gt;Welcome to another blog on how to get your stuff done (the easy way)! In this blog, we will be taking a look at how to deploy dockerized Python code on AWS Lambda. Not only that, we will be setting up our AWS environment using Terraform to reduce the chances of blowing up our servers without our knowledge. So, let's get started!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &lt;a href="https://aws.amazon.com/lambda/" rel="noopener noreferrer"&gt;Lambda&lt;/a&gt;?
&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%2Fnm2zladfamat73tvwndw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnm2zladfamat73tvwndw.png" alt="AWS Lambda" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This question is not uncommon. In case you have felt it as well, you have come to the right place! When we use &lt;strong&gt;Lambda functions&lt;/strong&gt; in place of traditional EC2 servers, we are taking a big leap into the world of &lt;strong&gt;serverless computing&lt;/strong&gt;. This technique enables us to focus only on the business logic of our product, while the cloud provider does the heavy-lifting of setting up the environment for us. &lt;/p&gt;

&lt;h2&gt;
  
  
  An use-case of Lambda
&lt;/h2&gt;

&lt;p&gt;AWS Lambda has a special use case in the industry. Consider this simple 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%2Fmn55504v8rx3pvo1jij5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmn55504v8rx3pvo1jij5.png" alt="Lambda use case 1" width="800" height="670"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This diagram demonstrates a caption generation API that does the following (The abstraction of intricate details is deliberate):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Take in a video&lt;/li&gt;
&lt;li&gt;Store the video&lt;/li&gt;
&lt;li&gt;Generate its captions&lt;/li&gt;
&lt;li&gt;Store the caption along with the video&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is one design flaw in here. We might have a case that the &lt;code&gt;Upload API&lt;/code&gt; might have authentication and authorization to filter out who can upload videos. But we can easily point out that, the video generation doesn't require any authentication, i.e, it can operate autonomously. This is where lambda can help us. We are also increasing the workload on &lt;code&gt;Upload API&lt;/code&gt; in this flow. The next diagram shows the optimized design:&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%2F904u9mf8bqwhj2sgaqj5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F904u9mf8bqwhj2sgaqj5.png" alt="Lambda use case 2" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, we have separated the caption generator to another component called &lt;code&gt;Caption Generator&lt;/code&gt;. You can think of this as a component. It does the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Retrieve the video from storage (eg- S3)&lt;/li&gt;
&lt;li&gt;Process the video and generate captions&lt;/li&gt;
&lt;li&gt;Return the captions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Through this design, we achieved the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implemented separation of concern and single responsibility principle.&lt;/li&gt;
&lt;li&gt;Reduced workload on &lt;code&gt;Upload API&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, you might be wondering, how do you actually host this &lt;code&gt;Caption Generator&lt;/code&gt;. Well, you have your answer - AWS Lambda! Lambda functions are meant for exactly such use cases, where you can isolate autonomous functionalities into separate services and host them. The &lt;code&gt;Upload API&lt;/code&gt; can then &lt;strong&gt;invoke&lt;/strong&gt; the &lt;code&gt;Caption Generator&lt;/code&gt; when it will need to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our roadmap
&lt;/h2&gt;

&lt;p&gt;Implementing the above service can take quite some amount of coding. To keep this tutorial simple, we will implement a Hello World function for starters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create Python code for the Hello World function.&lt;/li&gt;
&lt;li&gt;Dockerize the code.&lt;/li&gt;
&lt;li&gt;Initialize Terraform&lt;/li&gt;
&lt;li&gt;Create ECR.&lt;/li&gt;
&lt;li&gt;Deploy our code.&lt;/li&gt;
&lt;li&gt;Create Lambda function.&lt;/li&gt;
&lt;li&gt;Test our function.&lt;/li&gt;
&lt;li&gt;Cleaning up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the code for this blog in &lt;a href="https://github.com/rajdip-b/python-ecr-lambda-tf" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Did you say Python?
&lt;/h2&gt;

&lt;p&gt;Yes, Python! Perhaps one of the easiest languages for getting started. Lambda supports a lot of &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html" rel="noopener noreferrer"&gt;runtimes&lt;/a&gt;. Do check them out if you are interested. Here is a glimpse:&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%2F82cho32jh650b4mtd48b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82cho32jh650b4mtd48b.png" alt="Lambda runtimes" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, we need to create a file named &lt;code&gt;lambda_function.py&lt;/code&gt;. The naming convention is necessary since we will be using a base image that utilizes this name.&lt;/p&gt;

&lt;h3&gt;
  
  
  Short note on using containerized build.
&lt;/h3&gt;

&lt;p&gt;Lambda supports three sources of code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Single file code:&lt;/strong&gt; used for smaller use cases such as testing and demonstration and is not often recommended for production environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zipped up code from S3:&lt;/strong&gt; Generally used along with pipelines where the artifacts from the &lt;code&gt;build&lt;/code&gt; stage of the pipelines is uploaded into a S3 bucket and the lambda function uses this archive.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Containerized code from AWS ECR:&lt;/strong&gt; Perhaps the most stable one, this gives you the flexibility to use custom runtimes with the help of Docker. The code is built into a docker image and is pushed into ECR which is then used by Lambda.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://hub.docker.com/r/lambda/python/" rel="noopener noreferrer"&gt;base image&lt;/a&gt; that we will be using dictates us to name the entry file as &lt;code&gt;lambda_function.py&lt;/code&gt; and the entry function as &lt;code&gt;handler&lt;/code&gt;. Hence, the names.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# lambda_function.py
&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;statusCode&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Hello &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is pretty simple. It extracts a parameter called &lt;code&gt;name&lt;/code&gt; from the &lt;strong&gt;lambda event&lt;/strong&gt; and returns a JSON response. We will come to the event format at the end.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker up!
&lt;/h2&gt;

&lt;p&gt;That's step one done. Next, we move towards dockerizing our code.&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;Dockerfile&lt;/code&gt; in the same directory with the following contents:&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;# Dockerfile&lt;/span&gt;

&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; public.ecr.aws/lambda/python:3.10&lt;/span&gt;

&lt;span class="c"&gt;# Copy function code&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; lambda_function.py ${LAMBDA_TASK_ROOT}&lt;/span&gt;

&lt;span class="c"&gt;# Set the CMD to your handler (could also be done as a parameter override outside of the Dockerfile)&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; [ "lambda_function.handler" ]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Initialize Terraform
&lt;/h2&gt;

&lt;p&gt;For starters, &lt;a href="https://www.terraform.io/" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt; is an open-sourced tool developed and maintained by HashiCorp that allows us to build our cloud infrastructure from code. This approach is popularly known as &lt;strong&gt;Infrastructure as Code(IaC)&lt;/strong&gt;. If you would like to read more, I suggest you go through their docs (and perhaps some YouTube?).&lt;/p&gt;

&lt;p&gt;Before proceeding forward, make sure you have these prerequisites checked: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli" rel="noopener noreferrer"&gt;terraform installed locally&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-quickstart.html" rel="noopener noreferrer"&gt;AWS CLI set up&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, we are ready to get started with terraform.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First, create a folder named &lt;code&gt;terraform&lt;/code&gt; in the root folder of your project. This isn't a rule, but will allow you to properly organize your code files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, create these files in the folder:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="c1"&gt;# terraform.tf &lt;/span&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;aws&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/aws"&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;"~&amp;gt; 4.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;span class="k"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;region&lt;/span&gt;
  &lt;span class="nx"&gt;access_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;access_key&lt;/span&gt;
  &lt;span class="nx"&gt;secret_key&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;secret_key&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file is used to hold all the configurations required by our project. To simplify, we will be using AWS, hence we mentioned &lt;code&gt;aws&lt;/code&gt; in the &lt;code&gt;required_providers&lt;/code&gt; block. Next, we set up our &lt;code&gt;aws provider&lt;/code&gt;, where in we mention our AWS settings.&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="c1"&gt;# variables.tf&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"region"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your_aws_region"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"access_key"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your_aws_access_id"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"secret_key"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your_aws_secret_key"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file contains the AWS option values. It is usually a good practice to extract all sensitive values from your terraform code into the &lt;code&gt;variables.tf&lt;/code&gt; file and inject the values at runtime to enforce and maintain security of your code.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once done, run the following:
&lt;/li&gt;
&lt;/ul&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;p&gt;This will initialize your project with the dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create ECR
&lt;/h2&gt;

&lt;p&gt;With the previous step done, we are ready to move into the actual stuff. Now, we will be creating our repository &lt;a href="https://aws.amazon.com/ecr/" rel="noopener noreferrer"&gt;(AWS ECR)&lt;/a&gt;. This will allow us to host the custom python image that we will be building shortly. Add this file inside the &lt;code&gt;terraform&lt;/code&gt; folder that you created just a while back.&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="c1"&gt;# ecr.tf&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_ecr_repository"&lt;/span&gt; &lt;span class="s2"&gt;"greetings_repository"&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;"greetings-repository"&lt;/span&gt;
  &lt;span class="nx"&gt;force_delete&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;image_tag_mutability&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"MUTABLE"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the name of our repository is &lt;code&gt;greetings-repository&lt;/code&gt;. You can change it if you want to. &lt;/p&gt;

&lt;p&gt;After that, we will want to spin up our repository:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;p&gt;This command will create your ECR. You can check it from your AWS Console by going into &lt;strong&gt;Search &amp;gt; ECR &amp;gt; Repositories &amp;gt; greetings-repository&lt;/strong&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Deploying our code
&lt;/h2&gt;

&lt;p&gt;Now that we have our repository set up, we are ready to build and push our code. To do this, click on the &lt;strong&gt;View push commands&lt;/strong&gt; button on the top right of the repository page.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuetavptp642o0hkwn7hj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuetavptp642o0hkwn7hj.png" alt="ECR Push commands" width="800" height="371"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go into your root directory of the project and run the commands one by one.&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%2Fc29vz8df1wpm7mgg8b64.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc29vz8df1wpm7mgg8b64.png" alt="docker push" width="800" height="901"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After running the commands, your output should look something similar to this. To confirm you have pushed the image, you can go into your repository in ECR and verify that it's there.&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%2Fr2zzz6o2hzh69jd1qi6v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2zzz6o2hzh69jd1qi6v.png" alt="docker image" width="800" height="104"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Create the Lambda function
&lt;/h2&gt;

&lt;p&gt;Before we deploy our lambda function, we need to create a &lt;strong&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html" rel="noopener noreferrer"&gt;Lambda execution role&lt;/a&gt;&lt;/strong&gt; that our lambda function will use. This allows the function to operate on its own.&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="c1"&gt;# role.tf&lt;/span&gt;

&lt;span class="k"&gt;data&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_policy_document"&lt;/span&gt; &lt;span class="s2"&gt;"assume_role"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;statement&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;effect&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allow"&lt;/span&gt;

    &lt;span class="nx"&gt;principals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Service"&lt;/span&gt;
      &lt;span class="nx"&gt;identifiers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"lambda.amazonaws.com"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;actions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_iam_role"&lt;/span&gt; &lt;span class="s2"&gt;"iam_for_lambda"&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;"iam_for_lambda"&lt;/span&gt;
  &lt;span class="nx"&gt;assume_role_policy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_iam_policy_document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assume_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we created a role called &lt;code&gt;iam_for_lambda&lt;/code&gt; that we will attach to our lambda function.&lt;/p&gt;

&lt;p&gt;Let's buckle up and get that function deployed.&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="c1"&gt;# lambda.tf&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_lambda_function"&lt;/span&gt; &lt;span class="s2"&gt;"greetings_function"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;function_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"greetingsFunction"&lt;/span&gt;
  &lt;span class="nx"&gt;role&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;aws_iam_role&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;iam_for_lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;arn&lt;/span&gt;
  &lt;span class="nx"&gt;package_type&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Image"&lt;/span&gt;
  &lt;span class="nx"&gt;timeout&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
  &lt;span class="nx"&gt;image_uri&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;aws_ecr_repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;greetings_repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository_url&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;:latest"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We did quite a few things in there, namely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a lambda function named &lt;code&gt;greetingsFunction&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Attach the &lt;code&gt;iam_for_lambda&lt;/code&gt; role that we just created&lt;/li&gt;
&lt;li&gt;Specified that our lambda function will be using an image as its source.&lt;/li&gt;
&lt;li&gt;Specified the &lt;code&gt;greetings-repository&lt;/code&gt; url.&lt;/li&gt;
&lt;li&gt;Specified a timeout for the function.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that, we come to the finale. All we need to do now is, 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 apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;After this, we should see our lambda function up and running! You can check it from your &lt;strong&gt;AWS Console&lt;/strong&gt; via &lt;strong&gt;Search &amp;gt; Lambda &amp;gt; greetingsFunction&lt;/strong&gt;&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Testing the lambda function
&lt;/h2&gt;

&lt;p&gt;In case you forgot, our lambda function is extracting a key called &lt;code&gt;name&lt;/code&gt; from the &lt;strong&gt;event&lt;/strong&gt; and returning us a JSON in the form of:&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;"statusCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hello &amp;lt;name&amp;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;To test the function, we will be using the console. Head over to your lambda function and go into the &lt;strong&gt;Test&lt;/strong&gt; tab. Scroll down to find a text editor. Paste the following content in there:&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John Doe"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Once satisfied, click on the &lt;strong&gt;Test&lt;/strong&gt; button. You should see the following content if your execution was successful:&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%2F1j6be57ir9u9pqyjjs60.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1j6be57ir9u9pqyjjs60.png" alt="Lambda test output" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congrats! You have successfully created a serverless, containerized python application! Don't be so harsh on yourself, give yourself a pat on the back! &lt;/p&gt;

&lt;h2&gt;
  
  
  Cleaning up
&lt;/h2&gt;

&lt;p&gt;It's always a good idea to dispose off your resources when you don't need them. Gives us the ability to delete everything with just once command. So, when you feel that your are done playing with, 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;



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

&lt;p&gt;In this blog, we had a deep dive into how you can set up your own container, deploy code to lambda, and create a fully managed AWS environment. In the &lt;a href="https://dev.to/thecodersden/automating-python-deployments-with-github-actions-aws-ecr-and-aws-lambda-1d62"&gt;next part&lt;/a&gt;, we will be looking at setting up a CI/CD pipeline using GitHub Actions that will allow us integrate changes into the lambda function at ease. Till then, happy hacking!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>aws</category>
      <category>cloud</category>
    </item>
    <item>
      <title>SOLID Design Patterns for Spring Boot Developers</title>
      <dc:creator>Rajdip Bhattacharya</dc:creator>
      <pubDate>Tue, 05 Sep 2023 18:47:05 +0000</pubDate>
      <link>https://dev.to/thecodersden/solid-design-patterns-for-spring-boot-developers-2ao7</link>
      <guid>https://dev.to/thecodersden/solid-design-patterns-for-spring-boot-developers-2ao7</guid>
      <description>&lt;p&gt;Hello geeks!&lt;/p&gt;

&lt;p&gt;Welcome to yet another new blog on the tidbits of software development. In my previous blogs, I have touched upon topics such as &lt;strong&gt;Docker&lt;/strong&gt; and &lt;strong&gt;System Design&lt;/strong&gt;. While these topics are no doubt a good to have skills, what is more important is how you write your code. Imagine this scenario where you have a top-class secure pipeline set up for your application, all ready to go into deployment, your manager is super happy with you, and he/she hires more people to assist you in your work. But now, they are introduced with a nightmare since your code isn't clean. No, I'm not saying that you don't know how to code, all I'm saying is, even if you do, you might not be following the world-class &lt;strong&gt;SOLID Principles&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;This is the core motive of this blog, to introduce you to this magical concept of clean coding and make you stand apart in the crowd! So, let's get started without further ado. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A note:&lt;/strong&gt; Most of the references in this article has been taken from the book &lt;strong&gt;Clean Architecture by Robert C. Martin&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is SOLID?
&lt;/h2&gt;

&lt;p&gt;Before we start, make a note of this: &lt;em&gt;The essence of design and architecture is that, it never gave us anything new, but always took from us what we already had.&lt;/em&gt;&lt;br&gt;
Let me simplify this. We live in a society where we are bound by some laws enforced upon us by our government. Violating any such law would impose a penalty upon us. What laws essentially are: barriers. Laws draw the line between the dos and don'ts of our society. This is absolutely necessary because us humans have the capability to do absolute wonders in the planet. To maintain the stability of our society, laws are our only hopes. &lt;br&gt;
Similarly, to maintain the sustainability and developability of code, coding best practices are the only way forward.&lt;/p&gt;

&lt;p&gt;Now, to begin with SOLID, it focuses on arranging data and functions into &lt;strong&gt;classes&lt;/strong&gt;. Note that in this context, class doesn't necessarily mean the class we know from OOP, but rather containers that allow us to containerize our code.&lt;/p&gt;

&lt;p&gt;Goal of SOLID: Creating &lt;em&gt;mid-level&lt;/em&gt; software programs that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Tolerate change&lt;/li&gt;
&lt;li&gt;Are easy to understand&lt;/li&gt;
&lt;li&gt;Can be easily used in many software systems.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The term &lt;strong&gt;mid-level&lt;/strong&gt; signifies that we use SOLID principles while working at module level. To further simplify, we use solid principles while developing, for example, business logic and APIs for our software.&lt;/p&gt;

&lt;p&gt;As you might have already guessed, SOLID is a short form. It consists of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;(S)ingle Responsibility Principle (SRP)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;(O)pen Closed Principle (OCP)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;(L)iskov Substitution Principle (LSP)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;(I)nterface Segregation Principle (ISP)&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;(D)ependency Inversion Principle (DIP)&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;We will look at each of the constituents and analyze them in the following sections.&lt;/p&gt;
&lt;h3&gt;
  
  
  Single Responsibility Principle (SRP)
&lt;/h3&gt;

&lt;p&gt;First, let's see what we do in general. Consider that we have a class named &lt;code&gt;UserService&lt;/code&gt;. It does the following things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Register a user&lt;/li&gt;
&lt;li&gt;Send promotional mails&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Upon registration, a user will receive a mail from us denoting their successful registration, followed by a promotional email. &lt;/p&gt;

&lt;p&gt;While this might look ok, it isn't optimal. We can clearly spot two different functionalities stashed inside the same class. What this will do is, any changes in the &lt;code&gt;registerUser()&lt;/code&gt; function will also recompile the &lt;code&gt;promotionalMail()&lt;/code&gt; function. Plus, if there were two teams working on the two different functions, a merge conflict is inevitable.&lt;/p&gt;

&lt;p&gt;For this very reason, we would like to use two separate classes for this: &lt;code&gt;UserService&lt;/code&gt; and &lt;code&gt;EmailService&lt;/code&gt;. This obeys the following principle: &lt;strong&gt;A module should be responsible to one, and only one, actor&lt;/strong&gt;. Actor, here, means the changing factor. In simple words, the reason for which a class needs to change. The lesser the changing factors for a class, the more stability it gains.&lt;/p&gt;

&lt;p&gt;The main takeaway of this principle is: make sure that you segregate your code based on the factors that changes them.&lt;/p&gt;
&lt;h3&gt;
  
  
  Open Closed Principle (OCP)
&lt;/h3&gt;

&lt;p&gt;While the name might sound intuitive, what it really means is, we want to develop code where in to make changes to our code, we would essentially extend the code rather than updating the existing code.&lt;/p&gt;

&lt;p&gt;Consider the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShoppingCartService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;calculateTotalPrice&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPrice&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;calculateTotalPrice()&lt;/code&gt; calculates the total price of our order based upon the cost of each item. Later, let's say we need to implement a discount mechanism in the code where the discount percentage is variable.&lt;/p&gt;

&lt;p&gt;One way to do this is to directly insert the math in the same function. While we can give ourselves a pat on the back for doing this so simply, we might be digging our own graves in the longer run.&lt;/p&gt;

&lt;p&gt;The optimal way to solve this problem is by creation another service class that will calculate the price for us based upon the discount. We can then segregate our code based on the SRP, which narrates us to separate our code based upon the actors affecting it.&lt;/p&gt;

&lt;p&gt;We are going to do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a new interface named &lt;code&gt;DiscountStratergy&lt;/code&gt; with a single method named &lt;code&gt;applyDiscount&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;DiscountStrategy&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;totalPrice&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create an implementation of this interface named &lt;code&gt;PercentageDiscount&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Component&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PercentageDiscount&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;DiscountStrategy&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;discountRate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;PercentageDiscount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${app.discountRate}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;discountRate&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;discountRate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;discountRate&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;applyDiscount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;totalPrice&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;totalPrice&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;discountRate&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Hook up this interface to do the calculation for us in &lt;code&gt;ShoppingCartService&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShoppingCartService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;DiscountStrategy&lt;/span&gt; &lt;span class="n"&gt;discountStrategy&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ShoppingCartService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;DiscountStrategy&lt;/span&gt; &lt;span class="n"&gt;discountStrategy&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;discountStrategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;discountStrategy&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;calculateTotalPrice&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getPrice&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;discountStrategy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;applyDiscount&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wallah! We now have SRP, OCP and DIP &amp;amp; LSP (coming soon) in place. Now, let's say we choose to move from percentage based discount to loyalty based discount. All we need to do is create another implementation of this interface and comment out the &lt;code&gt;@Component&lt;/code&gt; tag in the current implementation. This approach also makes sure that, for any change in the discount implementation, there aren't any changes in the &lt;code&gt;ShoppingCartService&lt;/code&gt; class.&lt;/p&gt;

&lt;h3&gt;
  
  
  Liskov Substitution Principle (LSP)
&lt;/h3&gt;

&lt;p&gt;We have already covered the usage of LSP unknowingly, but let's look at it properly in this section. &lt;/p&gt;

&lt;p&gt;Let's take an example of the Linux kernel. Don't worry, you don't need to be a Linux geek to understand this example! Linux uses files to represent everything, be it a device or an actual file. This enables the kernel to use &lt;strong&gt;uniformity&lt;/strong&gt; across its code for doing I/O based operations. Namely, there are 4 functions that Linux use to operate on file or I/O devices: &lt;code&gt;open()&lt;/code&gt;, &lt;code&gt;read()&lt;/code&gt;, &lt;code&gt;write()&lt;/code&gt;, &lt;code&gt;close()&lt;/code&gt;. What this means is, any I/O device that is attached to the Linux kernel, must provide their own implementations for these methods. The kernel doesn't bother itself with the details of the implementation. This is what LSP enforces. &lt;br&gt;
LSP promotes the use of interfaces instead of concrete definitions. This allows relaxation of code and lesser dependency.&lt;/p&gt;

&lt;p&gt;Here is an example of the interface promoted by the Linux kernel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.io.IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;FileDevice&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any device that wants to talk to Linux should implement these methods (It is the device drivers that do this and not the device. Kept it simple for ease of understanding).&lt;/p&gt;

&lt;h3&gt;
  
  
  Interface Segregation Principle (ISP)
&lt;/h3&gt;

&lt;p&gt;The name already tells us what it does. ISP tells us to not couple classes together that are not used.&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%2Fmcl260h3uikcs9m8jwn4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmcl260h3uikcs9m8jwn4.png" alt="ISP" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above diagram, we can see that the 3 &lt;code&gt;User&lt;/code&gt; classes directly depend on the &lt;code&gt;OPS&lt;/code&gt; class. Note that &lt;code&gt;User1&lt;/code&gt; uses &lt;code&gt;ops1&lt;/code&gt; method, and the same goes for the rest 3. As you can see, it makes a clutter if stash unrelated code. We solve this issue by using interfaces to segregate the use.&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%2Fbah4g5pv6sm2xlt7ee45.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbah4g5pv6sm2xlt7ee45.png" alt="ISP" width="800" height="594"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This diagram demonstrates how we can change the hierarchy of classes and interfaces so that each module talks to another module that is made for just a specific use case. The green boxes are interfaces.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dependency Inversion Principle (DIP)
&lt;/h3&gt;

&lt;p&gt;The last and perhaps one of the most tricky principles to understand. Let's expand on the previous examples of using interfaces in place of classes. Following this approach helps us to &lt;strong&gt;not depend&lt;/strong&gt; on concretions, but rather, abstractions. If we depend on concrete classes, any change in the class would also mean recompilation of dependent classes. Not only that, this approach makes the code highly dependent and reduces code reusability. This is what DIP puts emphasis on.&lt;/p&gt;

&lt;p&gt;DIP dictates that the most flexible systems are those in which source code dependencies refer only to abstractions, not to concretions. Abstraction, in the context of OOP, can mean interfaces or abstract classes. &lt;/p&gt;

&lt;p&gt;These abstractions are of classes that are highly volatile. A point to note is that, it is perfectly normal to depend directly on classes that do not change often or at all (eg. String in Java).&lt;/p&gt;

&lt;p&gt;The bottom line of this principle is, never ever depend directly on volatile classes.&lt;/p&gt;

&lt;p&gt;Let's take the example of JPA repository.&lt;/p&gt;

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

&lt;p&gt;This is the dependency graph we follow when we are creating a simple CRUD application using springboot. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Service class contains business related logic that uses the JPA Repository to do its work.&lt;/li&gt;
&lt;li&gt;The JPA repository provides an interface of the functions that might be used by its consumers&lt;/li&gt;
&lt;li&gt;The DB provides drivers that implements these methods to connect all the dots &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a simple java code for the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;UserService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;userRepository&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Rest of the code&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that the &lt;code&gt;userRepository&lt;/code&gt; object is injected by SpringBoot at runtime.&lt;/p&gt;

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

&lt;p&gt;With this, we come to the end of this blog. I'm sure if you have read so far, you would have found it really helpful. As developers, it's our responsibility to maintain the software we develop. There is no better way to do this than starting from such a granular level. &lt;/p&gt;

&lt;p&gt;Once again, in case you feel I have missed something, please do let me know.&lt;br&gt;
P.S. You should definitely get &lt;strong&gt;Clean Architecture&lt;/strong&gt; if you liked this article :D!&lt;/p&gt;

</description>
      <category>solidprinciples</category>
      <category>springboot</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Effortless Containerization: Deploying Spring Boot and MySQL with Docker and Docker Compose</title>
      <dc:creator>Rajdip Bhattacharya</dc:creator>
      <pubDate>Thu, 17 Aug 2023 08:03:17 +0000</pubDate>
      <link>https://dev.to/thecodersden/effortless-containerization-deploying-spring-boot-and-mysql-with-docker-and-docker-compose-e8n</link>
      <guid>https://dev.to/thecodersden/effortless-containerization-deploying-spring-boot-and-mysql-with-docker-and-docker-compose-e8n</guid>
      <description>&lt;p&gt;Greetings!&lt;/p&gt;

&lt;p&gt;In the increasing complexity of software development, there is a general shift from manual configuration to automation. Be it development, or deployment, &lt;strong&gt;seamless development and integration&lt;/strong&gt; is the word of the town.&lt;br&gt;
Hence, in this blog, I plan to crack open a critical aspect of DevOps: &lt;strong&gt;Containerization&lt;/strong&gt;. &lt;/p&gt;
&lt;h2&gt;
  
  
  What is Containerization?
&lt;/h2&gt;

&lt;p&gt;Before we dive into that, first let us understand the old school way of doing it. Make a supposition that you are developing an application. You know every inch of this application. Be it the databases or the environments, you have everything set up. Now consider that this application is done with development. You now want to host it someplace. For instance, let's say you decided to use Amazon EC2 for its ease of use. Now let's look at the steps that you would perform to get this application running (at least).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone the application into the EC2 instance&lt;/li&gt;
&lt;li&gt;Install required dependencies (Java, NodeJS, etc.)&lt;/li&gt;
&lt;li&gt;Set up the required environmental variables&lt;/li&gt;
&lt;li&gt;Test the application for bugs or errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While this might look trivial, it becomes a pain when you have to do it over and over again, for all of your applications. There is always a chance that some OS feature would break your application, some dependency won't be installed, some environmental variable might not be configured. It becomes extremely difficult to debug such applications. Here is where &lt;strong&gt;containerization&lt;/strong&gt; comes to our rescue. &lt;/p&gt;

&lt;p&gt;A container includes everything needed for an application to run: the code, runtime, system libraries, and settings. This self-contained unit ensures that the application behaves consistently regardless of the environment it's deployed in. Containers are lightweight, portable, and can be easily moved between different host systems or cloud platforms without significant modifications.&lt;/p&gt;

&lt;p&gt;Key features and benefits of containerization include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Isolation:&lt;/strong&gt; Containers are isolated from each other and from the host system, preventing conflicts between dependencies and runtime environments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistency:&lt;/strong&gt; Containers ensure that an application behaves the same way in every environment, reducing the "it works on my machine" problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Portability:&lt;/strong&gt; Containers can be moved between different systems or cloud platforms with minimal effort, making application deployment and migration easier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Resource Efficiency:&lt;/strong&gt; Containers share the host OS kernel, resulting in lower overhead compared to traditional virtualization.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Scalability:&lt;/strong&gt; Containers can be rapidly scaled up or down to accommodate varying workloads and demands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version Control:&lt;/strong&gt; Container images can be versioned, allowing teams to track changes and roll back to previous versions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DevOps Enablement:&lt;/strong&gt; Containers facilitate DevOps practices by enabling continuous integration, continuous delivery, and automated deployment.&lt;/p&gt;
&lt;h2&gt;
  
  
  Roadmap
&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%2F8pncag13fwhou5sag5ai.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8pncag13fwhou5sag5ai.png" alt="Architecture" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this blog, we would be doing the following things.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a simple &lt;strong&gt;SpringBoot&lt;/strong&gt; application to manage a &lt;code&gt;Person&lt;/code&gt; entity&lt;/li&gt;
&lt;li&gt;Set up &lt;strong&gt;MySQL&lt;/strong&gt; using &lt;strong&gt;Docker&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Create a &lt;strong&gt;Docker Image&lt;/strong&gt; of our application&lt;/li&gt;
&lt;li&gt;Develop a run-and-deploy of the entire infrastructure using &lt;strong&gt;Docker Compose&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To follow along, clone this &lt;a href="https://github.com/rajdip-b/springboot-docker-example" rel="noopener noreferrer"&gt;repository&lt;/a&gt; (also leave a star maybe?)&lt;/p&gt;

&lt;p&gt;So, let's get started!&lt;/p&gt;
&lt;h2&gt;
  
  
  Creating the SpringBoot application
&lt;/h2&gt;

&lt;p&gt;We would start with our SpringBoot application. Head over to &lt;a href="https://start.spring.io/" rel="noopener noreferrer"&gt;Spring Initializr&lt;/a&gt; and create a project using the following settings and dependencies.&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%2F1yii7h18rh5r18ne8t7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1yii7h18rh5r18ne8t7k.png" alt="start.spring.io" width="800" height="504"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To summarize, we are using:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lombok:&lt;/strong&gt; For annotation based POJOs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spring Web:&lt;/strong&gt; For our web application.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spring Data JPA:&lt;/strong&gt; For Hibernate ORM&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MySQL Driver:&lt;/strong&gt; Enables our application to talk to a MySQL database.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spring Boot Actuator:&lt;/strong&gt; For health checks&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once you are satisfied, generate the project, extract it, and open it with your favourite code editor.&lt;/p&gt;

&lt;p&gt;We would be creating the following classes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Person&lt;/code&gt;: Base entity for holding the person.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PersonPayload&lt;/code&gt;: Contains the request body for a Person object.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PersonDTO&lt;/code&gt;: Contains the DTO of the person object when the API returns data.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PersonService&lt;/code&gt;: Contains business interface for managing persons.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PersonServiceImpl&lt;/code&gt;: Contains the implementation of &lt;code&gt;PersonService&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PersonController&lt;/code&gt;: Exposes the endpoints for managing Persons.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PersonRepository&lt;/code&gt;: Enables us to use JPA&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here are a list of endpoints we would be developing in &lt;code&gt;PersonController&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POST /api/person/&lt;/code&gt;: Creates a person &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PUT /api/person/{personId}&lt;/code&gt;: Updates a person with the given data&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /api/person/all?page=&amp;lt;page_index&amp;gt;&amp;amp;size=&amp;lt;page_size&amp;gt;&lt;/code&gt;: Gets the list of all persons on the database. &lt;code&gt;page&lt;/code&gt; and &lt;code&gt;size&lt;/code&gt; helps us to control the index of a page and number of items in a page in pagination. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /api/person/{personId}&lt;/code&gt;: Gets a person by their ID&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE /api/person/{personId}&lt;/code&gt;: Delete a person by their ID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Our final folder structure should look something like this:&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%2F4f82hpg6e7c889idbihq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4f82hpg6e7c889idbihq.png" alt="folder structure" width="340" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since this blog is focussed on getting Docker set up, I would be skipping the code explanation in here. You can always clone the repository and check the code.&lt;/p&gt;

&lt;p&gt;Let's go through the &lt;code&gt;application.properties&lt;/code&gt; file&lt;/p&gt;

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

&lt;p&gt;As you can see, I have injected environmental variables. This would allow us to resolve the values at runtime. It gives us the flexibility to configure our application without actually touching any of the code. Any change that you would like to make to the environments, all you need to do is tweak the values as per your wish in the system's environment.&lt;/p&gt;

&lt;p&gt;I will be using a &lt;code&gt;.env&lt;/code&gt; file to feed the values into the application. Nearly every IDE has the support for doing so. In case you can't figure out how to include a &lt;code&gt;.env&lt;/code&gt; file into your execution environment, you can try setting those values in the environment of your OS. Alternatively, you can let that untouched, since all the keys have a default value assigned to them. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.env.docker&lt;/code&gt;: Used when deployed using docker compose.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0peeb13qtfpbrlpktskm.png" alt=".env.docker" width="297" height="185"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.env.local&lt;/code&gt;: Used when using just docker.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw19idnx3dil9fa9njrl9.png" alt=".env.local" width="227" height="163"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, we have our application ready. Before we are actually able to run it, we need to launch MySQL, which we will do next.&lt;/p&gt;
&lt;h2&gt;
  
  
  Launching MySQL using Docker
&lt;/h2&gt;

&lt;p&gt;To begin with this step, first, make sure that you have docker installed. &lt;a href="https://docs.docker.com/engine/install/" rel="noopener noreferrer"&gt;This&lt;/a&gt; article provides an excellent guide in letting you set up docker. Once it is set up, we are ready to move forward.&lt;/p&gt;

&lt;p&gt;We will be launching a MySQL docker container using this 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 run &lt;span class="nt"&gt;--name&lt;/span&gt; springboot-test &lt;span class="nt"&gt;-p&lt;/span&gt; 3306:3306 &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root &lt;span class="nt"&gt;-d&lt;/span&gt; mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Here is a breakdown into what this command does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It creates us a container from the &lt;a href="https://hub.docker.com/_/mysql" rel="noopener noreferrer"&gt;mysql&lt;/a&gt; docker image&lt;/li&gt;
&lt;li&gt;It assigns a name to that container using &lt;code&gt;--name springboot-test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It exposes the standard mysql port of the docker container to the host's network using &lt;code&gt;--p 3306:3306&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;It sets the &lt;code&gt;root&lt;/code&gt; password of the docker image to &lt;code&gt;root&lt;/code&gt; using &lt;code&gt;-e MYSQL_ROOT_PASSWORD=root&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Lastly, it tells the container to run in detached mode, meaning, it won't be attached to the console where we are writing this command using the &lt;code&gt;-d&lt;/code&gt; flag&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that, we have a brand new mysql container up and running which you can check using:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;p&gt;At this point of time, we are ready to launch our springboot application. Go to the root of the project, and run&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you have maven installed:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvn spring-boot:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If you don't have maven:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mvnw spring-boot:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can verify that the application is running using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8080/actuator/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Now we are ready to finally dockerize the application!&lt;/p&gt;

&lt;h2&gt;
  
  
  Dockerizing the application
&lt;/h2&gt;

&lt;p&gt;We use &lt;strong&gt;Dockerfile&lt;/strong&gt; to containerize any application using docker. &lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;This&lt;/a&gt; article provides all that you need to know to get started. For starters, I'll run down through the docker image that I'm creating.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the project's root&lt;/li&gt;
&lt;li&gt;Create a file named &lt;code&gt;Dockerfile&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Paste the following content in the file
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# The base image on which we would build our image&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; openjdk:18-jdk-alpine&lt;/span&gt;

&lt;span class="c"&gt;# Install curl and maven&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apk &lt;span class="nt"&gt;--no-cache&lt;/span&gt; add curl maven

&lt;span class="c"&gt;# Set environment variables&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; DB_HOST=${DB_HOST}&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; DB_NAME=${DB_NAME}&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; DB_USER=${DB_USER}&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; DB_PASS=${DB_PASS}&lt;/span&gt;

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

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

&lt;span class="c"&gt;# Copy the pom.xml file to the working directory&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; pom.xml .&lt;/span&gt;

&lt;span class="c"&gt;# Resolve the dependencies in the pom.xml file&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;mvn dependency:resolve

&lt;span class="c"&gt;# Copy the source code to the working directory&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; src src&lt;/span&gt;

&lt;span class="c"&gt;# Build the project&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;mvn package &lt;span class="nt"&gt;-DskipTests&lt;/span&gt;

&lt;span class="c"&gt;# Run the application&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["java", "-jar", "target/application.jar"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that I'm still not hard coding the environmental variables. Also, note that, the last line mentions using the command &lt;code&gt;java -jar target/application.jar&lt;/code&gt; to launch the container. For this to happen, we need to first set the build name to &lt;code&gt;application&lt;/code&gt; in the &lt;code&gt;pom.xml&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%2Fgncfdf1gjs687zcftibx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgncfdf1gjs687zcftibx.png" alt="pom.xml" width="800" height="620"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To optimize the docker build process, I have first copied the &lt;code&gt;pom.xml&lt;/code&gt; and then resolved the dependencies before actually copying our soruce code. This is done with the purpose of reducing the number of layers docker rebuild during its build process. Source code is bound to change often. Putting that at the very top would mean all the subsequent layers would be rebuilt.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker networking
&lt;/h2&gt;

&lt;p&gt;Before we get started with running the application, let's first get a few points right about networking in docker. When we run a docker image, the container boots up into a separate docker network that works in isolation to our host network and other docker containers. Hence, container A can't ping container B if they are running on different networks. In our case, we would be running the springboot application and MySQL database. So if we let them run in different networks, our containers won't be able to intercommunicate. &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%2F0hizd3wm5os5kgxp8fzy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0hizd3wm5os5kgxp8fzy.png" alt="Networks" width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two ways to address this issue:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a custom network and attaching our containers to that network.&lt;/li&gt;
&lt;li&gt;Attaching the containers directly to the host network.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Using custom network
&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%2Fmxxs8m0ie8jx6cwuohh8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmxxs8m0ie8jx6cwuohh8.png" alt="Custom Docker network" width="800" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's start by creating a docker network&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;p&gt;Once done, you can verify this using&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;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnkfkluwec9xbkhaockp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsnkfkluwec9xbkhaockp.png" alt="docker network ls" width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, we need to migrate our MySQL container to this network. We do this by:&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 disconnect bridge springboot-test
docker network connect dummy-network springboot-test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can verify that these commands work by inspecting the &lt;code&gt;Containers&lt;/code&gt; section in the output of this 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 inspect dummy network
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using host network
&lt;/h3&gt;

&lt;p&gt;Recall that we used the flag &lt;code&gt;-p 3306:3306&lt;/code&gt; while creating our MySQL container. This flag creates a channel in the network of our MySQL container that allows us to communicate with the container's &lt;code&gt;3306&lt;/code&gt; port via our hosts &lt;code&gt;3306&lt;/code&gt; port.&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%2F0mj6eknxosjyes486p9y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mj6eknxosjyes486p9y.png" alt="host" width="800" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can bypass this by instructing docker to run the container directly on the host's network. This can be done by:&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; springboot-test &lt;span class="nt"&gt;--network&lt;/span&gt; host &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;root &lt;span class="nt"&gt;-d&lt;/span&gt; mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that I replaced the &lt;code&gt;-p&lt;/code&gt; flag with the &lt;code&gt;--network&lt;/code&gt; flag. When we are using the &lt;code&gt;host&lt;/code&gt; network driver, port mappings are neglected by docker.&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%2Fm7gkstapyre64xfsgr5h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7gkstapyre64xfsgr5h.png" alt="Host" width="800" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we know the fixes, let's move towards making the application work.&lt;/p&gt;
&lt;h2&gt;
  
  
  Running the SpringBoot application
&lt;/h2&gt;

&lt;p&gt;We have created our Dockerfile in the previous sections. Now, first, we need to create a docker image out of that file. To do this, go to the root directory of the project 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;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; application:latest &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; temp &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="nt"&gt;--env-file&lt;/span&gt; .env.local &lt;span class="nt"&gt;--network&lt;/span&gt; dummy-network  application:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;--name temp&lt;/code&gt; will set the name of the container as &lt;code&gt;temp&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--rm&lt;/code&gt; will remove the container once it's stopped&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;-p 8080:8080&lt;/code&gt; will map the container's port 8080 to the host's port 8080&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--env-file .env.local&lt;/code&gt; will read the environments from the &lt;code&gt;.env.local&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--network dummy-network&lt;/code&gt; will associate the container to &lt;code&gt;dummy-network&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Lastly, it will launch the docker container&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In case you get any error stating that the DB connection fail, I would like to point you to the &lt;code&gt;.env.local&lt;/code&gt; file. In there, we have a key called &lt;code&gt;DB_HOST&lt;/code&gt; with the value set as &lt;code&gt;springboot-test&lt;/code&gt;. This is the name we used when launching the MySQL docker container. The above command will only work when these conditions are satisfied:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The MySQL container is named &lt;code&gt;springboot-test&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Both the database and the application are in the same network.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Alternatively, if you want to use some other name for the MySQL container, you can should the name in the &lt;code&gt;.env.local&lt;/code&gt; file aswell.&lt;/p&gt;

&lt;p&gt;Now that we have everything up and running, we can verify our network again using the &lt;code&gt;docker network inspect dummy-network&lt;/code&gt; command. &lt;/p&gt;

&lt;h2&gt;
  
  
  Using docker compose
&lt;/h2&gt;

&lt;p&gt;No doubt that most of you have felt that this is too much of configuration. Yes, configuration comes as the cost of making applications reliable and secure. But don't feel demotivated, &lt;strong&gt;docker compose&lt;/strong&gt; is here to rescue!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;docker compose&lt;/strong&gt; is a plugin that reads deployment configurations from a file (typically named &lt;strong&gt;docker-compose.yaml&lt;/strong&gt;) and deploys the entire infrastructure at one click!&lt;/p&gt;

&lt;p&gt;For doing this, let us first create the &lt;strong&gt;docker-compose.yaml&lt;/strong&gt; file in the root directory of the project.&lt;/p&gt;

&lt;p&gt;Then, paste the following into the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3.8'&lt;/span&gt;
&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mysql&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql&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;mysql&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;3306:3306"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;MYSQL_ROOT_PASSWORD=admin1234&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;stack&lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;test&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;CMD"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;mysqladmin"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ping"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-h"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;localhost"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-u"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;root"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;-padmin1234"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
      &lt;span class="na"&gt;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;

  &lt;span class="na"&gt;application&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;dockerfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Dockerfile&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080:8080"&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env.docker&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;stack&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;mysql&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;service_healthy&lt;/span&gt;

&lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stack&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stack&lt;/span&gt;
    &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we have created a network named &lt;code&gt;stack&lt;/code&gt;. We have created two services - &lt;code&gt;application&lt;/code&gt; and &lt;code&gt;mysql&lt;/code&gt;. Both of these services come under the &lt;code&gt;stack&lt;/code&gt; network. In the &lt;code&gt;.env.docker&lt;/code&gt; file, I have set the &lt;code&gt;DB_HOST&lt;/code&gt; to &lt;code&gt;mysql&lt;/code&gt;. This name corresponds to the name of the service. In the docker file, I have added a dependency of &lt;code&gt;mysql&lt;/code&gt; in &lt;code&gt;application&lt;/code&gt; service. This means that the &lt;code&gt;application&lt;/code&gt; service wont start before the &lt;code&gt;mysql&lt;/code&gt; service reaches the &lt;code&gt;service_healthy&lt;/code&gt; state.&lt;/p&gt;

&lt;p&gt;Once done, shut down your previous containers using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker stop springboot-test
docker stop temp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we can fire up the entire infrastructure using:&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will take some time to start up. A few flags that might come in handy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;-d&lt;/code&gt;: Starts in detached mode&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;--build&lt;/code&gt;: Rebuilds the images. Useful when you have made any changes to the source code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When you are done playing around with, you can shut down the entire thing by using:&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 down
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;So that was all about using docker to make your lives easier. I hope you have quiet a few tricks by now. Feel free to leave a comment in case you find something off. &lt;/p&gt;

</description>
      <category>docker</category>
      <category>springboot</category>
      <category>devops</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to develop a scalable, resilient and highly available URL shortener</title>
      <dc:creator>Rajdip Bhattacharya</dc:creator>
      <pubDate>Wed, 09 Aug 2023 20:20:36 +0000</pubDate>
      <link>https://dev.to/thecodersden/how-to-develop-a-scalable-resilient-and-highly-available-url-shortener-2iak</link>
      <guid>https://dev.to/thecodersden/how-to-develop-a-scalable-resilient-and-highly-available-url-shortener-2iak</guid>
      <description>&lt;p&gt;Greetings everyone!&lt;/p&gt;

&lt;p&gt;In the world of software development, we often face an overwhelming amount of information. Every application has its complexities hidden beneath the surface, which can be difficult to understand upfront. When I started my career in development, I was mainly focused on learning programming languages and familiarizing myself with a specific tech stack. Over time, I began to realize the importance of understanding the inner workings of applications. This shift in perspective occurred as I observed the performance of my applications in real-world scenarios and recognized the need to dig deeper into the details. I realized that to date, I was only staring at the tip of the iceberg.&lt;/p&gt;

&lt;p&gt;In this blog, my intent is to present to you my thought process while developing an application. I will try to guide you through the critical aspects of system designs, how to assess your application and finally, how to arrive at a happy showdown. This blog might seem boring/irrelevant to some of the readers because this is purely theory-based. Don't worry, I'll be coming back with the practical version of this blog soon. But if you are willing to understand the details, this would be the one-stop shop for you.&lt;/p&gt;

&lt;p&gt;Okay then, let's begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;p&gt;Here is the list of things we will be doing in this blog:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Get introduced to URL Shorteners&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Decide upon the implementation of the idea&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Take a deep dive into its working&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Figure out the working of the backend&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have come this far, I'm sure you will enjoy this:")&lt;/p&gt;

&lt;h2&gt;
  
  
  What are URL Shorteners?
&lt;/h2&gt;

&lt;p&gt;Have you ever gone to Facebook profile via the web? Did you ever try to share your LinkedIn profile? If yes, then you can certainly feel where this is going. If not, though, let me tell you.&lt;/p&gt;

&lt;p&gt;Here is the link to my GitHub profile: &lt;a href="https://github.com/rajdip-b" rel="noopener noreferrer"&gt;https://github.com/rajdip-b&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This link might look like it's easy to memorize. Well, it is. But, if we ramp up the URL, let's say I show you my LinkedIn URL, you would get the idea.&lt;/p&gt;

&lt;p&gt;Here goes: &lt;a href="https://www.linkedin.com/in/rajdip-bhattacharya-581119232/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/rajdip-bhattacharya-581119232&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it's no joke to remember this URL. This is where URL shorteners come into play. You can think of URL shortness as a mathematical function that takes a string as input and generates another string based on the input. Let's see this in action with an 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%2F82msq4fhfzgbl327d3s2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F82msq4fhfzgbl327d3s2.png" width="768" height="411"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Notice how the big URL gets &lt;strong&gt;shortened&lt;/strong&gt; into a much smaller URL. Now that we know what a URL shortener does, let's see how it does it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting our goals
&lt;/h2&gt;

&lt;p&gt;To make sure that our application stands out in the crowd, first, we need to make sure that we have a clear conception of what we are trying to build. It is in this step that we outline our application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Working overview
&lt;/h3&gt;

&lt;p&gt;First, let's see how our application will function.&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%2F1zs1txcrinfkomaddzpq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1zs1txcrinfkomaddzpq.png" width="800" height="694"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above diagram sketches out the working of our URL Shortener. To reiterate,&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The client sends a request to our server to generate a shortened version of a URL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The server generates this URL, stores it in the DB (which will be covered in the next sections) and returns the shortened URL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The client, later on, requests the shortened URL to our server.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Our server sends a &lt;code&gt;301 Permanently Moved\&lt;/code&gt; response along with the location.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The client gets redirected to the actual server (in here, google.com).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note that in step 4, we are sending &lt;code&gt;301 Permanently Moved\&lt;/code&gt;. In case you need to brush up your knowledge, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status" rel="noopener noreferrer"&gt;here&lt;/a&gt; is a great resource to learn more about HTTP status codes. There are two status codes that we use for redirecting:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;301 Permanently Moved&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;302 Found&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;There is a subtle difference between the two:&lt;/p&gt;

&lt;p&gt;301 states that the resource has moved &lt;strong&gt;permanently&lt;/strong&gt;. Browsers are programmed to cache such responses so that when we make subsequent requests to this URL, we are redirected to the actual location instead of the former location.&lt;/p&gt;

&lt;p&gt;302, on the other hand, merely redirects us. This means the browsers won't cache these responses, and we will always be hitting the URL that sends us the redirected location.&lt;/p&gt;

&lt;p&gt;To summarize, considering that we have requested a server that gets us redirected, for the subsequent requests,&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;301: Browser -&amp;gt; Our Server -&amp;gt; Actual Location&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;302: Browser -&amp;gt; Actual Location&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Where "Actual Location" can be thought of as the long URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  Planning
&lt;/h3&gt;

&lt;p&gt;Next stop, we will make some assumptions on the use case of our application. This can be considered the most crucial point in any application design because implementation and resource allocation highly depend upon the output of this state. So here they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Capacity: 100 million URLs generated per day&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Uptime: Should be running for 1 year at least.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data: URLs containing alphanumeric characters.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Data modification: Just writes are allowed.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From the given design, we can infer that our application would have more reads than the number of writes. Let's say, reads:writes would be 10:1&lt;/p&gt;

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

&lt;p&gt;Writes per second: 100 mil / (24 * &lt;em&gt;60 *&lt;/em&gt; 60) = 1160&lt;/p&gt;

&lt;p&gt;Read operations: 10*1160 (since 10:1 is read:write) = 11600&lt;/p&gt;

&lt;p&gt;Number of records that needs to be stored: 100 mil * 365 = 36.5 billion records&lt;/p&gt;

&lt;p&gt;Considering an average of 100 bytes per record, the storage required for 1 year: ~= 33 TB&lt;/p&gt;

&lt;p&gt;From the above calculations, we can infer the following requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A database that can scale at large. Hence, scalability is ensured.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The database should have great indexing support for decreasing delay.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Caching the most frequently accessed URLs would decrease delay.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating multiple servers and load balancing would make the application resilient.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Designing the heart of the URL Shortener
&lt;/h2&gt;

&lt;p&gt;Now that we have established the requirements, we are ready to move forward. The next stop is deciding the function that will actually generate the shortened URL. Note that we will have to store 36.5 billion records, which means we will have 36.5 billion unique shortened URLs. Therefore, we need to find out the minimum size of the shortened URL. We know that we will be operating on alphanumeric input, which has a size of 62. Since our shortened URL would also contain alphanumeric, we will have 62 different characters in 1 position and 62^n different combinations, where n is the size of the URL. So if our URL is of size 4, then n=4. So the number of combinations becomes 62^4 = 1,47,76,336 ~= 14 million. Therefore, we need to find an n such that 62^n &amp;gt;= 36.5 billion. I'll spare you the calculation. The lowest n that satisfies this equation is 7. Therefore, our shortened URL would be size 7.&lt;/p&gt;

&lt;p&gt;Next, I'll be discussing 2 approaches to solving this problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://www.geeksforgeeks.org/hash-functions-and-list-types-of-hash-functions/" rel="noopener noreferrer"&gt;Hash Function&lt;/a&gt;
&lt;/h3&gt;

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

&lt;p&gt;A hash function can be defined as a complex mathematical function that takes in an input (hashValue) and generates a hashOutput based on the input. SHA256, SHA512, MD5 are some renowned hashing algorithms to name a few.&lt;/p&gt;

&lt;p&gt;The above diagram illustrates &lt;a href="https://en.wikipedia.org/wiki/SHA-2" rel="noopener noreferrer"&gt;SHA256&lt;/a&gt; converting a string into absolute gibberish. Behind the scenes, the hash function uses mathematical functions to map characters to certain calculated values. The output is very long and according to our requirements, we only need 7 characters. We can truncate the output to be 7 characters long, but then it will mean that we might have duplicate elements in our records. To mitigate this, we will use hash + &lt;a href="https://quescol.com/data-structure/collision-in-hashing-and-collision-resolution-technique" rel="noopener noreferrer"&gt;collision detection&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%2Fpcj41mdmapuya2n8kkwx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpcj41mdmapuya2n8kkwx.png" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diagram illustrates how we will be generating our shortened URL. Note that the output &lt;code&gt;shortUrl\&lt;/code&gt; has 7 characters, and this is done by truncating the rest of the output.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://en.wikipedia.org/wiki/Base62" rel="noopener noreferrer"&gt;Base 62 conversion&lt;/a&gt;
&lt;/h3&gt;

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

&lt;p&gt;Base 62 is a commonly used &lt;strong&gt;encoding&lt;/strong&gt; technique that uses 62 characters-long set. This set consists of all characters in the alphanumeric family. For generating a Base62 short URL, we follow the following steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Character Set Selection:&lt;/strong&gt; We map all the alphanumeric characters to decimal numbers, as represented in the above table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Converting to Decimal:&lt;/strong&gt; The entire long URL is scanned through, and each character is replaced by its decimal representation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Conversion to Base62:&lt;/strong&gt; The output of the previous step is continuously divided by 62 and the remainder obtained at each step is mapped back from the table. For example, at any step, we got a remainder of 20, then would write K, because the table maps alphanumeric K to decimal 20.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Padding and truncating:&lt;/strong&gt; The output obtained from the above stage might not be always 7 characters long. If the output length is lesser than 7, pad it with 0s else, truncate it if it's greater than 7.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The steps involved are much similar to that of hashing, just that we don't use any hash function but encoding functions.&lt;/p&gt;

&lt;p&gt;With our URL Shortener function defined, we are ready to move forward to the "web" aspects of our application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deciding the backend
&lt;/h2&gt;

&lt;p&gt;Nearly any application is always backend-heavy. In our case, we need to figure out how we want to put the pieces together to make our URL shortener functional.&lt;/p&gt;

&lt;p&gt;Firstly, we want to establish how our DB operates.&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%2Ftw1rx5s6gayix5jy6iyc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftw1rx5s6gayix5jy6iyc.png" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The records in the database would be of the format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auto&lt;/span&gt; &lt;span class="k"&gt;generated&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;shortUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;longUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, comes the high-level architecture of the overall application.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The client requests the server requesting for the long URL for a short URL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The load balancer receives the request and sends forwards it to one of its healthy servers in the target group.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The server first checks the cache. If it is present, it returns the short URL to the client (5).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If it is not present in the cache, the server queries the DB and fetches it. It stores it in the cache and sends it over to the client(5).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This is a 301 Moved Permanently response, that will ultimately make the browser go to the destined location.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;With that, we've concluded this blog. While it delved into theory, it has provided you with a clear understanding of the inner workings of such applications. What's even better is that you're now equipped to put this knowledge into action and apply the thought process to your projects!&lt;/p&gt;

&lt;p&gt;This blog might not be 100% accurate, so, if you see any window for improvements, you're always welcome!&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>tutorial</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Logical Volume Manager: A Beginner's Guide</title>
      <dc:creator>Rajdip Bhattacharya</dc:creator>
      <pubDate>Mon, 07 Aug 2023 10:14:24 +0000</pubDate>
      <link>https://dev.to/thecodersden/logical-volume-manager-a-beginners-guide-49l3</link>
      <guid>https://dev.to/thecodersden/logical-volume-manager-a-beginners-guide-49l3</guid>
      <description>&lt;p&gt;Hey there, everyone!&lt;/p&gt;

&lt;p&gt;I'm super excited to kick off my very first blog! Today, I want to take you on a journey into the awesome realm of Linux Volume Manager (LVM). Don't worry if you're new to this – I'll start from the very basics and walk you through the entire process of creating and managing your own LVM. And guess what? I promise to keep things fun and easy to understand. So, buckle up, and let's embark on this exciting adventure together! Ready? Let's go! 😊&lt;/p&gt;

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

&lt;p&gt;Before we get started, we would need a few tools at our disposal.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🖥️ A Linux machine with root access (VMs would suffice as well)&lt;/li&gt;
&lt;li&gt;📀 A USB drive (preferably 8 GB and above)&lt;/li&gt;
&lt;li&gt;☕ A cup of coffee (can't miss this one!)&lt;/li&gt;
&lt;li&gt;🐧 Some understanding of Linux is always a plus!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Physical Volumes
&lt;/h2&gt;

&lt;p&gt;As the name suggests, we would be dealing with volumes, to be precise, storage. For us to understand LVM better, we would need a firm understanding of how Linux stores data without LVM in the first hand. Let's start by inspecting how a regular hard disk drive or solid state drive (&lt;strong&gt;block devices&lt;/strong&gt;)&lt;/p&gt;

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

&lt;p&gt;The diagram above illustrates how a physical device or block device is partitioned and used by our Linux machines. At the top, there's a &lt;strong&gt;partition table&lt;/strong&gt;, which is just &lt;strong&gt;a reflection of how the device is internally partitioned&lt;/strong&gt;. The next three blocks represent the &lt;strong&gt;partitions&lt;/strong&gt;, named in ascending order for easy understanding. Each partition has a &lt;strong&gt;filesystem&lt;/strong&gt;, a special database that stores the file and folder hierarchy details**. Common examples of filesystems are ext4, NTFS, and FAT. Don't worry; we'll dive into filesystems and partitions in the hands-on section later!&lt;/p&gt;

&lt;p&gt;Linux organizes its file system like a tree structure, with the &lt;code&gt;/&lt;/code&gt; directory as the root. All files and folders reside next to it. In our setup, partition 1 is &lt;strong&gt;mounted&lt;/strong&gt; to &lt;code&gt;/&lt;/code&gt;, partition 2 to /tmp, and partition 3 to &lt;code&gt;/home&lt;/code&gt;. When we store data in any directory, it goes into the corresponding partition.&lt;/p&gt;

&lt;p&gt;However, using physical volumes directly comes with some problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the &lt;code&gt;/&lt;/code&gt; directory runs out of space, extending it can be tricky.&lt;/li&gt;
&lt;li&gt;Incorporating a new storage device with your &lt;code&gt;/home&lt;/code&gt; directory requires adjustments.&lt;/li&gt;
&lt;li&gt;Replacing a slow storage device is a cumbersome task.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's where LVM comes to the rescue! It simplifies these processes and provides more flexibility. Let's explore LVM further in the upcoming sections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Okay, so, what actually is LVM?
&lt;/h2&gt;

&lt;p&gt;LVM, which stands for &lt;strong&gt;Logical Volume Manager&lt;/strong&gt;, becomes more understandable now that we have a basic understanding of storage devices and their utilization. LVM acts as an intermediate layer, allowing us to manage our storage seamlessly. It adds flexibility and simplicity to the storage management process, making it easier to handle partitions and filesystems. With LVM, we can efficiently allocate, resize, and move logical volumes, providing us with a more dynamic and adaptable storage solution&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%2Fm01j7w8dq18idhuycyce.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm01j7w8dq18idhuycyce.png" alt="LVM" width="766" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the diagram shows, LVM utilizes a Volume Group (VG) to abstract the Physical Volumes (PVs), which represent the raw storage devices like HDDs and SSDs. The VG is typically created with one or more PVs, and from this pool of storage, Logical Volumes (LVs) are carved out. The beauty of LVM lies in its ability to freely adjust the size of these LVs, thanks to its dynamic data management on the physical volumes. In a sense, the VGs act as a versatile and flexible &lt;strong&gt;data pool&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You may have noticed the block labeled /boot. This partition holds the data related to our system's boot process. At boot time, Linux cannot read data from the LVs directly, so a separate raw /boot partition is necessary.&lt;/p&gt;

&lt;p&gt;It's important to note that not all LVM-based systems offer the same level of flexibility. Some systems may restrict us to just one PV and two LVs (for swap and root), limiting the benefits of LVM's true potential. However, when we have the liberty to leverage LVM's full capabilities, it opens up a world of possibilities for efficient and customizable storage management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operations supported in LVM
&lt;/h2&gt;

&lt;p&gt;LVM supports the following operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Add&lt;/strong&gt; more physical volumes (PVs) to volume group (VG)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remove&lt;/strong&gt; PVs as long as there is enough space to accomodate the existing logical volumes (LVs) into the VG.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resize&lt;/strong&gt; LVs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Enough chit-chat, let's get to the real stuff!
&lt;/h2&gt;

&lt;p&gt;Now that we have the theory out of the way, let's get our hands dirty by actually creating a LVM on our systems. We would be doing the following stuff:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Partition our USB drive to have 2 partitions (2 GB + ~6 GB).&lt;/li&gt;
&lt;li&gt;Create a VG from 1 partition and, later on, extending it with the other partition.&lt;/li&gt;
&lt;li&gt;Displaying the details of the VGs.&lt;/li&gt;
&lt;li&gt;Create 2 LVs (1 GB + 2 GB)&lt;/li&gt;
&lt;li&gt;Display the LVs&lt;/li&gt;
&lt;li&gt;Create file systems on the LVs and mount them to our systems&lt;/li&gt;
&lt;li&gt;Extend the 1 GB LV by 2 GB and re-adjusting the file system.&lt;/li&gt;
&lt;li&gt;Removing the VGs and LVs.&lt;/li&gt;
&lt;li&gt;Fixing out pendrives.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Just to make a note of it, some commands that I will be using might not be already present on your distro. In that case, please be sure to read the error messages and install the required binaries.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So turn on your Linux machine, get a sip of your coffee and get started!&lt;/p&gt;

&lt;h3&gt;
  
  
  Partitioning our USB drive
&lt;/h3&gt;

&lt;p&gt;Just so we don't actually blow up our computers trying to do anything fancy, we would do this experiment using a USB drive. I am using an 8 GB HP stick for this. Just make sure to back up any data that is present in the USB drive and then we are good to go.&lt;/p&gt;

&lt;p&gt;The first step is to partition the USB drive.&lt;/p&gt;

&lt;p&gt;Make sure you are in a root shell. If not, use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, let's grab some details about our block devices.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;p&gt;I have truncated the irrelevant details from the output. You can notice that there are 2 devices called &lt;code&gt;sda&lt;/code&gt; and &lt;code&gt;sdb&lt;/code&gt;. And under the &lt;code&gt;TYPE&lt;/code&gt; column, you can also see that these are...disk. But wait, where did these names come from? Let's find out how.&lt;/p&gt;

&lt;p&gt;Block devices use &lt;strong&gt;SCSI (Small Computer System Interface)&lt;/strong&gt; to talk to processes on one side and hardware on the other side. Hence, block devices have device names (since everything on Linux is a file, so device files) starting with sd*, where s = SCSI and d = device. During boot time, the kernel detects block devices one by one and name them in the form &lt;code&gt;sd[a-z]&lt;/code&gt;. So in my case, my vmware disk got detected first and hence, it was named &lt;code&gt;sda&lt;/code&gt;. Next, after boot, I attached my USB stick and the kernel named it &lt;code&gt;sdb&lt;/code&gt;. As I mentioned earlier, all disks have one or more partitions. In the above output, &lt;code&gt;sdb1&lt;/code&gt;, &lt;code&gt;sda1&lt;/code&gt;, etc. are names of partitions.&lt;br&gt;
Note that USB devices use SCSI as a layer of abstraction over its USB interface. That's the reason why it gets detected as block devices.&lt;/p&gt;

&lt;p&gt;We can fetch more details about our block devices using this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fdisk &lt;span class="nt"&gt;-l&lt;/span&gt; /dev/sdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Now, we would partition the device into 2 halves. For that, we first need to unmount our device:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;umount /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To verify that the device is unmounted, you can run 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;mount | &lt;span class="nb"&gt;grep &lt;/span&gt;sdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output of this command should be empty.&lt;/p&gt;

&lt;p&gt;Next, we will use &lt;code&gt;fdisk&lt;/code&gt; to manage the partitions. Here is what we will do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Delete the existing partition&lt;/li&gt;
&lt;li&gt;Create a new partition of 2 GB&lt;/li&gt;
&lt;li&gt;Create another partition of the remaining size&lt;/li&gt;
&lt;li&gt;Save the changes (fdisk doesn't save the changes on the go)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To start, type the following command and refer to the output for more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fdisk /dev/sdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;strong&gt;Commands used:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;d:&lt;/strong&gt; Delete existing partition&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;n:&lt;/strong&gt; Create new partition&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;p:&lt;/strong&gt; List all partitions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once done, you can verify the newly created partitions using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lsblk /dev/sdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Creating a volume group
&lt;/h3&gt;

&lt;p&gt;Now that we are done with partitioning our USB drive, it's time to create our brand-new VG.&lt;/p&gt;

&lt;p&gt;Before running any of the commands below, make sure you have installed the &lt;code&gt;lvm2&lt;/code&gt; package:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Next, we create our VG:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vgcreate myvg /dev/sdb1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Listing VGs
&lt;/h3&gt;

&lt;p&gt;We can list the existing VGs in our system using 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;vgs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OR&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;The first command lists all the VGs in a compact manner, while the second command gives us a detailed view.&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%2Fu8qr8iknueg1eoqmqbws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu8qr8iknueg1eoqmqbws.png" alt="vgs" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VG:&lt;/strong&gt; Name of the volume group&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;#PV:&lt;/strong&gt; Number of physical volumes associated with the VG&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;#LV:&lt;/strong&gt; Number of logical volumes inside the VG&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;#SN:&lt;/strong&gt; Number of snapshots of the VG&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VSize:&lt;/strong&gt; VG Size&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VFree:&lt;/strong&gt; Amount of unallocated space on the VG&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;If you have come this far, give yourself a pat on the back and have a sip from that cup of yours!&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding PVs to VG
&lt;/h3&gt;

&lt;p&gt;We want to add our &lt;code&gt;/dev/sdb2&lt;/code&gt; partition to &lt;code&gt;myvg&lt;/code&gt; aswell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vgextend myvg /dev/sdb2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Notice that if we list out our VG now, we would see that its size has changed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vgs myvg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Creating logical volumes out of &lt;code&gt;myvg&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Our VG has been created. Now, we want to create volumes out of it so that we can start using it.&lt;/p&gt;

&lt;p&gt;We will create a 1 GB volume named &lt;code&gt;mylv1&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;lvcreate &lt;span class="nt"&gt;--size&lt;/span&gt; 1g &lt;span class="nt"&gt;--name&lt;/span&gt; mylv1 myvg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And similarly, we will create another LV of size 2g, named &lt;code&gt;mylv2&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;lvcreate &lt;span class="nt"&gt;--size&lt;/span&gt; 2g &lt;span class="nt"&gt;--name&lt;/span&gt; mylv2 myvg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;If we try to see our VG config now, we will see that the &lt;code&gt;VFree&lt;/code&gt; has reduced now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vgs myvg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Listing LVs
&lt;/h3&gt;

&lt;p&gt;We have 2 LVs created and we would like to see how they look like. The command is similar to that of listing VGs:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;h3&gt;
  
  
  Using our LVs
&lt;/h3&gt;

&lt;p&gt;Okay, so now we have 2 LVs created and now we want to use them. Lets see how we can do that.&lt;/p&gt;

&lt;p&gt;Previously, we saw that the kernel detects devices during boot time and assigns them the names accordingly. This means that our LV "device" names will also vary with each boot. Initially, the kernel creates the logical volumes under &lt;code&gt;/dev&lt;/code&gt; folder with a naming convention &lt;code&gt;dm-*&lt;/code&gt;, where * is an integer. To make sure we can map our LVs by the name we know them to these &lt;code&gt;dm-*&lt;/code&gt; device files, the kernel also creates symbolic links under the &lt;code&gt;/dev/mapper&lt;/code&gt; and &lt;code&gt;/dev/&amp;lt;vgname&amp;gt;&lt;/code&gt; directories.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contents of &lt;code&gt;/dev/mapper&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Contents of &lt;code&gt;/dev/myvg&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Now that we know what device files to use, let's actually create a file system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mkfs &lt;span class="nt"&gt;-t&lt;/span&gt; ext4 /dev/myvg/mylv1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This command creates an &lt;code&gt;ext4&lt;/code&gt; file system on our &lt;code&gt;mylv1&lt;/code&gt; LV. Now its time to mount it to a location.&lt;/p&gt;

&lt;p&gt;First, I'll create a mountpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; /mnt/mylv1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, I'll mount the LV:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mount /dev/myvg/mylv1 /mnt/mylv1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, I'll verify my mount point using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mount | &lt;span class="nb"&gt;grep &lt;/span&gt;mylv1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;As we can see, everything is set up exactly how we wanted it to be. If I were you, I would have tried to do the following things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do the same for &lt;code&gt;mylv2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Take a break&lt;/li&gt;
&lt;li&gt;Take another sip from my cup&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Using our newly created LV
&lt;/h3&gt;

&lt;p&gt;First, we need to move to our mount point:&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;cd&lt;/span&gt; /mnt/mylv1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we can inspect the size using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;df&lt;/span&gt; &lt;span class="nt"&gt;-h&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly, we can start creating files. I'll leave this to you. But remember, this space is created by the root so no other user would have write access to it. If you want to give the users write access, then run &lt;code&gt;chmod a+rw .&lt;/code&gt; while you are still in that directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resizing the LV
&lt;/h3&gt;

&lt;p&gt;Remember our &lt;code&gt;mylv1&lt;/code&gt; LV just has 1 GB of storage. We now would like to ramp it up to have 3 GB. Lets do that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lvresize &lt;span class="nt"&gt;-L&lt;/span&gt; +2g myvg/mylv1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;This command adds 2 GB of storage to &lt;code&gt;mylv1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But now if we run &lt;code&gt;df -h /mnt/mylv1&lt;/code&gt;, we notice that the size didn't change. Did we make a mistake? No.&lt;br&gt;
Remember that file systems are the managers of every partition? When we created a partition on &lt;code&gt;mylv1&lt;/code&gt;, it's size was 1 GB. Just increasing the volume size doesn't mean that the filesystem would also be synchronized. So, to do that, we need to run 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;fsadm &lt;span class="nt"&gt;-v&lt;/span&gt; resize /dev/myvg/mylv1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Try running &lt;code&gt;df -h /mnt/mylv1&lt;/code&gt; and you will see that the size has increased.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lvresize&lt;/code&gt; provides us with a &lt;code&gt;-r&lt;/code&gt; flag to automatically do the file system resizing for us. So, the command would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lvresize &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="nt"&gt;-L&lt;/span&gt; +2g myvg/mylv1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Removing LVs and VGs
&lt;/h3&gt;

&lt;p&gt;We have almost reached the end of this long blog now. Before we finish, we would like to perfrom a clean-up.&lt;/p&gt;

&lt;p&gt;First step is to unmount the LVs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;umount /dev/mylv1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure you unmount &lt;code&gt;mylv2&lt;/code&gt; if you did mount it earlier.&lt;/p&gt;

&lt;p&gt;Second step is to delete the LVs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;lvremove myvg/mylv1
lvremove myvg/mylv2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And at last, we will be deleting the VG:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vgremove myvg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;I made the mistake of removing a LV before unmounting it, so I got an error.&lt;br&gt;
After this command, you can issue &lt;code&gt;vgs&lt;/code&gt; and &lt;code&gt;lvs&lt;/code&gt; to confirm that everything is deleted.&lt;/p&gt;
&lt;h3&gt;
  
  
  Fixing our USB drive
&lt;/h3&gt;

&lt;p&gt;Since I have already talked about partitioning and file systems, I won't be reiterating over them.&lt;br&gt;
To get started, do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fdisk /dev/sdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Wallah! Your USB would now be fixed. With this, we come to the end of this blog. &lt;/p&gt;

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

&lt;p&gt;In conclusion, Linux Volume Manager (LVM) serves as a crucial tool for flexible storage management. It abstracts raw storage devices (PVs) into logical volumes (LVs) within volume groups (VGs). LVM empowers us to resize LVs dynamically and handle storage with ease, providing a versatile storage solution. While some systems may limit its potential, utilizing LVM opens up possibilities for optimizing storage usage and system performance. Embrace the power of LVM in your Linux journey for seamless and efficient storage management. Happy computing!&lt;/p&gt;

</description>
      <category>linux</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
