<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Luke</title>
    <description>The latest articles on Forem by Luke (@locnguyenpv).</description>
    <link>https://forem.com/locnguyenpv</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%2F524882%2F4c23f357-1397-4bbd-8aa0-acd228365754.png</url>
      <title>Forem: Luke</title>
      <link>https://forem.com/locnguyenpv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/locnguyenpv"/>
    <language>en</language>
    <item>
      <title>Pull/Push in DevOps</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Sun, 16 Nov 2025 16:34:25 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/pullpush-in-devops-49pi</link>
      <guid>https://forem.com/locnguyenpv/pullpush-in-devops-49pi</guid>
      <description>&lt;p&gt;Push-based or Pull-based are synchronize code/config between dev, server and repository - but mechanism of synchronization is different.&lt;/p&gt;

&lt;h2&gt;
  
  
  Push-based
&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%2Ffinqvyl24axjp2bd41c0.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%2Ffinqvyl24axjp2bd41c0.png" alt="push-based" width="800" height="727"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;push-based&lt;/strong&gt;, we'll have an CI/CD flow which active "push" the changes to server. This model usually use in traditional deployment, apply the changes after pipeline run directly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pros:

&lt;ul&gt;
&lt;li&gt;Easy to deployment&lt;/li&gt;
&lt;li&gt;Re-use existing pipeline&lt;/li&gt;
&lt;li&gt;Immediate execution&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Cons:

&lt;ul&gt;
&lt;li&gt;Hard to track drift&lt;/li&gt;
&lt;li&gt;Pipeline dependence&lt;/li&gt;
&lt;li&gt;Rollback missing&lt;/li&gt;
&lt;li&gt;Security risk&lt;/li&gt;
&lt;li&gt;Audit challenges&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pull-based
&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%2F49fz8cvqwe30ywyyrxsk.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%2F49fz8cvqwe30ywyyrxsk.png" alt="Pull-based" width="800" height="642"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;pull-based&lt;/strong&gt;, the server actively pulls changes from the project’s repository. This approach is called GitOps, where Git acts as the &lt;strong&gt;Single Source of Truth&lt;/strong&gt;. The workflow is similar to push-based, but with some key differences - The pipeline won't deploy to server directly - We add an agent (ArgoCD / Flux) to the server side, which continuously observes the project’s repository and pulls the changes to apply them to the server whenever updates occur.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pros:

&lt;ul&gt;
&lt;li&gt;Automation&lt;/li&gt;
&lt;li&gt;Easy rollback&lt;/li&gt;
&lt;li&gt;Multi-cluster support&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Cons:

&lt;ul&gt;
&lt;li&gt;Agent installation&lt;/li&gt;
&lt;li&gt;Complex configuration&lt;/li&gt;
&lt;li&gt;Polling latency&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Criteria&lt;/th&gt;
&lt;th&gt;Pull-Based&lt;/th&gt;
&lt;th&gt;Push-Based&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Status Synchronization&lt;/td&gt;
&lt;td&gt;Automation&lt;/td&gt;
&lt;td&gt;Manual (triggered by pipeline run)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Installation&lt;/td&gt;
&lt;td&gt;Install agent in server side&lt;/td&gt;
&lt;td&gt;No need agent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Suitable For&lt;/td&gt;
&lt;td&gt;Kubernetes, multi-cluster, complex project&lt;/td&gt;
&lt;td&gt;Medium-sized project, simple pipeline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;More secure (server only pulls from Git)&lt;/td&gt;
&lt;td&gt;High risk (pipeline needs direct access to server)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>devops</category>
    </item>
    <item>
      <title>Git - Dev/DevOps best friend</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Fri, 26 Sep 2025 20:45:51 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/git-devdevops-best-friend-4ji6</link>
      <guid>https://forem.com/locnguyenpv/git-devdevops-best-friend-4ji6</guid>
      <description>&lt;p&gt;In a software, &lt;strong&gt;Git&lt;/strong&gt; is more than just a version control system - It's a &lt;u&gt;backbone&lt;/u&gt; of the entire project. It acts as a &lt;u&gt;single source of truth&lt;/u&gt;, it store anything related to code and infrastructure. &lt;/p&gt;

&lt;h2&gt;
  
  
  Why Git is important
&lt;/h2&gt;

&lt;p&gt;Git solves 3 big problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;History changes:&lt;/strong&gt;Every changes is recorded, making it easy to review, revert, or understand the evolution of the code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automation workflow:&lt;/strong&gt;Git integrates seamlessly with CI/CD pipelines, enabling automated testing, building, and deployment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Made/keep an update:&lt;/strong&gt;Git ensures that everyone works with the latest version, reducing conflicts and improving team efficiency.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Tips for using Git effectively
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Small commit and clearly message:&lt;/strong&gt; You should commit a small part, not a big change and writing clearly message which describe what you did &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Give a meaning name for branch:&lt;/strong&gt; Don't make your team member be confuse or guessing what the branch do&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the &lt;code&gt;main&lt;/code&gt; branch stable:&lt;/strong&gt; Ensure code in &lt;code&gt;main&lt;/code&gt; branch is always stable, even new members can clone and run it without error&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag version:&lt;/strong&gt; Tagging version for rollback / manage easily &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Branching strategy in Git
&lt;/h2&gt;

&lt;p&gt;Now a day, we have two popular strategies &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Git flow&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Trunk-Based&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a look into it 👀&lt;/p&gt;

&lt;h3&gt;
  
  
  Git flow
&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%2Fkaeaqv8k8vjw23citvih.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%2Fkaeaqv8k8vjw23citvih.png" alt="git-flow" width="800" height="546"&gt;&lt;/a&gt;&lt;/p&gt;
Git flow



&lt;p&gt;In real-world projects, we often create many branches—and each branch serves a specific purpose. Depending on your company or team, branch names might differ, but they should still align with the core structure of Git Flow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;main&lt;/code&gt;: production-ready branch, it contain stable and deployable code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;hotfix&lt;/code&gt;: Urgent fixes for production issues. Branched from &lt;code&gt;main&lt;/code&gt; and merged into both &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;develop&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;release&lt;/code&gt;: Code ready for final testing before merging into &lt;code&gt;main&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;develop&lt;/code&gt;: The integration branch for development&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;features&lt;/code&gt;: Developing new features, typical branched from &lt;code&gt;develop&lt;/code&gt; and merged back when completed&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;We can use git flow for a big team or projects have complex release cycles&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Trunk-Based
&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%2Fjnizutokkybpa0sffy7s.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%2Fjnizutokkybpa0sffy7s.png" alt="trunk-based" width="800" height="526"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In trunk-based, we only have two branches &lt;code&gt;main&lt;/code&gt; and &lt;code&gt;features&lt;/code&gt;, with &lt;code&gt;features&lt;/code&gt;'s life-time is smaller and shorter than &lt;u&gt;git flow&lt;/u&gt; (usually 2-3 days). This strategy helps us take advantage of &lt;u&gt;automation &lt;/u&gt; in git.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;We can use trunk-based for a small team or pet projects&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&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%2F867f9dgrmfn55rd4el6f.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%2F867f9dgrmfn55rd4el6f.png" alt="meme" width="500" height="756"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choosing a right strategy will help your team deliver product faster and reliable. No need to follow the others, just choose your best suite 😎&lt;/p&gt;

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

</description>
      <category>cicd</category>
      <category>git</category>
    </item>
    <item>
      <title>Introduction to CI/CD</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Fri, 26 Sep 2025 18:49:37 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/introduction-to-cicd-2nfg</link>
      <guid>https://forem.com/locnguyenpv/introduction-to-cicd-2nfg</guid>
      <description>&lt;p&gt;As a developer, at least one time you said or heard...&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%2F2zgmnbtmvl2ylww7691i.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%2F2zgmnbtmvl2ylww7691i.png" alt="img1" width="300" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Including me also 🤣 So why it happened? Hmmm...Many factors "contribute" to this, example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;u&gt;Code conflict&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;&lt;u&gt;Integration error&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;&lt;u&gt;Process Manual&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And CI/CD has born to helps us fix those issues&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%2Fo55f17b8d6vrbqv58std.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%2Fo55f17b8d6vrbqv58std.png" alt="img2" width="631" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is CI/CD
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;CI/CD&lt;/strong&gt; are the short term for &lt;strong&gt;Continuous Integration&lt;/strong&gt; &amp;amp; &lt;strong&gt;Continuous Delivery/Deployment&lt;/strong&gt;. It helps the process become automated and deliver product to client in a reliable and fastest way.&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%2F02x94ic6u4o4hhvxqan4.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%2F02x94ic6u4o4hhvxqan4.png" alt="cicd-overview" width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;
CI/CD overview



