<?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: Adnan Latif</title>
    <description>The latest articles on DEV Community by Adnan Latif (@adnanlatif).</description>
    <link>https://dev.to/adnanlatif</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%2F1207995%2Ff1dd6c58-83a2-4e10-8018-2c047fe03bae.jpeg</url>
      <title>DEV Community: Adnan Latif</title>
      <link>https://dev.to/adnanlatif</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adnanlatif"/>
    <language>en</language>
    <item>
      <title>We Built an Autonomous Content Pipeline So Engineers Could Keep Engineering</title>
      <dc:creator>Adnan Latif</dc:creator>
      <pubDate>Sun, 07 Jun 2026 21:34:41 +0000</pubDate>
      <link>https://dev.to/adnanlatif/we-built-an-autonomous-content-pipeline-so-engineers-could-keep-engineering-34oe</link>
      <guid>https://dev.to/adnanlatif/we-built-an-autonomous-content-pipeline-so-engineers-could-keep-engineering-34oe</guid>
      <description>&lt;p&gt;Most conversations about content automation focus on generating articles.&lt;/p&gt;

&lt;p&gt;That’s usually the easy part.&lt;/p&gt;

&lt;p&gt;The real challenge is building a system that can consistently generate useful content, review its own work, create supporting assets, distribute content across multiple platforms, and do it all without someone manually managing the process every day.&lt;/p&gt;

&lt;p&gt;A few months ago, we started with a simple question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if content publishing worked more like a CI/CD pipeline than a traditional writing workflow?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That question led to one of the most interesting automation projects we’ve built.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Like many engineering teams, we had no shortage of ideas worth sharing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;DevOps lessons learned&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloud cost optimization strategies&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI experiments&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Platform engineering practices&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;CI/CD improvements&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Architecture decisions&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ideas weren’t the problem.&lt;/p&gt;

&lt;p&gt;Consistency was.&lt;/p&gt;

&lt;p&gt;Writing an article takes time. Publishing it takes even more. Then come the cover images, formatting, SEO tags, distribution, and tracking.&lt;/p&gt;

&lt;p&gt;Before long, the entire process started looking a lot like a manual deployment pipeline.&lt;/p&gt;

&lt;p&gt;Every step depended on someone remembering to do it.&lt;/p&gt;

&lt;p&gt;And like many tasks that are important but not urgent, content creation kept getting pushed down the priority list.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treating Content as an Engineering Problem
&lt;/h2&gt;

&lt;p&gt;Instead of asking how we could write faster, we asked a different question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How would engineers solve this problem?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Modern delivery pipelines already know how to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Run on schedules&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Execute workflows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validate outputs&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reject low-quality results&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Deploy to multiple destinations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Record outcomes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The more we looked at it, the more content publishing resembled software delivery.&lt;/p&gt;

&lt;p&gt;So we decided to build our publishing process using the same principles we use to ship software.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;At the center of the system is n8n.&lt;/p&gt;

&lt;p&gt;Every twelve hours, a scheduled workflow kicks off automatically.&lt;/p&gt;

&lt;p&gt;The workflow reads a niche from a spreadsheet. Topics include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;DevOps&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Cloud Engineering&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI Agents&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kubernetes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Platform Engineering&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Developer Productivity&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But instead of generating an article immediately, the system first generates a topic.&lt;/p&gt;

&lt;p&gt;That decision turned out to be one of the biggest improvements we made.&lt;/p&gt;

&lt;p&gt;The workflow follows a simple sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Select niche&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate topic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate article&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Review article&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate cover image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publish draft&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Store publication URLs&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;At a high level, the workflow looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Cron
 ↓
Select Niche
 ↓
Generate Topic
 ↓
Generate Article
 ↓
Quality Review
 ↓
Generate Image
 ↓
Upload Assets
 ↓
Publish Drafts
 ↓
Store Results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once configured, the entire process runs without manual intervention.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Topic Generation Changed Everything
&lt;/h2&gt;

&lt;p&gt;One of the earliest lessons we learned was that article quality is often determined before the first paragraph is written.&lt;/p&gt;

&lt;p&gt;Initially, we provided a niche and asked the model to generate an article.&lt;/p&gt;

&lt;p&gt;The results were technically correct, but forgettable.&lt;/p&gt;

&lt;p&gt;Generic inputs produced generic outputs.&lt;/p&gt;

&lt;p&gt;Once we separated topic generation from article generation, the quality improved dramatically.&lt;/p&gt;

&lt;p&gt;Instead of telling the model:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“Write about Kubernetes.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The system would first generate something more specific:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;“How Small Kubernetes Clusters Become Operationally Expensive Faster Than Teams Expect.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Suddenly the article had a clear angle.&lt;/p&gt;

&lt;p&gt;The model wasn’t just writing about a technology. It was exploring a specific idea.&lt;/p&gt;

&lt;p&gt;That small change made a surprisingly big difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding Quality Gates
&lt;/h2&gt;

&lt;p&gt;This became the most important part of the project.&lt;/p&gt;

&lt;p&gt;Generating content is easy.&lt;/p&gt;

&lt;p&gt;Filtering content is hard.&lt;/p&gt;

&lt;p&gt;Without validation, an autonomous publishing system eventually becomes an autonomous spam generator.&lt;/p&gt;

&lt;p&gt;To prevent that, we introduced a review stage powered by a separate language model.&lt;/p&gt;