&lt;h2&gt;
  
  
  Continuous Integration - CI
&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%2F0uvbhc34orh4yevvz4k9.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%2F0uvbhc34orh4yevvz4k9.png" alt="ci-overview" width="800" height="488"&gt;&lt;/a&gt;&lt;/p&gt;
CI overview



&lt;p&gt;In &lt;strong&gt;CI&lt;/strong&gt;, whenever a developer commit changes to the repository, it'll &lt;u&gt;build&lt;/u&gt; &amp;amp; &lt;u&gt;run test automatically&lt;/u&gt;. This helps ensure code is reliable and runnable, ready to integrate with the rest of the team's work. So with CI implementation, we can get the feedback right away after we commit, no need to wait the others for build and test&lt;/p&gt;

&lt;h2&gt;
  
  
  Continuous Delivery/Deployment - CD
&lt;/h2&gt;

&lt;p&gt;When your changes reach &lt;strong&gt;CD&lt;/strong&gt;, the next phase after CI, it means they’re packaged, tested, and ready to be deployed to staging or production environments.&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%2Ftiwibfknffs9qmr96mw2.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%2Ftiwibfknffs9qmr96mw2.png" alt="congrats" width="295" height="171"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;CD&lt;/strong&gt;, there are two definitions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Continuous Deliver:&lt;/strong&gt; Code is ready to deploy, but it need someone - maybe you, to click approve for deployment =&amp;gt; best suitable for &lt;u&gt;production&lt;/u&gt; environments &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Continuous Deployment:&lt;/strong&gt; The code is automatically deployed to the target environment as soon as it passes all the checks, it's hands-free deployment =&amp;gt; ideal for &lt;u&gt;staging&lt;/u&gt; environments&lt;/p&gt;&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%2Fktw2051g2nwpf8pywwfa.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%2Fktw2051g2nwpf8pywwfa.png" alt="CD overview" width="800" height="883"&gt;&lt;/a&gt;&lt;/p&gt;
CD overview



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

&lt;p&gt;We've covered the basics of CI/CD. If your team/project hasn't implemented it yet, consider doing so, you'll likely find it beneficial. In the next post, I will cover some tips/tools can use in CI/CD. &lt;/p&gt;

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

</description>
      <category>cicd</category>
    </item>
    <item>
      <title>Pod - The smallest unit in Kubernetes</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Fri, 05 Sep 2025 16:10:11 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/pod-the-smallest-unit-in-kubernetes-1d4e</link>
      <guid>https://forem.com/locnguyenpv/pod-the-smallest-unit-in-kubernetes-1d4e</guid>
      <description>&lt;p&gt;I have gone through Kubernetes architecture in the past, you can go over &lt;a href="https://dev.to/locnguyenpv/kubernetes-architecture-overview-mll"&gt;here&lt;/a&gt;. In that article, we know Kubernetes run application in the place call &lt;strong&gt;Pod&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%2Fat9n7dmbquwdp350xnqw.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%2Fat9n7dmbquwdp350xnqw.png" alt="meme" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Pod is the smallest unit in Kubernetes for deploy and run an application. Pod can contain one or many containers and they sharing the pod's resource for each others. &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%2Flerx3h8r3lwlairkmoul.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%2Flerx3h8r3lwlairkmoul.png" alt="pod_1" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;
Pod example



&lt;h2&gt;
  
  
  Deploy the first app
&lt;/h2&gt;

&lt;p&gt;I would use simple image &lt;code&gt;okteto/hello-world:node&lt;/code&gt; for test. Or you can deploy custom image to docker hub by yourself, I have written in &lt;a href="https://dev.to/locnguyenpv/multi-host-deployment-and-management-using-portainer-110l"&gt;this article&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt; 
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt; &lt;span class="c1"&gt;# Declare Pod resource&lt;/span&gt;
&lt;span class="na"&gt;metadata&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;hello-pod&lt;/span&gt; &lt;span class="c1"&gt;# The name of the pod&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;okteto/hello-world:node&lt;/span&gt; &lt;span class="c1"&gt;# Image to create the container&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;hello-pod&lt;/span&gt; &lt;span class="c1"&gt;# The name of the container&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="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt; &lt;span class="c1"&gt;# The port the app is listening on &lt;/span&gt;
          &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Access to your master node and create the file &lt;code&gt;test.yaml&lt;/code&gt; with content above. After that, run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; test.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check it deploy success or not by 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;kubectl get pod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It must show the pod with name &lt;code&gt;hello-pod&lt;/code&gt; and &lt;code&gt;status&lt;/code&gt; is running &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%2F5du3lk8kr0soyewl6hov.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%2F5du3lk8kr0soyewl6hov.png" alt="first app" width="411" height="31"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;status&lt;/code&gt; is &lt;code&gt;ContainerCreating&lt;/code&gt;, wait for a few minutes and try again because the container is being create. To ensure the image runs correctly, I will use a network proxy for expose the port. Currently, here is my app&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%2Fdgh5toplw7cukbjjebl6.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%2Fdgh5toplw7cukbjjebl6.png" alt="pod_status" width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run 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;kubectl port-forward pod/hello-pod 3000:3000 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will expose port &lt;code&gt;3000&lt;/code&gt;, listening and coordinating access to the container app on the same port. &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%2Ffhxdx5rmibxuutnulxt6.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%2Ffhxdx5rmibxuutnulxt6.png" alt="port expose" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Test it with &lt;code&gt;curl localhost:3000&lt;/code&gt;, if you receive &lt;u&gt;hello message&lt;/u&gt;...You have your first app with Kubernetes 🎉&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%2Fcxztn5jdvfaqpigh06oo.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%2Fcxztn5jdvfaqpigh06oo.png" alt="award" width="600" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;We have deploy and run simple app with pod in Kubernetes. In reality, no one deploy and run app like this 🤣, they usually use &lt;u&gt;Deployment&lt;/u&gt;, &lt;u&gt;StatefulSet&lt;/u&gt;, &lt;u&gt;DaemonSet&lt;/u&gt;. But that is another article, the goal of this post is to show you what a Pod is and its intend. &lt;/p&gt;

&lt;p&gt;In the next article, I will write how to group and manage pod by &lt;strong&gt;label&lt;/strong&gt; and &lt;strong&gt;namespace&lt;/strong&gt;&lt;/p&gt;

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