&lt;p&gt;Each article is evaluated for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Originality&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Readability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Technical depth&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Practical value&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;SEO potential&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reviewer assigns a quality score.&lt;/p&gt;

&lt;p&gt;If the score falls below a predefined threshold, the article is rejected and the workflow starts over with a new topic.&lt;/p&gt;

&lt;p&gt;This simple quality gate improved output more than any prompt engineering tweak we tried.&lt;/p&gt;

&lt;p&gt;It also mirrors how engineering teams handle deployments.&lt;/p&gt;

&lt;p&gt;Not every build reaches production.&lt;/p&gt;

&lt;p&gt;Not every article should reach publication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating Visual Assets
&lt;/h2&gt;

&lt;p&gt;Another unexpected bottleneck was image creation.&lt;/p&gt;

&lt;p&gt;Every article needs a cover image, and creating those manually quickly became a repetitive task.&lt;/p&gt;

&lt;p&gt;We integrated image generation directly into the workflow.&lt;/p&gt;

&lt;p&gt;The article topic is transformed into a structured image prompt focused on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Technical concepts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Architecture themes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Infrastructure visuals&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publication-quality graphics&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The generated image is automatically attached to the article and becomes part of the publishing package.&lt;/p&gt;

&lt;p&gt;No additional work required.&lt;/p&gt;

&lt;h2&gt;
  
  
  Publishing Across Multiple Platforms
&lt;/h2&gt;

&lt;p&gt;Publishing targets fell into two categories.&lt;/p&gt;

&lt;p&gt;The first includes platforms with stable APIs, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;WordPress&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dev.to&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Hashnode&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ghost&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are ideal for automation. The workflow can create drafts, publish content, and store resulting URLs with minimal effort.&lt;/p&gt;

&lt;p&gt;The second category includes platforms that are less automation-friendly.&lt;/p&gt;

&lt;p&gt;Medium is a good example.&lt;/p&gt;

&lt;p&gt;While automation is possible, the platform is designed primarily for human interaction rather than programmatic publishing. That introduces additional complexity and maintenance overhead.&lt;/p&gt;

&lt;p&gt;For now, Medium remains part of the workflow as a draft destination while the automation continues to evolve.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Surprised Us
&lt;/h2&gt;

&lt;p&gt;The biggest surprise was that article generation wasn’t the hard part.&lt;/p&gt;

&lt;p&gt;Quality control was.&lt;/p&gt;

&lt;p&gt;Most discussions around AI content focus on generation.&lt;/p&gt;

&lt;p&gt;In practice, generation became only a small piece of the system.&lt;/p&gt;

&lt;p&gt;The more interesting engineering challenges involved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Topic selection&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Duplicate detection&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Quality scoring&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Asset management&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Publishing workflows&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi-platform distribution&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Over time, the project evolved from a simple article generator into a complete content platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  What We Learned
&lt;/h2&gt;

&lt;p&gt;A few lessons stood out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automation amplifies existing processes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the process is broken, automation simply helps you produce bad results faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quality gates matter more than generation quality.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A decent generator combined with strong validation will often outperform an excellent generator with no review process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Publishing content is surprisingly similar to shipping software.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The same principles apply:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Validation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Repeatability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reliability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Observability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Feedback loops&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And perhaps most importantly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Autonomous systems still benefit from human oversight.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The workflow handles repetitive tasks.&lt;/p&gt;

&lt;p&gt;Humans provide direction, judgment, and context.&lt;/p&gt;

&lt;p&gt;That’s where the real value comes from.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;The original goal was straightforward:&lt;/p&gt;

&lt;p&gt;Publish consistently without turning engineers into full-time writers.&lt;/p&gt;

&lt;p&gt;What emerged was something much closer to a software delivery pipeline.&lt;/p&gt;

&lt;p&gt;Topics are generated.&lt;/p&gt;

&lt;p&gt;Articles are reviewed.&lt;/p&gt;

&lt;p&gt;Images are created.&lt;/p&gt;

&lt;p&gt;Drafts are published.&lt;/p&gt;

&lt;p&gt;Results are tracked.&lt;/p&gt;

&lt;p&gt;The system doesn’t replace expertise, experience, or judgment.&lt;/p&gt;

&lt;p&gt;What it replaces is repetitive work.&lt;/p&gt;

&lt;p&gt;And for engineering teams, that’s often the most valuable automation of all.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>n8n</category>
      <category>workflowautomation</category>
      <category>automation</category>
    </item>
    <item>
      <title>From 41 Minutes to 8 Minutes: How I Made Our CI/CD Pipeline 5x Faster</title>
      <dc:creator>Adnan Latif</dc:creator>
      <pubDate>Mon, 16 Dec 2024 18:23:11 +0000</pubDate>
      <link>https://dev.to/adnanlatif/from-41-minutes-to-8-minutes-how-i-made-our-cicd-pipeline-5x-faster-49d1</link>
      <guid>https://dev.to/adnanlatif/from-41-minutes-to-8-minutes-how-i-made-our-cicd-pipeline-5x-faster-49d1</guid>
      <description>&lt;h2&gt;
  
  
  From 41 Minutes to 8 Minutes: How I Made Our CI/CD Pipeline 5x Faster
&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%2F647jyd0ew5fptwh325ki.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F647jyd0ew5fptwh325ki.jpeg" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;In the world of software development, time is everything. Continuous Integration/Continuous Deployment pipelines speed the process up, but sometimes it’s the pipeline that makes the process slow down, ironically. This was what brought me to my latest problem when our Jenkins pipeline grew to an unmanageably long 41 minutes per build.&lt;/p&gt;