</description>
      <category>kubernetes</category>
    </item>
    <item>
      <title>YAML - Kubernetes 'Favorite' Configuration Language</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Fri, 05 Sep 2025 09:26:39 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/yaml-kubernetes-favorite-configuration-language-1l34</link>
      <guid>https://forem.com/locnguyenpv/yaml-kubernetes-favorite-configuration-language-1l34</guid>
      <description>&lt;p&gt;When work with &lt;u&gt;Kubernetes&lt;/u&gt;, we can interact with it via UI (I'll write about it in future) or configuration languages (YAML, JSON or HCL). This post will focus on &lt;strong&gt;YAML - Yet Another Markup Language&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%2F2n5iykjkwqg0b00pzkbi.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%2F2n5iykjkwqg0b00pzkbi.png" alt="YAML meme" width="800" height="683"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure
&lt;/h2&gt;

&lt;p&gt;When we import a YAML file in Kubernetes, we create a Kubernetes object which is a persistent entity in the cluster. Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pod - the place where you run your application&lt;/li&gt;
&lt;li&gt;Service - a way to expose your app&lt;/li&gt;
&lt;li&gt;Deployment - manage replicas and update&lt;/li&gt;
&lt;li&gt;ConfigMap, Secret, Ingress, etc. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We just need focus to &lt;strong&gt;four primary top-level fields&lt;/strong&gt; in YAML&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;apiVersion:&lt;/strong&gt; Specifies the version of the Kubernetes API that the object belongs to. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;apps/v1&lt;/strong&gt; for &lt;u&gt;Deployments &lt;/u&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;v1&lt;/strong&gt; for &lt;u&gt;Pods &lt;/u&gt; and &lt;u&gt;Services&lt;/u&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;kind:&lt;/strong&gt; Defines the type of Kubernetes object being created. Common examples include &lt;code&gt;Pod&lt;/code&gt;, &lt;code&gt;Deployment&lt;/code&gt;, &lt;code&gt;Service&lt;/code&gt;, &lt;code&gt;ReplicaSet&lt;/code&gt;, &lt;code&gt;Ingress&lt;/code&gt;, etc.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;metadata:&lt;/strong&gt; Contains data that identifies the object within the cluster and provides descriptive information. This typically include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;name:&lt;/strong&gt; unique name for object (require)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;namespace:&lt;/strong&gt; namespace the object belong to, default namespace is &lt;code&gt;default&lt;/code&gt; (optional)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;labels:&lt;/strong&gt; Attach label for object, it help another object can select base on this&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;annotation:&lt;/strong&gt; Often used for tools or specific configurations.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;&lt;strong&gt;spec:&lt;/strong&gt; Object configuration. The content of this section depending on the kind of object. For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For a &lt;strong&gt;Deployment&lt;/strong&gt; kind, spec defines &lt;u&gt;the number of replicas&lt;/u&gt;, &lt;u&gt;the pod template&lt;/u&gt; (including container images, ports, and resource limits), &lt;u&gt;update strategy&lt;/u&gt;, and &lt;u&gt;selectors&lt;/u&gt;.&lt;/li&gt;
&lt;li&gt;For a &lt;strong&gt;Service&lt;/strong&gt; kind, spec defines the &lt;u&gt;port mappings&lt;/u&gt;, &lt;u&gt;selector &lt;/u&gt; to find target pods, and &lt;u&gt;type of service&lt;/u&gt; (e.g., ClusterIP, NodePort, LoadBalancer).&lt;/li&gt;
&lt;li&gt;For a &lt;strong&gt;Pod&lt;/strong&gt; kind, spec defines the containers within the pod, volumes, restart policy, etc.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Example of YAML in deployment&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;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;generation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt; &lt;span class="c1"&gt;#EX: app:front-end&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;wordpress&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wp-ecommerce&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;progressDeadlineSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;600&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;revisionHistoryLimit&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt; &lt;span class="c1"&gt;#EX: app:front-end&lt;/span&gt;
  &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;rollingUpdate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;maxSurge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;25%&lt;/span&gt;
      &lt;span class="na"&gt;maxUnavailable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;25%&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RollingUpdate&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress&lt;/span&gt;  &lt;span class="c1"&gt;# ✅ This matches the selector&lt;/span&gt;
    &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;wordpress:latest&lt;/span&gt;
          &lt;span class="na"&gt;imagePullPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Always&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;wordpress&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="na"&gt;containerPort&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
              &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tcp&lt;/span&gt;
              &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
      &lt;span class="na"&gt;restartPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Always&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want run it in Kubernetes, just run in your &lt;strong&gt;master node&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; your-yaml-file.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;In reality, others people can use JSON / HCL for Kubernetes too. But for some reason, maybe it look cooler 👀 (J4F), they usually use YAML for Kubernetes. Each format has its pros and cons, use what you're comfortable with.&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%2F0zp4jmnubbb24ij9yg2r.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%2F0zp4jmnubbb24ij9yg2r.png" alt="yaml meme 2" width="500" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

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

</description>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Kubernetes Architecture Overview</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Thu, 04 Sep 2025 10:26:59 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/kubernetes-architecture-overview-mll</link>
      <guid>https://forem.com/locnguyenpv/kubernetes-architecture-overview-mll</guid>
      <description>&lt;h2&gt;
  
  
  What is Kubernetes?
&lt;/h2&gt;

&lt;p&gt;Kubernetes (or K8s) is an open-source developed by Google for container management. It can deploy on vary platform (On-premise,  Cloud, Virtual Machine). Many large companies use it for system deployment and management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is Kubernetes?
&lt;/h2&gt;

&lt;p&gt;We have several popular ways to deploy application&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traditional&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%2F48vg6iwi3cdxswgr7ddd.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%2F48vg6iwi3cdxswgr7ddd.png" alt="Traditional" width="420" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Virtualized &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%2Fdtlhhro2yy8pfsiq2b92.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%2Fdtlhhro2yy8pfsiq2b92.png" alt="Virtualized" width="572" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Container&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%2Fucxpja8qhxj0xac231wy.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%2Fucxpja8qhxj0xac231wy.png" alt="Container" width="633" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each approach has its advantages and disadvantages. Here, I will focus on the third approach (Container), which is more popular than the others. For a simple term, think of your server as a ship, and each container it carries is an isolated application ready to be deployed. Sound great, but we have another problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How we manage it? 🤔&lt;/li&gt;
&lt;li&gt;How we scale it? 🤨&lt;/li&gt;
&lt;li&gt;What happen if the "ship" drown? 😱&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%2Fpr3mi4cwbq31qzd5u9bn.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%2Fpr3mi4cwbq31qzd5u9bn.png" alt="Drown" width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we're anxious to find a solution, Google offers helpful solution - &lt;strong&gt;Kubernetes&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%2Fatrnjjfvrh2vyd4ll9dx.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%2Fatrnjjfvrh2vyd4ll9dx.png" alt="K8s hero" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How Kubernetes work?
&lt;/h2&gt;

&lt;p&gt;Kubernetes enables application grouping and management via namespaces, and its Services facilitate traffic routing to the correct applications. When a "ship" drown, it move our container to another "ship" to ensure high availability for the app. And many, many things we can work on it. And here is the "secret" behind it - architecture&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%2F0m4mymxi7jxwq7la7cai.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%2F0m4mymxi7jxwq7la7cai.png" alt="K8s architecture" width="800" height="503"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Control plane (Master node)
&lt;/h2&gt;

&lt;p&gt;It responsible for application management and high availability (HA). We never run application on it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API Server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes's heart&lt;/li&gt;
&lt;li&gt;All components must communicate through it, not directly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Control manager&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It contain vary controller for each purpose (deployment, services, 
storage, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cloud control manager&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only appear on cloud platform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Scheduler&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resource coordinator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;etcd&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A database stores the cluster's state, including configurations, node data, pod data, and service data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;P/s:&lt;/strong&gt; Backing up etcd is crucial for Kubernetes availability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Node (Worker node)
&lt;/h3&gt;

&lt;p&gt;The application will run inside this; the number of worker nodes is limited only by your budget.&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%2F7t6emwk0qrniivd2bmmm.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%2F7t6emwk0qrniivd2bmmm.png" alt="Worker nodes" width="687" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And worker node have 3 mains components:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Container Runtime Interface (CRI)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run container (docker, containerd or something else)&lt;/li&gt;
&lt;li&gt;A CRI contains one or more pods, each representing an application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Kubelet&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receive and execute from API Server&lt;/li&gt;
&lt;li&gt;Transmit system information to API server&lt;/li&gt;
&lt;li&gt;Ensure containers/pods run correct state&lt;/li&gt;
&lt;li&gt;Continuously report pod/node status to the control plane and manage the pod lifecycle on the node&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes Service Proxy&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maintain network rules for pod connectivity within and outside the cluster&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;We have go through the Kubernetes architecture and know what is it. In &lt;a href="https://dev.to/locnguyenpv/deploy-kubernetes-on-premises-from-zero-4c2i"&gt;the next post&lt;/a&gt;, I will guide you install and run Kubernetes with on-premise system.&lt;/p&gt;

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

</description>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Deploy Kubernetes On-Premises From Zero</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Sat, 16 Aug 2025 13:59:46 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/deploy-kubernetes-on-premises-from-zero-4c2i</link>
      <guid>https://forem.com/locnguyenpv/deploy-kubernetes-on-premises-from-zero-4c2i</guid>
      <description>&lt;h2&gt;
  
  
  Resource Preparation
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;IP&lt;/th&gt;
&lt;th&gt;Role&lt;/th&gt;
&lt;th&gt;RAM&lt;/th&gt;
&lt;th&gt;CPU&lt;/th&gt;
&lt;th&gt;OS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;k8s-master-1&lt;/td&gt;
&lt;td&gt;192.168.1.111&lt;/td&gt;
&lt;td&gt;Control Plane&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Ubuntu 22.04 LTS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;k8s-master-2&lt;/td&gt;
&lt;td&gt;192.168.1.112&lt;/td&gt;
&lt;td&gt;Worker&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Ubuntu 22.04 LTS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;k8s-master-3&lt;/td&gt;
&lt;td&gt;192.168.1.113&lt;/td&gt;
&lt;td&gt;Worker&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Ubuntu 22.04 LTS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Implementation Steps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Update system
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;apt&lt;/span&gt; &lt;span class="kd"&gt;update&lt;/span&gt; &lt;span class="na"&gt;-y &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;apt&lt;/span&gt; &lt;span class="kd"&gt;upgrade&lt;/span&gt; &lt;span class="na"&gt;-y
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2) Add hosts (above all 3 virtual machines)
&lt;/h3&gt;

&lt;p&gt;Open file host to config ip address&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;vim&lt;/span&gt; &lt;span class="na"&gt;/etc/hosts&lt;/span&gt;/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add those configs into file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.1.111 &lt;span class="kd"&gt;k8s&lt;/span&gt;&lt;span class="na"&gt;-master&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="m"&gt;192&lt;/span&gt;.168.1.112 &lt;span class="kd"&gt;k8s&lt;/span&gt;&lt;span class="na"&gt;-master&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="m"&gt;192&lt;/span&gt;.168.1.113 &lt;span class="kd"&gt;k8s&lt;/span&gt;&lt;span class="na"&gt;-master&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Saved and check&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="nb"&gt;ping&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;ip&lt;/span&gt;&lt;span class="na"&gt;-addr&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3) Create a new user
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;We should create/switch to another user (avoid using root) to install kubernetes&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Create &lt;code&gt;devops&lt;/code&gt; user and add to &lt;code&gt;sudo&lt;/code&gt; group&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;adduser&lt;/span&gt; &lt;span class="kd"&gt;devops&lt;/span&gt;
&lt;span class="kd"&gt;usermod&lt;/span&gt; &lt;span class="na"&gt;-aG &lt;/span&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;devops&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Switch to &lt;code&gt;devops&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;su&lt;/span&gt; &lt;span class="kd"&gt;devops&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; &lt;span class="na"&gt;/home/devops
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4) Turn off swap
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Because Kubernetes require actual RAM to ensure about performance and stable&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;# &lt;span class="kd"&gt;turn&lt;/span&gt; &lt;span class="na"&gt;off&lt;/span&gt; &lt;span class="kd"&gt;swap&lt;/span&gt; &lt;span class="kd"&gt;forever&lt;/span&gt;
&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;sed&lt;/span&gt; &lt;span class="na"&gt;-i &lt;/span&gt;&lt;span class="s1"&gt;'/swap/s/&lt;/span&gt;&lt;span class="se"&gt;^/&lt;/span&gt;&lt;span class="s1"&gt;#/'&lt;/span&gt; &lt;span class="na"&gt;/etc/fstab
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5) Download and add module into kernel
&lt;/h3&gt;