&lt;p&gt;Determined to eliminate this inefficiency, I analyzed, optimized, and transformed our pipeline from a whopping 41 minutes down to 8 minutes — a 5x improvement! In this article, I’ll walk you through the issues I encountered, the solutions I implemented, and the strategies you can use to supercharge your own pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Our CI/CD pipeline handled the following tasks for both backend and frontend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Code Checkout&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Static Code Analysis: ESLint, SonarQube&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unit Testing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker Image Build and Push&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Staging Deployment&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Manual Approval and Production Deployment&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At first glance, the pipeline appeared robust, but some issues came into view:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bloated Docker Build Context&lt;/strong&gt;&lt;br&gt;
The build context — all the files sent into Docker during an image build — had grown to 1.5GB and was taking a really long time to build.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Installing Dependencies Redundantly&lt;/strong&gt;&lt;br&gt;
Every stage in the pipeline had to reinstall the npm dependencies from scratch, thus adding unnecessary delays.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Poor Docker Image Management&lt;/strong&gt;&lt;br&gt;
Docker images were rebuilt and pushed to the registry, even when no changes had occurred.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No Parallel Execution&lt;/strong&gt;&lt;br&gt;
Similarly, all tasks, such as static code analysis or testing, were run sequentially.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Manual Deployment Steps&lt;/strong&gt;&lt;br&gt;
Since this involved updating AWS ECS task definitions manually, deployment of the backend was time-consuming and prone to human error.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Solutions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here’s How I Transformed the Pipeline for a 5x Optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reduce the size of the Docker Build Context
&lt;/h2&gt;

&lt;p&gt;The Docker build context was unnecessarily large due to unfiltered project directories. We can use .dockerignore file to exclude certain files such as node_modules, logs etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key File&lt;/strong&gt;: .dockerignore&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules  
*.log  
dist  
coverage  
test-results
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Impact&lt;/strong&gt;:&lt;br&gt;
Reduced the build context size from 1.5GB to ~10MB, reducing the transfer time from 30 minutes to &amp;lt;1 minute.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Dependency Caching&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Every stage was using npm install. I replaced it with npm ci for reproducibility and activated caching in Jenkins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Command Update&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm ci --cache ~/.npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Impact&lt;/strong&gt;:&lt;br&gt;
Reduced dependency installation time from 3–4 minutes per stage down to &amp;lt;20 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Improve Docker Image Handling&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Previously, the pipeline would rebuild and push Docker images irrespective of changes. I added the logic to compare the hash of local and remote images, doing a push only if the image changed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Updated Logic&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def remoteImageHash = sh(returnStdout: true, script: "docker inspect --format='{{.Id}}' $DOCKER_IMAGE:$DOCKER_TAG || echo ''").trim()
def localImageHash = sh(returnStdout: true, script: "docker images --no-trunc -q $DOCKER_IMAGE:$DOCKER_TAG").trim()