&lt;p&gt;System will download &lt;code&gt;overlay&lt;/code&gt; &amp;amp; &lt;code&gt;br_netfilter&lt;/code&gt; package manually, this is two modules which require for k8s implement&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;overlay&lt;/code&gt;: Support overlay filesystem, it's necessary for containerd to manage container image.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;br_netfilter&lt;/code&gt;: Allow filter network package on bridge network, it's very important for Kubernetes to handle traffic between container.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;modprobe&lt;/span&gt; &lt;span class="kd"&gt;overlay&lt;/span&gt;
&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;modprobe&lt;/span&gt; &lt;span class="kd"&gt;br_netfilter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make system automatically install two modules above after restart, we need modify config file by command below&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;tee&lt;/span&gt; &lt;span class="na"&gt;/etc/modules-load&lt;/span&gt;.d/containerd.conf &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;EOF&lt;/span&gt;
&lt;span class="kd"&gt;overlay&lt;/span&gt;
&lt;span class="kd"&gt;br_netfilter&lt;/span&gt;
&lt;span class="kd"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6) Config network
&lt;/h3&gt;

&lt;p&gt;Those config to make sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes can manage traffic between containers and Pods.&lt;/li&gt;
&lt;li&gt;Firewall rules can apply to traffic via bridge network.&lt;/li&gt;
&lt;li&gt;The system can routing package between nodes in cluster.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"net.bridge.bridge-nf-call-ip6tables = 1"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;tee&lt;/span&gt; &lt;span class="na"&gt;-a /etc/sysctl&lt;/span&gt;.d/kubernetes.conf
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"net.bridge.bridge-nf-call-iptables = 1"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;tee&lt;/span&gt; &lt;span class="na"&gt;-a /etc/sysctl&lt;/span&gt;.d/kubernetes.conf
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"net.ipv4.ip_forward = 1"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;tee&lt;/span&gt; &lt;span class="na"&gt;-a /etc/sysctl&lt;/span&gt;.d/kubernetes.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply &lt;code&gt;sysctl&lt;/code&gt; config&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;sysctl&lt;/span&gt; &lt;span class="na"&gt;--system
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7) Install docker
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;apt&lt;/span&gt; &lt;span class="kd"&gt;install&lt;/span&gt; &lt;span class="na"&gt;-y &lt;/span&gt;&lt;span class="nb"&gt;curl&lt;/span&gt; &lt;span class="kd"&gt;gnupg2&lt;/span&gt; &lt;span class="kd"&gt;software&lt;/span&gt;&lt;span class="na"&gt;-properties-common &lt;/span&gt;&lt;span class="kd"&gt;apt&lt;/span&gt;&lt;span class="na"&gt;-transport-https &lt;/span&gt;&lt;span class="kd"&gt;ca&lt;/span&gt;&lt;span class="na"&gt;-certificates
&lt;/span&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="nb"&gt;curl&lt;/span&gt; &lt;span class="na"&gt;-fsSL &lt;/span&gt;&lt;span class="kd"&gt;https&lt;/span&gt;://download.docker.com/linux/ubuntu/gpg &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;gpg&lt;/span&gt; &lt;span class="na"&gt;--dearmour -o /etc/apt/trusted&lt;/span&gt;.gpg.d/docker.gpg
&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;add&lt;/span&gt;&lt;span class="na"&gt;-apt-repository &lt;/span&gt;&lt;span class="s2"&gt;"deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  8) Install &amp;amp; config containerd
&lt;/h3&gt;

&lt;p&gt;This is container runtime which is use by Kubernetes for manage container&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;apt&lt;/span&gt; &lt;span class="kd"&gt;install&lt;/span&gt; &lt;span class="na"&gt;-y &lt;/span&gt;&lt;span class="kd"&gt;containerd&lt;/span&gt;.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installed, we need config &lt;code&gt;containerd&lt;/code&gt; use &lt;strong&gt;Systemd&lt;/strong&gt; to manage resource group (cgroup) =&amp;gt; This make resource management become consistent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;containerd&lt;/span&gt; &lt;span class="kd"&gt;config&lt;/span&gt; &lt;span class="kd"&gt;default&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;tee&lt;/span&gt; &lt;span class="na"&gt;/etc/containerd/config&lt;/span&gt;.toml &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="na"&gt;/dev/null &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;sed&lt;/span&gt; &lt;span class="na"&gt;-i &lt;/span&gt;&lt;span class="s1"&gt;'s/SystemdCgroup = false/SystemdCgroup = true/g'&lt;/span&gt; &lt;span class="na"&gt;/etc/containerd/config&lt;/span&gt;.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Restart &lt;code&gt;containerd&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;systemctl&lt;/span&gt; &lt;span class="kd"&gt;restart&lt;/span&gt; &lt;span class="kd"&gt;containerd&lt;/span&gt;
&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;systemctl&lt;/span&gt; &lt;span class="kd"&gt;enable&lt;/span&gt; &lt;span class="kd"&gt;containerd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  9) Install Kubernetes package
&lt;/h3&gt;

&lt;p&gt;Config to download from legit source&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;tee&lt;/span&gt; &lt;span class="na"&gt;/etc/apt/sources&lt;/span&gt;.list.d/kubernetes.list
&lt;span class="nb"&gt;curl&lt;/span&gt; &lt;span class="na"&gt;-fsSL &lt;/span&gt;&lt;span class="kd"&gt;https&lt;/span&gt;://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;gpg&lt;/span&gt; &lt;span class="na"&gt;--dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring&lt;/span&gt;.gpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install packages (kubelet, kubeadm, kubectl)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;apt&lt;/span&gt; &lt;span class="kd"&gt;install&lt;/span&gt; &lt;span class="na"&gt;-y &lt;/span&gt;&lt;span class="kd"&gt;kubelet&lt;/span&gt; &lt;span class="kd"&gt;kubeadm&lt;/span&gt; &lt;span class="kd"&gt;kubectl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For avoid auto upgrade version =&amp;gt; Ensure package versions are consistent.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;apt&lt;/span&gt;&lt;span class="na"&gt;-mark &lt;/span&gt;&lt;span class="kd"&gt;hold&lt;/span&gt; &lt;span class="kd"&gt;kubelet&lt;/span&gt; &lt;span class="kd"&gt;kubeadm&lt;/span&gt; &lt;span class="kd"&gt;kubectl&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Deploy model (1 master - 2 worker)
&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%2Ftmpjtzh0r2bzmt0f0e47.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%2Ftmpjtzh0r2bzmt0f0e47.png" alt="1master2workers" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;
Standard model



&lt;h3&gt;
  
  
  Init Kubernetes on master node
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;kubeadm&lt;/span&gt; &lt;span class="kd"&gt;init&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="na"&gt;-p &lt;/span&gt;$HOME/.kube
&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;cp&lt;/span&gt; &lt;span class="na"&gt;-i /etc/kubernetes/admin&lt;/span&gt;.conf $HOME/.kube/config
&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;chown&lt;/span&gt; $&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;id&lt;/span&gt; &lt;span class="na"&gt;-u&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;:$&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;id&lt;/span&gt; &lt;span class="na"&gt;-g&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; $HOME/.kube/config
&lt;span class="kd"&gt;kubectl&lt;/span&gt; &lt;span class="kd"&gt;apply&lt;/span&gt; &lt;span class="na"&gt;-f &lt;/span&gt;&lt;span class="kd"&gt;https&lt;/span&gt;://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the initial setup, it'll have command follow format below - use it to add &lt;strong&gt;worker&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;sudo&lt;/span&gt; &lt;span class="kd"&gt;kubeadm&lt;/span&gt; &lt;span class="kd"&gt;join&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;ip&lt;/span&gt;&lt;span class="na"&gt;-master-node&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;:6443 &lt;span class="na"&gt;--token &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;your_token&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="na"&gt;--discovery-token-ca-cert-hash &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kd"&gt;your_sha&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Add worker node
&lt;/h2&gt;

&lt;p&gt;Copy command from &lt;strong&gt;master node&lt;/strong&gt; and paste it to machine where role determine is &lt;strong&gt;worker&lt;/strong&gt; role (maybe you need to run it with &lt;code&gt;sudo&lt;/code&gt;)&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify
&lt;/h2&gt;

&lt;p&gt;Run &lt;code&gt;kubectl get node -o wide&lt;/code&gt; in &lt;strong&gt;master node&lt;/strong&gt; to check &lt;strong&gt;worker&lt;/strong&gt; added&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%2Fysnih0l0lmtcqi7rdi7n.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%2Fysnih0l0lmtcqi7rdi7n.png" alt="verify-workers" width="800" height="86"&gt;&lt;/a&gt;&lt;/p&gt;
Example output



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

&lt;p&gt;Just one of over 35 ways to install Kubernetes. In the future, to add more workers to your system, simply run&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;kubeadm &lt;span class="nb"&gt;join&lt;/span&gt; &amp;lt;ip-master-node&amp;gt;:6443 &lt;span class="nt"&gt;--token&lt;/span&gt; &amp;lt;your_token&amp;gt; &lt;span class="nt"&gt;--discovery-token-ca-cert-hash&lt;/span&gt; &amp;lt;your_sha&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next post of series, I will show you how to use cloud for Kubernetes&lt;br&gt;
Happy Coding!&lt;/p&gt;

</description>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Multi-host deployment and management using Portainer</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Sat, 26 Jul 2025 18:22:16 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/multi-host-deployment-and-management-using-portainer-110l</link>
      <guid>https://forem.com/locnguyenpv/multi-host-deployment-and-management-using-portainer-110l</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;I will simulate a multi-host environment using DinD and then use Portainer for deployment and management.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Installed Docker (If you don't have it, follow the instructions for &lt;a href="https://dev.to/locnguyenpv/install-docker-on-window-5cg0"&gt;Windows&lt;/a&gt; or &lt;a href="https://dev.to/locnguyenpv/install-docker-on-linux-2k1k"&gt;Linux&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Read &lt;a href="https://dev.to/locnguyenpv/deploy-microservice-with-docker-from-scratch-p1-46h7"&gt;previous post&lt;/a&gt; to know what I done&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;I will migrate from a single-host to a multi-host architecture.&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%2Fsurc46qa14nqxybu23p4.gif" 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%2Fsurc46qa14nqxybu23p4.gif" alt="Architecture" width="1699" height="701"&gt;&lt;/a&gt;&lt;/p&gt;
Multi-host



&lt;h2&gt;
  
  
  Install Portainer
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Register 3 nodes free for portainer&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the &lt;a href="https://www.portainer.io/take-3" rel="noopener noreferrer"&gt;link&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Fill out the form&lt;/li&gt;
&lt;li&gt;Get an email and save the license key&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%2Fbv2ol8mp20vxkykktind.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%2Fbv2ol8mp20vxkykktind.png" alt="License Key" width="800" height="243"&gt;&lt;/a&gt;&lt;/p&gt;
Email license key



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Create docker volume for portainer&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;volume&lt;/span&gt; &lt;span class="kd"&gt;create&lt;/span&gt; &lt;span class="kd"&gt;portainer_data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Create network&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;network&lt;/span&gt; &lt;span class="kd"&gt;create&lt;/span&gt; &lt;span class="kd"&gt;portainer&lt;/span&gt;&lt;span class="na"&gt;-network
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Run portainer with specify network&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="nb"&gt;run&lt;/span&gt; &lt;span class="na"&gt;-d -p &lt;/span&gt;&lt;span class="m"&gt;8000&lt;/span&gt;:8000 &lt;span class="na"&gt;-p &lt;/span&gt;&lt;span class="m"&gt;9443&lt;/span&gt;:9443 &lt;span class="na"&gt;--name &lt;/span&gt;&lt;span class="kd"&gt;portainer&lt;/span&gt; &lt;span class="na"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kd"&gt;always&lt;/span&gt; &lt;span class="na"&gt;--network &lt;/span&gt;&lt;span class="kd"&gt;portainer&lt;/span&gt;&lt;span class="na"&gt;-network -v /var/run/docker&lt;/span&gt;.sock:/var/run/docker.sock &lt;span class="na"&gt;-v &lt;/span&gt;&lt;span class="kd"&gt;portainer_data&lt;/span&gt;:/data &lt;span class="kd"&gt;portainer&lt;/span&gt;&lt;span class="na"&gt;/portainer-ee&lt;/span&gt;&lt;span class="nl"&gt;:lts&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Access portainer via &lt;u&gt;localhost:9443/#!/endpoints&lt;/u&gt; to create account&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%2F7yxetbl08cc31lnoglp2.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%2F7yxetbl08cc31lnoglp2.png" alt="register account" width="693" height="689"&gt;&lt;/a&gt;&lt;/p&gt;
Register Account



&lt;p&gt;&lt;strong&gt;Step 6:&lt;/strong&gt; Register license key you get from email &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%2Fgp7lur6pfop6ds67g7a3.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%2Fgp7lur6pfop6ds67g7a3.png" alt="register license key" width="800" height="208"&gt;&lt;/a&gt;&lt;/p&gt;
Register key



&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%2Fix2uqwm1vrecdvqigqi2.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%2Fix2uqwm1vrecdvqigqi2.png" alt="home page" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;
Home page