if (localImageHash != remoteImageHash) {
    sh 'docker push $DOCKER_IMAGE:$DOCKER_TAG'
} else {
    echo "Image has not changed; skipping push."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Impact&lt;/strong&gt;:&lt;br&gt;
Avoided unnecessary pushes, saving 3–5 minutes per build.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Run Static Analysis and Testing in Parallel&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I extended the Jenkins pipeline to make use of the parallel directive so that tasks like ESLint, SonarQube analysis, and unit tests could proceed simultaneously.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Updated Pipeline&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stage('Static Code Analysis') {
    parallel {
        stage('Frontend ESLint') {
            steps {
                sh 'npm run lint'
            }
        }
        stage('Backend SonarQube') {
            steps {
                withSonarQubeEnv() {
                    sh 'sonar-scanner'
                }
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Impact&lt;/strong&gt;:&lt;br&gt;
Reduced static analysis and testing time by 50%.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Automatic Backend Deployment&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Manual updates to AWS ECS task definitions were time-consuming and error-prone. I automated this step using the AWS CLI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Automated Script&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def taskDefinitionJson = """
{
    "family": "$ECS_TASK_DEFINITION_NAME",
    "containerDefinitions": [
        {
            "name": "backend",
            "image": "$DOCKER_IMAGE:$DOCKER_TAG",
            "memory": 512,
            "cpu": 256,
            "essential": true
        }
    ]
}
"""
sh "echo '${taskDefinitionJson}' &amp;gt; task-definition.json"
sh "aws ecs register-task-definition --cli-input-json file://task-definition.json --region $AWS_REGION"
sh "aws ecs update-service --cluster $ECS_CLUSTER_NAME --service $ECS_SERVICE_NAME --task-definition $ECS_TASK_DEFINITION_NAME --region $AWS_REGION"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Impact&lt;/strong&gt;:&lt;br&gt;
Streamlined deployments, shaving off 5 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Results&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After these optimizations, the pipeline time came down from 41 minutes to just 8 minutes — a 5x improvement. Here’s a detailed comparison:&lt;/p&gt;

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

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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Logs Are Your Best Friend&lt;/strong&gt;: Analyze logs to pinpoint bottlenecks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Caching Saves the Day&lt;/strong&gt;: Effective use of caching can drastically cut build times.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Run Tasks in Parallel&lt;/strong&gt;: Use parallel execution for immediate time savings.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Exclude Irrelevant Files&lt;/strong&gt;: A .dockerignore file can significantly boost performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automate Repetitive Tasks&lt;/strong&gt;: Automation eliminates errors and speeds up workflows.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Optimizing a CI/CD pipeline was an eye-opening experience. Targeting key bottlenecks and implementing strategic changes transformed a 41-minute chore into an 8-minute powerhouse. The result? Faster deployments, happier developers, and more time to focus on features.&lt;/p&gt;

&lt;p&gt;If you’re struggling with a slow pipeline, start by identifying bottlenecks, leverage caching, parallelize tasks, and automate repetitive steps. Even small tweaks can lead to massive gains.&lt;/p&gt;

&lt;p&gt;How much time have you saved by optimizing your CI/CD pipeline? Share your experiences and tips in the comments below!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>cicd</category>
      <category>jenkins</category>
      <category>docker</category>
    </item>
    <item>
      <title>From Confusion to Clarity: Understanding ‘this’ in JavaScript</title>
      <dc:creator>Adnan Latif</dc:creator>
      <pubDate>Tue, 30 Jan 2024 08:27:28 +0000</pubDate>
      <link>https://dev.to/adnanlatif/from-confusion-to-clarity-understanding-this-in-javascript-59gg</link>
      <guid>https://dev.to/adnanlatif/from-confusion-to-clarity-understanding-this-in-javascript-59gg</guid>
      <description>&lt;h2&gt;
  
  
  From Confusion to Clarity: Understanding ‘this’ in JavaScript
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cZ7kuWzo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2476/1%2AGHA1sOf3WnPtYGdVHW7H4A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cZ7kuWzo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2476/1%2AGHA1sOf3WnPtYGdVHW7H4A.png" alt="Main Image" width="800" height="424"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the world of JavaScript, the this keyword often stands as a mystery, perplexing many new developers. Understanding this is crucial for writing efficient and bug-free code. In this article, we'll embark on a journey to demystify this and unravel its secrets in simple terms that even a novice developer can grasp.&lt;/p&gt;

&lt;p&gt;What is “this”? In JavaScript, this is a special keyword that refers to the context in which a function is called. This context can vary based on how and where a function is invoked. Think of this as a placeholder that dynamically represents different values depending on the situation.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Understanding this in Different Contexts:&lt;br&gt;
 Inside a function body in JavaScript, the behavior of the &lt;em&gt;this&lt;/em&gt; keyword depends on how the function is called.&lt;br&gt;
 &lt;strong&gt;Regular Functions:&lt;/strong&gt;&lt;br&gt;
 In non-arrow functions, &lt;em&gt;this&lt;/em&gt; is determined by the caller of the function.&lt;br&gt;
 If the function is called as a method of an object, &lt;em&gt;this&lt;/em&gt; refers to that object.&lt;br&gt;
 If the function is called without a context, &lt;em&gt;this&lt;/em&gt; defaults to the global object (&lt;em&gt;window&lt;/em&gt; in browsers, &lt;em&gt;global&lt;/em&gt; in Node.js), or &lt;em&gt;undefined&lt;/em&gt; in strict mode.&lt;br&gt;
 &lt;strong&gt;Arrow Functions:&lt;/strong&gt;&lt;br&gt;
 Arrow functions do not have their own &lt;em&gt;this&lt;/em&gt; binding. Instead, they inherit &lt;em&gt;this&lt;/em&gt; from the enclosing lexical scope.&lt;br&gt;
 In other words, &lt;em&gt;this&lt;/em&gt; inside an arrow function refers to the &lt;em&gt;this&lt;/em&gt; value of the enclosing scope where the arrow function was defined.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Global Context:&lt;/strong&gt; When a function is called without any explicit context, this refers to the global object. In web browsers, this is usually the window object.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xlW25sqd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2416/1%2A-8DzXEBYZdxWU2PrYOK07Q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xlW25sqd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2416/1%2A-8DzXEBYZdxWU2PrYOK07Q.png" alt="this in global context" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Object Method:&lt;/strong&gt; When a function is called as a method of an object, this points to the object that owns the function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9oI-NhIQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2416/1%2ABoKUGOG5Ircb2_4dsCusig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9oI-NhIQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2416/1%2ABoKUGOG5Ircb2_4dsCusig.png" alt="this in object" width="800" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Arrow Functions:&lt;/strong&gt; Arrow functions do not have their own this binding and inherit this from the enclosing lexical scope.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yG4ZNHU8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2812/1%2ABV3Cft9MA5lqSmpfHzJNpQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yG4ZNHU8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2812/1%2ABV3Cft9MA5lqSmpfHzJNpQ.png" alt="this in arrow function" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constructor Function:&lt;/strong&gt; Inside a constructor function, this refers to the specific instance of the object being created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---CJeo-fF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2208/1%2AHK0gchWVUnu5e94TIAv_-g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---CJeo-fF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2208/1%2AHK0gchWVUnu5e94TIAv_-g.png" alt="this in constructor" width="800" height="514"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event Handlers:&lt;/strong&gt; In event handler functions, this typically points to the DOM element that triggered the event.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4tN-Xl_P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2360/1%2ADDvjXXemD8d_AEyyLzAapw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4tN-Xl_P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2360/1%2ADDvjXXemD8d_AEyyLzAapw.png" alt="this in event handler" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js Environment:&lt;/strong&gt; In Node.js, this behaves differently compared to the browser environment. In most cases, this in Node.js modules refers to the module.exports object, providing access to the module's exports and scoped variables.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SKSMxbNb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2360/1%2A9eFNy5Cv2dJFs6z6-TBV-A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SKSMxbNb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2360/1%2A9eFNy5Cv2dJFs6z6-TBV-A.png" alt="this in node" width="800" height="607"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Explicit Binding:&lt;/strong&gt; JavaScript provides methods like call, apply, and bind to explicitly set the value of this when calling a function.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oCreU7zC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2360/1%2ANCjKg0ZmTX9zWLK5zDW9nw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oCreU7zC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2360/1%2ANCjKg0ZmTX9zWLK5zDW9nw.png" alt="this in call, apply and bind" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Understanding this is essential for writing robust JavaScript code. By grasping the various contexts in which this operates, developers can wield its power effectively. Remember, this is not as daunting as it seems – it's just a pointer that adapts to its surroundings, guiding your functions to interact with the right objects at the right time. Happy coding!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>javascriptinterview</category>
    </item>
    <item>
      <title>JavaScript Tips and Tricks</title>
      <dc:creator>Adnan Latif</dc:creator>
      <pubDate>Sat, 18 Nov 2023 23:15:58 +0000</pubDate>
      <link>https://dev.to/adnanlatif/javascript-tips-and-tricks-49mi</link>
      <guid>https://dev.to/adnanlatif/javascript-tips-and-tricks-49mi</guid>
      <description>&lt;h2&gt;
  
  
  JavaScript Tips and Tricks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d2ThMrYZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/4120/1%2A06Q7HHp3ppGAdrIFwNVDVg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d2ThMrYZ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/4120/1%2A06Q7HHp3ppGAdrIFwNVDVg.jpeg" alt="" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you know, JavaScript is the number one programming language in the world, the language of the web, of mobile hybrid apps (like &lt;a href="https://reactnative.dev/"&gt;React Native&lt;/a&gt;), of the server side (like &lt;a href="https://nodejs.org/en/"&gt;NodeJS&lt;/a&gt; ) and has many other implementations. It’s also the starting point for many new developers to the world of programming, as it can be used to display a simple alert in the web browser but also to control a robot (using &lt;a href="https://nodebots.io/"&gt;nodebot&lt;/a&gt;, or nodruino). The developers who master JavaScript and write organized and performant code have become the most sought after in the job market.&lt;/p&gt;

&lt;p&gt;In this article, I’ll share a set of JavaScript tips, tricks and best practices that should be known by all JavaScript developers regardless of their browser/engine or the SSJS (Server Side JavaScript) interpreter.&lt;/p&gt;

&lt;h2&gt;
  
  
  *&lt;em&gt;use *&lt;/em&gt;=== *&lt;em&gt;instead of *&lt;/em&gt;==
&lt;/h2&gt;

&lt;p&gt;The == (or !=) operator performs an automatic type conversion if needed. The === (or !==) operator will not perform any conversion. It compares the value and the type, which could be considered faster than ==.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JbvwQbIb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2312/1%2A5j2S_Ot3LJmeMrISerV0CQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JbvwQbIb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2312/1%2A5j2S_Ot3LJmeMrISerV0CQ.png" alt="" width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;undefined, null, 0, false, NaN, ‘’(empty string) are all falsy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Find max and min from an array
&lt;/h2&gt;

&lt;p&gt;The traditional way to find min and max is loop through each element of array and find min and max. Below code snippet is showing to find min and max from array using spread operator.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2jiQRsAe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AgJ1aYxHa5cjJD5WipPxbLQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2jiQRsAe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AgJ1aYxHa5cjJD5WipPxbLQ.png" alt="" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Merging two arrays
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--l0LPPKah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2420/1%2AIiNhQA0SQtpnAxqTAIRv8A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--l0LPPKah--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2420/1%2AIiNhQA0SQtpnAxqTAIRv8A.png" alt="" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Repeating string multiple times
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mb5CEe2w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A8iFhY9LwId80tXP6Wqxf0A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mb5CEe2w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A8iFhY9LwId80tXP6Wqxf0A.png" alt="" width="681" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  String to Number conversion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mFpZP_Cz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A2ENDkJr_JbrmJtYSggZ3Rw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mFpZP_Cz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2A2ENDkJr_JbrmJtYSggZ3Rw.png" alt="" width="800" height="580"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple variable assignments
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KyTjaWvW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ApolManQb7avrsOb-o-W2Jw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KyTjaWvW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ApolManQb7avrsOb-o-W2Jw.png" alt="" width="800" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple condition check
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--X_6jWjzS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3132/1%2AYU67GcqRmuS74MM8HNzDVw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--X_6jWjzS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3132/1%2AYU67GcqRmuS74MM8HNzDVw.png" alt="" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Remove duplicates from an array
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LuJjNjxY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2624/1%2A_gEXMCTT80a7GJBCpHmZ1A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LuJjNjxY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2624/1%2A_gEXMCTT80a7GJBCpHmZ1A.png" alt="" width="800" height="567"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sum the values of an array
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TFxZ7OVu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2136/1%2A0MkwswVNT92WWb8le1HdYg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TFxZ7OVu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2136/1%2A0MkwswVNT92WWb8le1HdYg.png" alt="" width="800" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Convert a string to an array
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CVbXMnzT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2456/1%2Ai26ZtsiEaVnR4pBdo-N6Dg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CVbXMnzT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2456/1%2Ai26ZtsiEaVnR4pBdo-N6Dg.png" alt="" width="800" height="560"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Remove falsey values from an array
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OxBBC7Rz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3232/1%2A6_qYZQGMWFV2dQnk5FTWVg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OxBBC7Rz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3232/1%2A6_qYZQGMWFV2dQnk5FTWVg.png" alt="" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternatives of for loop
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HNjYuoG5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ADBCKNd9VHlKQPt14fxhuPA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HNjYuoG5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2ADBCKNd9VHlKQPt14fxhuPA.png" alt="" width="800" height="787"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  OR Short circuit
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vjBkruMX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2792/1%2AjaRFy9Zi8lSE4uE0brDmRw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vjBkruMX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2792/1%2AjaRFy9Zi8lSE4uE0brDmRw.png" alt="" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AND Short circuit
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r4e97opK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2928/1%2ATj0La0eChDoLdl7wlDd0QQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r4e97opK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2928/1%2ATj0La0eChDoLdl7wlDd0QQ.png" alt="" width="800" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Exponent power
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jeF6MbBx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AbUPRweugl3OZwskfeoJKhA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jeF6MbBx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2AbUPRweugl3OZwskfeoJKhA.png" alt="" width="800" height="578"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Count function parameters
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--S-ACMFiU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2As_Hu-wHUoEAkUngBgyzDTQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--S-ACMFiU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2000/1%2As_Hu-wHUoEAkUngBgyzDTQ.png" alt="" width="563" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Assign default function parameter
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vrqsKwsx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2220/1%2AU03MFq79zxo7rjIUjgBOxA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vrqsKwsx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2220/1%2AU03MFq79zxo7rjIUjgBOxA.png" alt="" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check if key exists in the object&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kK3Dyda2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2604/1%2A56cGx2ErQ0nTHeawQi9Pvw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kK3Dyda2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2604/1%2A56cGx2ErQ0nTHeawQi9Pvw.png" alt="" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Object property assignment
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eS95TPEl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3636/1%2ATwflyJ8BiQACWznFKKMEig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eS95TPEl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/3636/1%2ATwflyJ8BiQACWznFKKMEig.png" alt="" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Assigning object value property to a variable
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hlt1ZwL---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2220/1%2AqeS6GEGANg1uNpz1A6TzjA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hlt1ZwL---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2220/1%2AqeS6GEGANg1uNpz1A6TzjA.png" alt="" width="800" height="644"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Removing multiple properties from an object
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uBBQVf9q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2084/1%2Acjaz3KW-h0cIzxMaVeqq-w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uBBQVf9q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2084/1%2Acjaz3KW-h0cIzxMaVeqq-w.png" alt="" width="800" height="631"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are my two bits of contribution in JavaScript community. I hope these code snippets will help someone to learn some tips and tricks in JavaScript.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>tips</category>
    </item>
    <item>
      <title>Deep Dive into Docker</title>
      <dc:creator>Adnan Latif</dc:creator>
      <pubDate>Tue, 14 Nov 2023 19:44:26 +0000</pubDate>
      <link>https://dev.to/adnanlatif/deep-dive-into-docker-2if</link>
      <guid>https://dev.to/adnanlatif/deep-dive-into-docker-2if</guid>
      <description>&lt;p&gt;&lt;strong&gt;What is Docker&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Docker is an open-source software platform to create, deploy and manage virtualized application containers on a common operating system (OS), with an ecosystem of allied tools. Docker container technology debuted in 2013; Docker Inc. was formed to support a commercial edition of container management software and be the principal sponsor of an open-source version. Mirantis acquired the Docker Enterprise business in November 2019.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Docker works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Docker packages, provisions, and runs containers. Container technology is available through the operating system: A container packages the application service or function with all the libraries, configuration files, dependencies, and other necessary parts and parameters to operate. Each container shares the services of one underlying operating system. Docker images contain all the dependencies needed to execute code inside a container, so containers that move between Docker environments with the same OS work with no changes.&lt;/p&gt;

&lt;p&gt;Docker uses resource isolation in the OS kernel to run multiple containers on the same OS. This is different than virtual machines (VMs), which encapsulate an entire OS with executable code on top of an abstracted layer of physical hardware resources.&lt;/p&gt;

&lt;p&gt;Docker was created to work on the Linux platform, but has extended to offer greater support for non-Linux operating systems, including Microsoft Windows and Apple OS X. Versions of Docker for Amazon Web Services (AWS) and Microsoft Azure are available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A0hVg1ePfmVBYGJZsbPmuwA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A0hVg1ePfmVBYGJZsbPmuwA.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why do we need Docker?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Well, Docker is a platform for building, running, and shipping applications in a consistent manner. So, if your application works on your development machine, it can run and function the same way on other machines. If you have been developing software for a while, you’ve probably come across this situation where your application works on your development machine but doesn’t somewhere else. Can you think of three reasons why this happens? Well, this can happen if one or more files are not included as part of your deployment, so your application is not completely deployed. It’s missing something. This can also happen if the target machine is running a different version of some software that your application needs. Let’s say your application needs Node version 14, but the target machine is running Node version 9. This can also happen if the configuration settings like environment variables are different across these machines. And this is where Docker comes to the rescue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What are Containers in Docker?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;With Docker, we can easily package up our application with everything it needs and run it anywhere on any machine with Docker. So, if your application needs a given version of Node and MongoDB, all of these will be included in your Applications package. Now you can take this package and run it on any machine that runs Docker. So, if it works on your development machine, it’s going to work on your test and production machines. Now there’s more. If someone joins your team, they don’t have to spend half a day or so setting up a new machine to run your application. They don’t have to install and configure all these dependencies. They simply tell Docker to bring up your application, and Docker itself will automatically download and run these dependencies inside an isolated environment called a container and this is the beauty of Docker.&lt;/p&gt;

&lt;p&gt;This isolated environment allows multiple applications to use different versions of some software side by side. So, one application may use Node version 14. Another application may use Node version 9. Both these applications can run side by side on the same machine without messing with each other. So, this is how Docker allows us to consistently run an application on different machines. Now, there is one more benefit here. When we’re done with this application and don’t want to work on it anymore, we can remove the application and all its dependencies in one go without Docker.&lt;/p&gt;

&lt;p&gt;As we work on different projects, our development machine gets cluttered with so many libraries and tools that are used by different applications, and then after a while, we don’t know if we can remove one or more of these tools because we’re always afraid that we would mess up with some application with Docker, we don’t have to worry about this because each application runs with its dependencies inside an isolated environment. We can safely remove an application with all its dependencies to clean up our machine. Isn’t that great? So, in a nutshell. Docker helps us consistently build, run, and ship our applications and that’s why a lot of employers are looking for people with Docker skills these days. So if you’re pursuing a job as a software or DevOps engineer, I highly encourage you to learn Docker and learn it well.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Difference between Containers and Virtual Machines?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So, in the last paragraph, I briefly talked about containers. The container is an isolated environment for running an application. Now. One of the questions that often comes up is how our containers are different from virtual machines or VMS. Do you know the differences Well, a virtual machine as the name implies, is an abstraction of a machine or physical hardware. So, we can run several virtual machines on a real physical machine. For example, we can have a Mac, and on this Mac, we can run two virtual machines, one running Windows, and the other running Linux. How do we do that using a tool called Hyper Visor I know it’s one of those computer science names. In simple terms, the Hyper Visor is a software we use to create and manage virtual machines. There are many hypervisors available out there, like Virtual Box and VMware which are cross-platform. So, they can run on Windows or Mac. OS and Linux and Hyper-V (which is only for Windows). So, with a hyper Visor, we can manage virtual machines. Now, what is the benefit of building virtual machines Well, for us, software developers, we can run an application in isolation inside a virtual machine. So, on the same physical machine, we can have two different virtual machines. Each runs a completely different application and each application has the exact dependencies it needs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Af5P2mIOspp5ssTKjwpnGlQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2Af5P2mIOspp5ssTKjwpnGlQ.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A5xYZbrOxfFO73f370Ykjxw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2A5xYZbrOxfFO73f370Ykjxw.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, application one may use node version 14 and Mongo Db Version 4, and one application may use node version nine and Mongo Db Version 3. All these are running on the same machine but in different isolated environments. That’s one of the benefits of virtual machines. However, there are several problems with this model. Each virtual machine needs a full copy of an operating system that needs to be licensed, patched, and monitored. And that’s why these virtual machines are slow to start because the entire operating system must be loaded just like starting your computer. Another problem is that these virtual machines are resource-intensive because each virtual machine takes a slice of the actual physical hardware resources like CPU memory and disk space. So, if you have eight gigabytes of memory, that memory must be divided between different virtual machines. Of course, we can decide how much memory to allocate to each virtual machine. But at the end of the day, we have a limit in terms of the number of VMS, we can run on a machine, usually a handful, otherwise we’re going to run out of hardware resources. Now let’s talk about containers, containers give us the same kind of isolation, so we can run multiple applications in isolation, but they are more lightweight. They don’t need a full operating system. In fact, all containers on a single machine share the operating system of the host. So that means we need to license, patch, and monitor a single operating system. Also, because the operating system has already started on the host, a container can start up quickly, usually in a second, sometimes less. These containers also don’t need a slice of the hardware resources on the host, so we don’t need to give them a specific number of CPU cores or a slice of memory or disk space. So, on a single host, we can run tens or even hundreds of containers side by side. So, these are the differences between containers and virtual machines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker Architecture&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s talk about the architecture of Docker. So, you understand how it works Docker uses a client-server architecture. So, it has a client component that talks to a server component using a restful API the server also called the Docker engine sits in the background and takes care of building and running Docker containers. But technically a container is just a process, like other processes running on your computer. But it’s a special kind of process which we’re going to talk about soon Now, as I told you, unlike virtual machines, containers don’t contain a full-blown operating system. Instead, all containers on a host share the operating system of the host. Now, more accurately, all these containers share the kernel of the host. What’s the kernel? The kernel is the core of an operating system. It’s like the engine of a car. It’s the part that manages all applications as well as hardware resources like memory and CPU every operating system has its own kernel or engine. These kernels have different APIs that’s why we cannot run a Windows application on Linux because under the hood this application needs to talk to the kernel of the underlying operating system. Okay, so that means on a Linux machine, we can only run Linux containers because these containers need Linux On a Windows Machine. However, we can run both Windows and Linux containers because Windows 10 is now shipped with a custom-built Linux kernel. This is in addition to the Windows Kernel, that’s always been in Windows. It’s not a replacement. So, with this Linux kernel now we can run Linux applications natively on Windows, so on Windows, we can run both Linux and Windows containers. Our Windows containers share the Windows kernel and our Linux containers share the Linux kernel. Okay, now, what about Mac OS Well, Mac OS has its own kernel, which is different from Linux and Windows kernels, and this kernel does not have native support for continuous applications. So docker on Mac uses a lightweight Linux virtual machine to run Linux containers. Alright enough about the architecture. Next we’re going to install Docker and that’s where the fun begins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now the fun part begins, where we get our hands dirty with Docker&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s install the latest version of Docker. If you have an existing version of Docker on your machine, I highly encourage you to upgrade to the latest version because your version might be old and not compatible with the version I’m using this Quest.&lt;/p&gt;

&lt;p&gt;I am using the version at the time of blog is 20.10.13.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AAHWH83lsjhCRvaFwHXg5zg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F1%2AAHWH83lsjhCRvaFwHXg5zg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to &lt;a href="https://docs.docker.com/get-docker/" rel="noopener noreferrer"&gt;Docker docs&lt;/a&gt; to get the latest version of docker. Docker desktop is available for Windows, Mac and Linux. We have a Docker desktop which is the combination of the Docker engine, plus a bunch of other tools.&lt;/p&gt;

&lt;p&gt;Let’s look at the instructions for Windows. You can download the latest version from Docker Hub and make sure to read system requirement. What are the things that is really important is enabling hyper-v and containers Windows features just go to the settings where you can turn on or turn off those features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Docker Daily use Commands&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker version&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This command is used to get the currently installed version of docker.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker pull&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Usage: docker pull &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This command is used to pull images from the &lt;strong&gt;docker repository&lt;/strong&gt;(hub.docker.com).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker run&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Usage: docker run -it -d &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This command is used to create a container from an image.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;-d: To start a container in detached mode, you use -d=true or just -d option. By design, containers started in detached mode exit when the root process used to run the container exits, unless you also specify the --rm option.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;-it: For interactive processes (like a shell), you must use -i -t together in order to allocate a tty for the container process. -i -t is often written -it as you’ll see in later examples. Specifying -t is forbidden when the client is receiving its standard input from a pipe.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker ps&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This command is used to list the running containers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker ps -a&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This command is used to show all the running and exited containers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker exec&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Usage: docker exec -it  bash&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This command is used to access the running container.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker stop&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Usage: docker stop &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This command stops a running container.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker kill&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Usage: docker kill &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This command kills the container by stopping its execution immediately. The difference between ‘docker kill’ and ‘docker stop’ is that ‘docker stop’ gives the container time to shutdown gracefully, in situations when it is taking too much time for getting the container to stop, one can opt to kill it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker commit&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Usage: docker commit  &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This command creates a new image of an edited container on the local system.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker login&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This command is used to login to the docker hub repository.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker push&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Usage: docker push &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This command is used to push an image to the docker hub repository.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker images&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This command lists all the locally stored docker images.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker rm&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Usage: docker rm &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This command is used to delete a stopped container.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker rmi&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Usage: docker rmi &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This command is used to delete an image from local storage.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;docker build&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Usage: docker build &lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This command is used to build an image from a specified docker file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Our First Docker Application
&lt;/h2&gt;

&lt;p&gt;Let's say we have a PHP application and want to deploy it to our staging or production server. First, we make sure we have the docker configuration script included in the root directory of the application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Create a Dockerfile in your application&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create a file with name Dockerfile at the root of your application and include the code below to tell Docker what to do when running in the production or staging environment&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:alpine
COPY . /app
WORKDIR /app
CMD node app.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Above is a sample docker script which configures Node on a staging or production server.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Installing Docker on Staging Or Production Server&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For Mac get docker &lt;a href="https://docs.docker.com/docker-for-mac/install/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For Windows go &lt;a href="https://docs.docker.com/docker-for-windows/install/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For Linux go &lt;a href="https://docs.docker.com/desktop/linux/install/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Running Docker&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After docker is installed on the staging or production server, &lt;strong&gt;&lt;em&gt;click on the whale icon&lt;/em&gt;&lt;/strong&gt; to run docker&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Deploying Your Application&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Copy the application to the staging or production server and do the following&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to the project directory on the terminal and create a docker image.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the following command in the terminal and it will create a docker image of the application and download all the necessary dependencies needed for the application to run successfully&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t &amp;lt;name to give to your image&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Convert Docker image of the Application into a Running container.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run the following command in terminal and it will use create a running container with all the needed dependencies and start the application.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -p 9090:80 &amp;lt;name to give to your container&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The 9090 is the port we want to access our application on. 80 is the port the container is exposing for the host to access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Below are some useful Docker commands
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Stopping a running image&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker stop &amp;lt;id-of-image&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Starting an image which is not running&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker start &amp;lt;id-of-image&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Removing an image from docker&lt;/strong&gt;&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Removing a container from docker&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker rm &amp;lt;id-of-container&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For the moment that’s enough to understand what is docker and how we can use it. In my next blog we will write a full React and Node app and run it on Docker by using&lt;/p&gt;

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

&lt;/div&gt;

&lt;p&gt;With docker-compose.yml we don’t need to restart Docker again and again to publish the new changes. When we save the file Docker will automatically publish the new changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This post was originally posted on &lt;a href="https://medium.com/@alatif.bwp/deep-dive-into-docker-81549b1e6dad" rel="noopener noreferrer"&gt;Medium.com&lt;/a&gt; by me. 😃&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