&lt;h2&gt;
  
  
  Push image to docker registry
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Open terminal and run (it will will be prompted to enter Docker ID (username) and password interactively)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;login&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Tagging image with the following format &lt;code&gt;&amp;lt;your-username-docker&amp;gt;/&amp;lt;application-name&amp;gt;:&amp;lt;version&amp;gt;&lt;/code&gt;. Your username should be the same display on docker&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%2Fgpzzb2bifi1x0w5cgljl.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%2Fgpzzb2bifi1x0w5cgljl.png" alt="docker hub" width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For me, username is &lt;code&gt;locnguyenpv&lt;/code&gt;&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;tag&lt;/span&gt; &lt;span class="kd"&gt;project&lt;/span&gt;&lt;span class="na"&gt;-management/client-app &lt;/span&gt;&lt;span class="kd"&gt;locnguyenpv&lt;/span&gt;&lt;span class="na"&gt;/client-app&lt;/span&gt;&lt;span class="nl"&gt;:v&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;tag&lt;/span&gt; &lt;span class="kd"&gt;project&lt;/span&gt;&lt;span class="na"&gt;-management/project-service &lt;/span&gt;&lt;span class="kd"&gt;locnguyenpv&lt;/span&gt;&lt;span class="na"&gt;/project-service&lt;/span&gt;&lt;span class="nl"&gt;:v&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;tag&lt;/span&gt; &lt;span class="kd"&gt;project&lt;/span&gt;&lt;span class="na"&gt;-management/user-service &lt;/span&gt;&lt;span class="kd"&gt;locnguyenpv&lt;/span&gt;&lt;span class="na"&gt;/user-service&lt;/span&gt;&lt;span class="nl"&gt;:v&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;tag&lt;/span&gt; &lt;span class="kd"&gt;project&lt;/span&gt;&lt;span class="na"&gt;-management/task-service &lt;/span&gt;&lt;span class="kd"&gt;locnguyenpv&lt;/span&gt;&lt;span class="na"&gt;/task-service&lt;/span&gt;&lt;span class="nl"&gt;:v&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Push image to registry by tag&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;push&lt;/span&gt; &lt;span class="kd"&gt;locnguyenpv&lt;/span&gt;&lt;span class="na"&gt;/client-app&lt;/span&gt;&lt;span class="nl"&gt;:v&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;push&lt;/span&gt; &lt;span class="kd"&gt;locnguyenpv&lt;/span&gt;&lt;span class="na"&gt;/project-service&lt;/span&gt;&lt;span class="nl"&gt;:v&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;push&lt;/span&gt; &lt;span class="kd"&gt;locnguyenpv&lt;/span&gt;&lt;span class="na"&gt;/user-service&lt;/span&gt;&lt;span class="nl"&gt;:v&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;push&lt;/span&gt; &lt;span class="kd"&gt;locnguyenpv&lt;/span&gt;&lt;span class="na"&gt;/task-service&lt;/span&gt;&lt;span class="nl"&gt;:v&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Connect to DinD
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Create 2 DinD, one for FE, one for BE&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FE:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="nb"&gt;run&lt;/span&gt; &lt;span class="na"&gt;--privileged -d --name &lt;/span&gt;&lt;span class="kd"&gt;project&lt;/span&gt;&lt;span class="na"&gt;-management-fe --network &lt;/span&gt;&lt;span class="kd"&gt;portainer&lt;/span&gt;&lt;span class="na"&gt;-network -p &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;:80 &lt;span class="na"&gt;-p &lt;/span&gt;&lt;span class="m"&gt;9002&lt;/span&gt;:9001 &lt;span class="na"&gt;-p &lt;/span&gt;&lt;span class="m"&gt;2377&lt;/span&gt;:2375 &lt;span class="kd"&gt;docker&lt;/span&gt;&lt;span class="nl"&gt;:dind&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;BE:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="nb"&gt;run&lt;/span&gt; &lt;span class="na"&gt;--privileged -d --name &lt;/span&gt;&lt;span class="kd"&gt;project&lt;/span&gt;&lt;span class="na"&gt;-management-be --network &lt;/span&gt;&lt;span class="kd"&gt;portainer&lt;/span&gt;&lt;span class="na"&gt;-network -p &lt;/span&gt;&lt;span class="m"&gt;2376&lt;/span&gt;:2375 &lt;span class="na"&gt;-p &lt;/span&gt;&lt;span class="m"&gt;9001&lt;/span&gt;:9001 &lt;span class="na"&gt;-p &lt;/span&gt;&lt;span class="m"&gt;9099&lt;/span&gt;:9099 &lt;span class="kd"&gt;docker&lt;/span&gt;&lt;span class="nl"&gt;:dind&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; SSH into each DinD to install Portainer Agent&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FE:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;exec&lt;/span&gt; &lt;span class="na"&gt;-it &lt;/span&gt;&lt;span class="kd"&gt;project&lt;/span&gt;&lt;span class="na"&gt;-management-fe &lt;/span&gt;&lt;span class="kd"&gt;sh&lt;/span&gt;
&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="nb"&gt;run&lt;/span&gt; &lt;span class="na"&gt;-d &lt;/span&gt;\
  &lt;span class="na"&gt;-p &lt;/span&gt;&lt;span class="m"&gt;9001&lt;/span&gt;:9001 \
  &lt;span class="na"&gt;--name &lt;/span&gt;&lt;span class="kd"&gt;portainer_agent&lt;/span&gt; \
  &lt;span class="na"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kd"&gt;always&lt;/span&gt; \
  &lt;span class="na"&gt;-v /var/run/docker&lt;/span&gt;.sock:/var/run/docker.sock \
  &lt;span class="na"&gt;-v /var/lib/docker/volumes&lt;/span&gt;:/var/lib/docker/volumes \
  &lt;span class="na"&gt;-v &lt;/span&gt;/:/host \
  &lt;span class="kd"&gt;portainer&lt;/span&gt;&lt;span class="na"&gt;/agent&lt;/span&gt;:2.27.9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;BE:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight batchfile"&gt;&lt;code&gt;&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="kd"&gt;exec&lt;/span&gt; &lt;span class="na"&gt;-it &lt;/span&gt;&lt;span class="kd"&gt;project&lt;/span&gt;&lt;span class="na"&gt;-management-be &lt;/span&gt;&lt;span class="kd"&gt;sh&lt;/span&gt;
&lt;span class="kd"&gt;docker&lt;/span&gt; &lt;span class="nb"&gt;run&lt;/span&gt; &lt;span class="na"&gt;-d &lt;/span&gt;\
  &lt;span class="na"&gt;-p &lt;/span&gt;&lt;span class="m"&gt;9001&lt;/span&gt;:9001 \
  &lt;span class="na"&gt;--name &lt;/span&gt;&lt;span class="kd"&gt;portainer_agent&lt;/span&gt; \
  &lt;span class="na"&gt;--restart&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kd"&gt;always&lt;/span&gt; \
  &lt;span class="na"&gt;-v /var/run/docker&lt;/span&gt;.sock:/var/run/docker.sock \
  &lt;span class="na"&gt;-v /var/lib/docker/volumes&lt;/span&gt;:/var/lib/docker/volumes \
  &lt;span class="na"&gt;-v &lt;/span&gt;/:/host \
  &lt;span class="kd"&gt;portainer&lt;/span&gt;&lt;span class="na"&gt;/agent&lt;/span&gt;:2.27.9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Connect DinD with Portainer&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%2Fq2x7r4do238hvugkywa3.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%2Fq2x7r4do238hvugkywa3.png" alt="Environment Dashboard" width="800" height="405"&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%2Fq6o388r7l9xj0frbd3q5.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%2Fq6o388r7l9xj0frbd3q5.png" alt="select environment" width="800" height="405"&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%2Fjqzx65967qz0agtk6ozk.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%2Fjqzx65967qz0agtk6ozk.png" alt="connect env" width="800" height="405"&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%2Fg30zqv0xnlmenpfam927.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%2Fg30zqv0xnlmenpfam927.png" alt="connect success" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;
Connect Success



&lt;h2&gt;
  
  
  Update docker-compose
&lt;/h2&gt;

&lt;p&gt;Now that I've pushed the image to the Docker registry, I can use it instead of building from source. &lt;u&gt;Replace build from source to pull image from registry&lt;/u&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FE:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;client-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;locnguyenpv/client-app:v1&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;80:80"&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;BE:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mysql-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:latest&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-container&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysql-data:/var/lib/mysql&lt;/span&gt;  &lt;span class="c1"&gt;# create space for persistence data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./database:/docker-entrypoint-initdb.d&lt;/span&gt; &lt;span class="c1"&gt;# Mount init file into container &lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Check every 10s to make sure it work fine&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-SHELL"&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="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-u&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-p$MYSQL_PASSWORD&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ping&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-h&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;||&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;exit&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1"&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;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&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;start_period&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;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;internal-network&lt;/span&gt;

  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:latest&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;nginx-gateway&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;9099:9099"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx.conf:/etc/nginx/nginx.conf:ro&lt;/span&gt; &lt;span class="c1"&gt;# Mount nginx config from local to container&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="c1"&gt;# Start condition&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;project-service&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;user-service&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;task-service&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;internal-network&lt;/span&gt;   &lt;span class="c1"&gt;# Virtual network&lt;/span&gt;
  &lt;span class="na"&gt;project-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;locnguyenpv/project-service:v1&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;project-service-container&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;8081:8081"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql-service&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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-service&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;internal-network&lt;/span&gt; &lt;span class="c1"&gt;# Virtual network&lt;/span&gt;
  &lt;span class="na"&gt;user-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;locnguyenpv/user-service:v1&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;user-service-container&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;8082:8082"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql-service&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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-service&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;internal-network&lt;/span&gt; &lt;span class="c1"&gt;# Virtual network&lt;/span&gt;
  &lt;span class="na"&gt;task-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;locnguyenpv/task-service:v1&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;task-service-container&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;8083:8083"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql-service&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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-service&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;internal-network&lt;/span&gt; &lt;span class="c1"&gt;# Virtual network&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;internal-network&lt;/span&gt;&lt;span class="pi"&gt;:&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;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;internal-network&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Deploy to DinD
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Go to home page and choose DinD &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%2Fyjxdexh4z0ww0jakrjgu.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%2Fyjxdexh4z0ww0jakrjgu.png" alt="home page" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Choose stack &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%2Fg2oefqc2bnwoxagwu8wa.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%2Fg2oefqc2bnwoxagwu8wa.png" alt="stack" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Add new stack&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%2Ftpkzga6j9kustn4p69o4.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%2Ftpkzga6j9kustn4p69o4.png" alt="add stack" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Copy &amp;amp; paste docker-compose file into editor&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%2Fdpvqk3vae6krz99hz7e5.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%2Fdpvqk3vae6krz99hz7e5.png" alt="stack editor" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Deploy&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%2Fl6o48g1bt7fpspy6goar.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%2Fl6o48g1bt7fpspy6goar.png" alt="deploy stack" width="800" height="405"&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%2Fo65xcw91ctxl1ijf876d.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%2Fo65xcw91ctxl1ijf876d.png" alt="deploy success" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;
Deploy success



&lt;p&gt;Replace those steps for other DinD. All set!&lt;/p&gt;

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

&lt;p&gt;I just show you the way how to simulate multi-host environment by DinD. After that, use Portainer for management and deployment.&lt;/p&gt;

&lt;p&gt;Happy Coding &lt;/p&gt;

</description>
      <category>docker</category>
    </item>
    <item>
      <title>Docker-in-Docker (DinD)</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Sat, 26 Jul 2025 13:07:51 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/docker-in-docker-dind-1n18</link>
      <guid>https://forem.com/locnguyenpv/docker-in-docker-dind-1n18</guid>
      <description>&lt;h2&gt;
  
  
  What is DinD?
&lt;/h2&gt;

&lt;p&gt;For a simple terms, I will use docker to run another docker in docker 🤪 &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%2Fbdvgrut48ktkmfsf3anr.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%2Fbdvgrut48ktkmfsf3anr.png" alt="DinD" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;
DinD Methodology



&lt;h2&gt;
  
  
  Why is it?
&lt;/h2&gt;

&lt;p&gt;It can be used in many cases, but I use it to simulate a multi-host environment on a single physical machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to do it?
&lt;/h2&gt;

&lt;p&gt;Open your command line and run it&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;--privileged&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; &amp;lt;your-docker-name&amp;gt; docker:dind 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it, now I have a "virtual" of virtual machine to deploy and run the image&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Warning ❗❗❗:&lt;/strong&gt; Because it run with &lt;code&gt;--privileged&lt;/code&gt;, so it's only use for dev/test environment =&amp;gt; &lt;strong&gt;Never use in production&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>docker</category>
    </item>
    <item>
      <title>Deploy microservice with Docker from scratch - P2</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Sun, 20 Jul 2025 09:15:03 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/deploy-microservice-with-docker-from-scratch-p2-4hal</link>
      <guid>https://forem.com/locnguyenpv/deploy-microservice-with-docker-from-scratch-p2-4hal</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Use Docker Compose to run and deploy a project's Dockerfiles as microservices.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker-compose
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://dev.to/locnguyenpv/deploy-microservice-with-docker-from-scratch-p1-46h7"&gt;previous post&lt;/a&gt;, I have an overview of the project and its functionality. In this post, I'll delve into implementation details. I will go through each layer of the project&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Client App (FE)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;client-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./client-app&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;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;client-app-container&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;80:80"&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt; &lt;span class="c1"&gt;# Auto restart when it fail&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nginx&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:latest&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;nginx-gateway&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;9099:9099"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx.conf:/etc/nginx/nginx.conf:ro&lt;/span&gt; &lt;span class="c1"&gt;# Mount nginx config from local to container&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="c1"&gt;# Start condition&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;project-service&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;user-service&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;task-service&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;internal-network&lt;/span&gt;   &lt;span class="c1"&gt;# Virtual network&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Server (BE)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="na"&gt;project-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./project-service&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;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;project-service-container&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;8081:8081"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql-service&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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-service&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;internal-network&lt;/span&gt; &lt;span class="c1"&gt;# Virtual network&lt;/span&gt;
 &lt;span class="err"&gt; &lt;/span&gt;&lt;span class="na"&gt;user-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./user-service&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;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user-service-container&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;8082:8082"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql-service&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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-service&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;internal-network&lt;/span&gt; &lt;span class="c1"&gt;# Virtual network&lt;/span&gt;
  &lt;span class="na"&gt;task-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./task-service&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;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;task-service-container&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;8083:8083"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql-service&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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-service&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;internal-network&lt;/span&gt; &lt;span class="c1"&gt;# Virtual network&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Database (MySQL)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;mysql-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:latest&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-container&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysql-data:/var/lib/mysql&lt;/span&gt;  &lt;span class="c1"&gt;# create space for persistence data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./database:/docker-entrypoint-initdb.d&lt;/span&gt; &lt;span class="c1"&gt;# Mount init file into container &lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Check every 10s to make sure it work fine&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-SHELL"&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="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-u&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-p$MYSQL_PASSWORD&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ping&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-h&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;||&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;exit&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1"&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;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&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;start_period&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;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;internal-network&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Full docker-compose file
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mysql-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql:latest&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-container&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mysql-data:/var/lib/mysql&lt;/span&gt;  &lt;span class="c1"&gt;# create space for persistence data&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./database:/docker-entrypoint-initdb.d&lt;/span&gt; &lt;span class="c1"&gt;# Mount init file into container &lt;/span&gt;
    &lt;span class="na"&gt;healthcheck&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Check every 10s to make sure it work fine&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-SHELL"&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="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-u&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;root&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-p$MYSQL_PASSWORD&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;ping&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;-h&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;||&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;exit&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;1"&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;retries&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&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;start_period&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;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;internal-network&lt;/span&gt;

  &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:latest&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;nginx-gateway&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;9099:9099"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./nginx.conf:/etc/nginx/nginx.conf:ro&lt;/span&gt; &lt;span class="c1"&gt;# Mount nginx config from local to container&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="c1"&gt;# Start condition&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;project-service&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;user-service&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;task-service&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;internal-network&lt;/span&gt;   &lt;span class="c1"&gt;# Virtual network&lt;/span&gt;
  &lt;span class="na"&gt;project-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./project-service&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;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;project-service-container&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;8081:8081"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql-service&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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-service&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;internal-network&lt;/span&gt; &lt;span class="c1"&gt;# Virtual network&lt;/span&gt;
  &lt;span class="na"&gt;user-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./user-service&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;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;user-service-container&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;8082:8082"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql-service&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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-service&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;internal-network&lt;/span&gt; &lt;span class="c1"&gt;# Virtual network&lt;/span&gt;
  &lt;span class="na"&gt;task-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./task-service&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;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;task-service-container&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;8083:8083"&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql-service&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;123123&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-service&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="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;internal-network&lt;/span&gt; &lt;span class="c1"&gt;# Virtual network&lt;/span&gt;

  &lt;span class="na"&gt;client-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; 
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./client-app&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;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;client-app-container&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;80:80"&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt; &lt;span class="c1"&gt;# Auto restart when it fail&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;internal-network&lt;/span&gt;&lt;span class="pi"&gt;:&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;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;internal-network&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to run
&lt;/h2&gt;

&lt;p&gt;After finished docker-compose, open terminal 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 compose up &lt;span class="nt"&gt;-d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will build, create, and start the services defined in a docker-compose.yml file for you.&lt;/p&gt;

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

&lt;p&gt;In this post, I focused on the overall structure and main services. In an upcoming topic, I’ll dive deeper into how healthchecks, volumes, and networks work to further improve reliability and maintainability in your deployments.&lt;br&gt;
Happy Coding !!!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
    </item>
    <item>
      <title>Deploy microservice with Docker from scratch - P1</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Sun, 20 Jul 2025 09:14:27 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/deploy-microservice-with-docker-from-scratch-p1-46h7</link>
      <guid>https://forem.com/locnguyenpv/deploy-microservice-with-docker-from-scratch-p1-46h7</guid>
      <description>&lt;p&gt;In this series, I will build and deploy a simple microservice app with docker. Everything begin from scratch 😎&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Installed Docker (If you don't have it, follow the instructions for &lt;a href="https://dev.to/locnguyenpv/install-docker-on-window-5cg0"&gt;Windows&lt;/a&gt; or &lt;a href="https://dev.to/locnguyenpv/install-docker-on-linux-2k1k"&gt;Linux&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Tech stack
&lt;/h2&gt;

&lt;p&gt;Right here, I will use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FE&lt;/strong&gt;: Angular&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BE&lt;/strong&gt;: Java&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DB&lt;/strong&gt;: MySQL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;P/s:&lt;/strong&gt; You can use your preferred stack, but scripting a &lt;code&gt;docker-image&lt;/code&gt; build may differ slightly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&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%2F3832jj6nut8b7q167le1.gif" 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%2F3832jj6nut8b7q167le1.gif" alt="Architecture" width="1497" height="594"&gt;&lt;/a&gt;&lt;/p&gt;
Architecture



&lt;p&gt;The system will have 6 components:&lt;br&gt;
1) &lt;strong&gt;Client app:&lt;/strong&gt; Interact BE via API &lt;br&gt;
2) &lt;strong&gt;Nginx (gateway):&lt;/strong&gt; Reverse proxy and load balancer&lt;br&gt;
3) &lt;strong&gt;Project Service:&lt;/strong&gt; Handle request relate to project&lt;br&gt;
4) &lt;strong&gt;Task Service:&lt;/strong&gt; Handle request relate to task&lt;br&gt;
5) &lt;strong&gt;User Service:&lt;/strong&gt; Handle request relate to user&lt;br&gt;
6) &lt;strong&gt;Database Layer (MySQL):&lt;/strong&gt; Data persistence&lt;/p&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/
├── client-app/ 
│   ├── src/
│   └── Dockerfile 
├── project-service/
│   ├── src/ 
│   └── Dockerfile 
├── task-service/ 
│   ├── src/
│   └── Dockerfile
├── user-service/ 
│   ├── src/
│   └── Dockerfile
├── docker-compose
└── nginx.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;❗Important thing:&lt;/strong&gt; Did you notice every service have each own &lt;u&gt;Dockerfile&lt;/u&gt; 🤔 &lt;/p&gt;

&lt;h2&gt;
  
  
  Docker file
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;FE (AngularJS)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;FROM node:20-alpine AS builder&lt;/span&gt;
&lt;span class="s"&gt;WORKDIR /app&lt;/span&gt;
&lt;span class="s"&gt;COPY package*.json ./&lt;/span&gt;
&lt;span class="s"&gt;COPY angular*.json ./&lt;/span&gt;
&lt;span class="s"&gt;COPY tsconfig*.json ./&lt;/span&gt;
&lt;span class="s"&gt;RUN npm install --legacy-peer-deps&lt;/span&gt;
&lt;span class="s"&gt;COPY . .&lt;/span&gt;
&lt;span class="s"&gt;RUN npm run build -- --configuration production&lt;/span&gt;

&lt;span class="s"&gt;FROM nginx:alpine AS production&lt;/span&gt;
&lt;span class="s"&gt;COPY --from=builder /app/dist/client-app/browser/ /usr/share/nginx/html&lt;/span&gt;

&lt;span class="s"&gt;EXPOSE &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;
&lt;span class="s"&gt;CMD ["nginx", "-g", "daemon off;"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;BE (Java)
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;FROM maven:latest AS build&lt;/span&gt;
&lt;span class="s"&gt;WORKDIR /projectservice&lt;/span&gt;
&lt;span class="s"&gt;COPY . .&lt;/span&gt;
&lt;span class="s"&gt;RUN mvn clean package -DskipTests&lt;/span&gt;

&lt;span class="s"&gt;FROM eclipse-temurin:21-jdk-alpine&lt;/span&gt;
&lt;span class="s"&gt;WORKDIR /projectservice&lt;/span&gt;
&lt;span class="s"&gt;COPY --from=build /projectservice/target/*.jar app.jar&lt;/span&gt;
&lt;span class="s"&gt;EXPOSE &lt;/span&gt;&lt;span class="m"&gt;8081&lt;/span&gt;
&lt;span class="s"&gt;ENTRYPOINT ["java", "-jar", "/projectservice/app.jar"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As mentioned above, each service will have its own Dockerfile so remember &lt;u&gt;clone and update&lt;/u&gt; it for each service.&lt;/p&gt;

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

&lt;p&gt;Okay, I have an overview of the project and its functionality. In the &lt;a href="https://dev.to/locnguyenpv/deploy-microservice-with-docker-from-scratch-p2-4hal"&gt;next post&lt;/a&gt;, I'll delve into implementation details. &lt;/p&gt;

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

</description>
      <category>docker</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Install Docker on Linux</title>
      <dc:creator>Luke</dc:creator>
      <pubDate>Sun, 20 Jul 2025 09:14:02 +0000</pubDate>
      <link>https://forem.com/locnguyenpv/install-docker-on-linux-2k1k</link>
      <guid>https://forem.com/locnguyenpv/install-docker-on-linux-2k1k</guid>
      <description>&lt;h2&gt;
  
  
  1) Update system
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Make sure your system are using latest version of everything
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install packages help &lt;code&gt;apt&lt;/code&gt; download package via HTTPS
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;apt-transport-https ca-certificates curl software-properties-common &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2) Install Docker
&lt;/h2&gt;

&lt;p&gt;Docker can be installed using either a quick method or a more detailed one.&lt;/p&gt;

&lt;h3&gt;
  
  
  The quick one
&lt;/h3&gt;



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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Another way
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add Docker's GPG official
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://download.docker.com/linux/ubuntu/gpg |sudo gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/share/keyrings/docker-archive-keyring.gpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Add Docker repository into APT source list
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;lsb_release &lt;span class="nt"&gt;-cs&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; stable"&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/apt/sources.list.d/docker.list&amp;gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install Docker Engine
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  3) Check Docker status
&lt;/h2&gt;

&lt;p&gt;If it's fine, you'll see &lt;code&gt;active (running)&lt;/code&gt; status&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;systemctl status docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4) Allow Docker run without &lt;code&gt;sudo&lt;/code&gt;
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
newgrp docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5) Test Docker
&lt;/h2&gt;

&lt;p&gt;If you see welcome message, it mean Docker install successfully&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 hello-world

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6) Install Docker Compose (Optional)
&lt;/h2&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;curl &lt;span class="nt"&gt;-L&lt;/span&gt; &lt;span class="s2"&gt;"https://github.com/docker/compose/releases/download/1.29.2/docker-compose-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/local/bin/docker-compose &lt;span class="nb"&gt;sudo chmod&lt;/span&gt; +x /usr/local/bin/docker-compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your Linux system ready to go!&lt;br&gt;
Happy Coding.  &lt;/p&gt;

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