<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: SandeepKomal</title>
    <description>The latest articles on DEV Community by SandeepKomal (@sandeepkomal).</description>
    <link>https://dev.to/sandeepkomal</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1284504%2F326ef034-12c3-4299-b7a7-3cd7c90b47cb.jpeg</url>
      <title>DEV Community: SandeepKomal</title>
      <link>https://dev.to/sandeepkomal</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sandeepkomal"/>
    <language>en</language>
    <item>
      <title>I turned my GitHub year into a 3D solar system for my profile README</title>
      <dc:creator>SandeepKomal</dc:creator>
      <pubDate>Fri, 16 Oct 2026 19:44:25 +0000</pubDate>
      <link>https://dev.to/sandeepkomal/i-turned-my-github-year-into-a-3d-solar-system-for-my-profile-readme-kgj</link>
      <guid>https://dev.to/sandeepkomal/i-turned-my-github-year-into-a-3d-solar-system-for-my-profile-readme-kgj</guid>
      <description>&lt;p&gt;GitHub's contribution graph is a grid of green squares. It's useful, but it doesn't tell much of a story, and everyone's looks the same.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;&lt;a href="https://github.com/SandeepKomal/Git3D-Universe" rel="noopener noreferrer"&gt;Git3D Universe&lt;/a&gt;&lt;/strong&gt;: a free GitHub Action that turns your year of contributions into a small 3D solar system, drawn as one self-contained SVG for your profile README.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe1manhdjeur0a80veigq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe1manhdjeur0a80veigq.png" alt="Git3D Universe at night: a 3D pie of month wedges round a glowing core, with repositories orbiting as planets" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⭐ &lt;strong&gt;Source (MIT):&lt;/strong&gt; &lt;a href="https://github.com/SandeepKomal/Git3D-Universe" rel="noopener noreferrer"&gt;github.com/SandeepKomal/Git3D-Universe&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in the picture
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;🥧 Your year as a 3D pie.&lt;/strong&gt; One wedge per month, read clockwise like a clock face. Each wedge rises with that month's contributions and carries its name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🏆 Your busiest month in gold.&lt;/strong&gt; It's outlined, with its name and total floating above the pie.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🪐 Your repos as planets.&lt;/strong&gt; Your top repositories orbit the pie, sized by stars, passing behind it on the far side and in front of it on the near side. The most-starred one gets rings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;📊 Your contribution mix.&lt;/strong&gt; A small upright 3D pie in the corner shows how your year splits between commits, pull requests, issues and code review, with each share labelled, so it never depends on colour alone. The four colours were checked for colour-blind separation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;📅 Your peak day&lt;/strong&gt; in a glass card in the corner.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;✨ A glowing core&lt;/strong&gt; in the middle, and planets that orbit with plain CSS animation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Day and night, in your own timezone
&lt;/h2&gt;

&lt;p&gt;There are two themes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;aurora&lt;/code&gt;&lt;/strong&gt;: deep space, with a navy sky, stars and nebulas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;daylight&lt;/code&gt;&lt;/strong&gt;: a soft dawn sky with the same colour wheel (teal, sky, indigo, violet, rose and gold).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The example workflow checks once an hour, works out the time &lt;strong&gt;in your timezone&lt;/strong&gt;, and switches between them. Your profile is daylight during your day and deep space at night.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhjzdsv30f0ru55ljtkvh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhjzdsv30f0ru55ljtkvh.png" alt="Git3D Universe in the daylight theme" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Add it to your profile in 2 steps
&lt;/h2&gt;

&lt;p&gt;You need a profile repository: a public repo with the same name as your username (&lt;code&gt;your-username/your-username&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: add the workflow
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;.github/workflows/git3d-universe.yml&lt;/code&gt; in your profile repo. The full workflow, with timezone switching and checks on the generated image, is in the &lt;a href="https://github.com/SandeepKomal/Git3D-Universe#step-1--add-the-github-actions-workflow" rel="noopener noreferrer"&gt;README&lt;/a&gt;. The core of it is one step:&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="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;Generate Git3D Universe&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SandeepKomal/Git3D-Universe@v2.0.0&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.repository_owner }}&lt;/span&gt;
    &lt;span class="na"&gt;github-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
    &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aurora&lt;/span&gt;            &lt;span class="c1"&gt;# or daylight&lt;/span&gt;
    &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;profile/git3d-universe.svg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Set your timezone at the top of the workflow (for example &lt;code&gt;Asia/Kolkata&lt;/code&gt;, &lt;code&gt;America/New_York&lt;/code&gt; or &lt;code&gt;Europe/London&lt;/code&gt;). Then open the &lt;strong&gt;Actions&lt;/strong&gt; tab and run &lt;strong&gt;Git3D Universe&lt;/strong&gt; once by hand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: show it in your README
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;![&lt;/span&gt;&lt;span class="nv"&gt;Git3D Universe&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="sx"&gt;./profile/git3d-universe.svg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. The workflow keeps the image up to date and commits it only when something changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Built to be trusted
&lt;/h2&gt;

&lt;p&gt;A profile widget runs on your repo every hour, so I kept it small and boring where it matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No hosted rendering service.&lt;/strong&gt; The image is drawn inside your own GitHub Actions run. Data comes straight from GitHub's GraphQL API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No npm dependencies&lt;/strong&gt; at runtime.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Uses the built-in &lt;code&gt;GITHUB_TOKEN&lt;/code&gt;.&lt;/strong&gt; No personal token is needed, and the token is passed through an environment variable, never on the command line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Least privilege.&lt;/strong&gt; The workflow needs only &lt;code&gt;contents: write&lt;/code&gt;, to commit the SVG.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safe text.&lt;/strong&gt; Repo names, descriptions and language colours are escaped and checked before they go into the SVG.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduced motion respected.&lt;/strong&gt; Turn the orbits off with &lt;code&gt;no-motion: true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pin a release.&lt;/strong&gt; Use the &lt;code&gt;v2.0.0&lt;/code&gt; tag or a commit SHA rather than &lt;code&gt;main&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it locally first
&lt;/h2&gt;

&lt;p&gt;Want to see it before touching your profile? It runs on Node 18+ with no dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/SandeepKomal/Git3D-Universe
&lt;span class="nb"&gt;cd &lt;/span&gt;Git3D-Universe

npm run sample      &lt;span class="c"&gt;# draws a sample universe in out/, no network needed&lt;/span&gt;
&lt;span class="nv"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;token&amp;gt; node src/cli.mjs &lt;span class="nt"&gt;--user&lt;/span&gt; YOUR_LOGIN &lt;span class="nt"&gt;--out&lt;/span&gt; profile/git3d-universe.svg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Options: &lt;code&gt;--theme aurora|daylight&lt;/code&gt;, &lt;code&gt;--no-motion&lt;/code&gt;, &lt;code&gt;--sample&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Want a whole profile, not just the universe?
&lt;/h2&gt;

&lt;p&gt;Git3D Universe is also built into my other project, &lt;strong&gt;&lt;a href="https://readme-glassfolio.in/" rel="noopener noreferrer"&gt;README-Glassfolio&lt;/a&gt;&lt;/strong&gt;. It makes a complete profile README (banner, stats, heatmap, languages, projects and Connect buttons) with the 3D universe included, and publishes it in one click.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tell me what your universe looks like
&lt;/h2&gt;

&lt;p&gt;It's free and open source (MIT):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💻 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/SandeepKomal/Git3D-Universe" rel="noopener noreferrer"&gt;SandeepKomal/Git3D-Universe&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐛 &lt;strong&gt;Ideas or bugs:&lt;/strong&gt; &lt;a href="https://github.com/SandeepKomal/Git3D-Universe/issues" rel="noopener noreferrer"&gt;open an issue&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you add it to your profile, &lt;strong&gt;drop your GitHub link in the comments.&lt;/strong&gt; I'd love to see whose busiest month is December. 😄 A ⭐ on the repo helps other developers find it.&lt;/p&gt;

&lt;p&gt;Happy orbiting! 🪐&lt;/p&gt;

</description>
      <category>github</category>
      <category>showdev</category>
      <category>githubactions</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I built a free GitHub profile README generator with no badge APIs, no backend and a 3D contribution universe</title>
      <dc:creator>SandeepKomal</dc:creator>
      <pubDate>Fri, 16 Oct 2026 19:15:52 +0000</pubDate>
      <link>https://dev.to/sandeepkomal/i-built-a-free-github-profile-readme-generator-with-no-badge-apis-no-backend-and-a-3d-5h9</link>
      <guid>https://dev.to/sandeepkomal/i-built-a-free-github-profile-readme-generator-with-no-badge-apis-no-backend-and-a-3d-5h9</guid>
      <description>&lt;p&gt;Your GitHub profile is often the first thing a recruiter, a hiring manager or a possible collaborator sees. For most of us it's a contribution graph and six pinned repos. That's a missed chance.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;&lt;a href="https://readme-glassfolio.in/" rel="noopener noreferrer"&gt;README-Glassfolio&lt;/a&gt;&lt;/strong&gt;: type your GitHub username, pick a theme, and get a complete profile README with a banner, stats, a contribution heatmap, a 3D "contribution universe", a languages card, a timeline, project cards and Connect buttons. Then publish it to your profile in one click.&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Try it:&lt;/strong&gt; &lt;a href="https://readme-glassfolio.in/" rel="noopener noreferrer"&gt;readme-glassfolio.in&lt;/a&gt;&lt;br&gt;
⭐ &lt;strong&gt;Source (MIT):&lt;/strong&gt; &lt;a href="https://github.com/SandeepKomal/README-Glassfolio" rel="noopener noreferrer"&gt;github.com/SandeepKomal/README-Glassfolio&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj1x0ugabkivoidv1h18h.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fj1x0ugabkivoidv1h18h.jpg" alt="The README-Glassfolio page: a themed preview that shows the README exactly as GitHub will show it" width="800" height="1187"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem with most profile README tools
&lt;/h2&gt;

&lt;p&gt;If you've made a fancy profile README before, you've probably pasted in a stack of image URLs pointing at somebody else's server: a stats card here, a streak counter there, a typing banner on top. It looks great until:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the free service hits its rate limit and your profile fills with broken images,&lt;/li&gt;
&lt;li&gt;the service shuts down,&lt;/li&gt;
&lt;li&gt;or you realise every visit to your profile is pinging a third party.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;README-Glassfolio takes a different approach: &lt;strong&gt;everything is drawn as plain SVG files that live in your own &lt;code&gt;&amp;lt;user&amp;gt;/&amp;lt;user&amp;gt;&lt;/code&gt; repo.&lt;/strong&gt; No badge APIs, no stats services, no backend. Data comes straight from &lt;code&gt;api.github.com&lt;/code&gt;, and every card is rendered in your browser.&lt;/p&gt;
&lt;h2&gt;
  
  
  What you get
&lt;/h2&gt;

&lt;p&gt;Here's a README made with it (Royal theme, default options), shown on GitHub's dark and light pages:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4ujhysu35qoo5q0tivju.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4ujhysu35qoo5q0tivju.jpg" alt="The same README on GitHub's dark page and on its light page" width="800" height="1309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Wave header and footer:&lt;/strong&gt; a gradient banner with your name, title and top skills, with gently drifting waves.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stats and streak cards:&lt;/strong&gt; commits, PRs, issues, stars, followers, current and longest streak.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Contribution heatmap:&lt;/strong&gt; laid out like GitHub's own graph, with best day and daily average.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;🪐 3D contribution universe:&lt;/strong&gt; your year as a 3D pie of month wedges round a glowing core, with your top repos orbiting as planets sized by stars, plus a mini pie of your commit / PR / issue / review mix.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Languages card&lt;/strong&gt;, &lt;strong&gt;timeline&lt;/strong&gt;, &lt;strong&gt;project cards&lt;/strong&gt; (pick the ones you want featured, in your order) and &lt;strong&gt;Connect buttons&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;An optional &lt;strong&gt;changelog layout&lt;/strong&gt; that shows your repos as release notes, and a &lt;strong&gt;Recently pushed&lt;/strong&gt; card.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  8 themes, or your own colours
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;aurora&lt;/code&gt;, &lt;code&gt;cyber&lt;/code&gt;, &lt;code&gt;sunset&lt;/code&gt;, &lt;code&gt;emerald&lt;/code&gt;, &lt;code&gt;royal&lt;/code&gt;, &lt;code&gt;graphite&lt;/code&gt;, the light &lt;code&gt;paper&lt;/code&gt;, or &lt;code&gt;auto&lt;/code&gt;, which picks colours from your username so every profile looks different. Want your brand colours? Choose &lt;strong&gt;Custom&lt;/strong&gt;, pick two accents, and it adjusts them so text stays readable. The tests throw 300 random and extreme colour pairs at it to check that.&lt;/p&gt;
&lt;h3&gt;
  
  
  Day and night, automatically
&lt;/h3&gt;

&lt;p&gt;By default you get &lt;strong&gt;two complete image sets&lt;/strong&gt;, dark and light, wrapped in &lt;code&gt;&amp;lt;picture&amp;gt;&lt;/code&gt; with &lt;code&gt;prefers-color-scheme&lt;/code&gt;. Visitors in dark mode see the dark set; visitors in light mode see the light one. Nothing looks out of place on either page.&lt;/p&gt;
&lt;h2&gt;
  
  
  Publish in one click, and it stays fresh
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create your profile repo (&lt;code&gt;your-username/your-username&lt;/code&gt;, public).&lt;/li&gt;
&lt;li&gt;Create a &lt;a href="https://github.com/settings/personal-access-tokens/new" rel="noopener noreferrer"&gt;fine-grained token&lt;/a&gt; limited to &lt;strong&gt;only that repo&lt;/strong&gt;, with &lt;em&gt;Contents&lt;/em&gt; and &lt;em&gt;Workflows&lt;/em&gt; set to read and write.&lt;/li&gt;
&lt;li&gt;On &lt;a href="https://readme-glassfolio.in/" rel="noopener noreferrer"&gt;readme-glassfolio.in&lt;/a&gt;, enter your username, tweak the options, press &lt;strong&gt;Publish to GitHub&lt;/strong&gt; and paste the token.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All files land in &lt;strong&gt;one commit&lt;/strong&gt;. The token goes only to &lt;code&gt;api.github.com&lt;/code&gt;, stays in memory, and is cleared after publishing.&lt;/p&gt;

&lt;p&gt;A README is normally a snapshot, so &lt;strong&gt;"Keep my stats fresh every day"&lt;/strong&gt; is on by default. It adds a small GitHub Action to &lt;em&gt;your&lt;/em&gt; repo that rebuilds the README once a day and commits only when something changed. It has &lt;strong&gt;no &lt;code&gt;uses:&lt;/code&gt; lines&lt;/strong&gt; (no third-party actions), no secrets, one permission (&lt;code&gt;contents: write&lt;/code&gt;), and a copy of the generator sits in &lt;code&gt;.readme-patch/&lt;/code&gt; so you can read every line that runs. If GitHub's API is down that day, it changes nothing, so you never end up with a half-empty profile.&lt;/p&gt;

&lt;p&gt;Prefer not to use a token? &lt;strong&gt;Download the zip&lt;/strong&gt; and drag the files into your repo.&lt;/p&gt;
&lt;h3&gt;
  
  
  How often it updates
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ GitHub pauses scheduled workflows after 60 days without activity in a repo.&lt;/strong&gt; If your profile stops updating, open the &lt;strong&gt;Actions&lt;/strong&gt; tab and re-enable the workflow. It takes one click.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;README and cards:&lt;/strong&gt; once a day, at a time worked out from your username, so runs are spread out without anyone setting a cron time. The page shows your time before you publish.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;3D universe:&lt;/strong&gt; every 6 hours, by a second small workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only real changes are committed&lt;/strong&gt;, so there are no empty commits. Refresh any time with &lt;strong&gt;Run workflow&lt;/strong&gt; in the Actions tab.&lt;/li&gt;
&lt;li&gt;GitHub caches README images for a few minutes, so a new commit can take a moment to show.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;📘 New to profile READMEs? There's a &lt;a href="https://github.com/SandeepKomal/README-Glassfolio/blob/main/docs/HOW_TO_USE.md" rel="noopener noreferrer"&gt;step-by-step guide with screenshots&lt;/a&gt; (also as a PDF) that walks through every click.&lt;/p&gt;
&lt;h2&gt;
  
  
  Safe to paste a token into
&lt;/h2&gt;

&lt;p&gt;I took security seriously, because I'm asking people to paste a token into a web page:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;strict Content-Security-Policy&lt;/strong&gt;: scripts only from the site itself, network requests only to the site and &lt;code&gt;api.github.com&lt;/code&gt;, no inline scripts, no &lt;code&gt;eval&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No &lt;code&gt;innerHTML&lt;/code&gt;&lt;/strong&gt; anywhere. The live preview builds elements from a whitelist, so markup hidden in a bio or repo description can't do anything.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tokens are never stored&lt;/strong&gt; and can't end up in a share link.&lt;/li&gt;
&lt;li&gt;The browser tests actually &lt;em&gt;attack&lt;/em&gt; the page (injected scripts, inline handlers, &lt;code&gt;eval&lt;/code&gt;, fetch/XHR/image/iframe/WebSocket to another host) and check that everything is blocked.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  For terminal fans: there's a CLI
&lt;/h2&gt;

&lt;p&gt;Same engine, zero dependencies, Node 18+:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/SandeepKomal/README-Glassfolio
&lt;span class="nb"&gt;cd &lt;/span&gt;README-Glassfolio

node cli.js your-username &lt;span class="nt"&gt;--theme&lt;/span&gt; cyber &lt;span class="nt"&gt;--role&lt;/span&gt; &lt;span class="s2"&gt;"Cloud Engineer"&lt;/span&gt; &lt;span class="nt"&gt;--stack&lt;/span&gt; &lt;span class="s2"&gt;"AWS, Terraform"&lt;/span&gt;
node cli.js &lt;span class="nt"&gt;--sample&lt;/span&gt;                       &lt;span class="c"&gt;# try it with no network&lt;/span&gt;
&lt;span class="nv"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;github_pat_xxx node cli.js your-username &lt;span class="nt"&gt;--publish&lt;/span&gt; &lt;span class="nt"&gt;--daily&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output goes to &lt;code&gt;./out/&lt;/code&gt;: &lt;code&gt;README.md&lt;/code&gt;, &lt;code&gt;banner.svg&lt;/code&gt; and &lt;code&gt;cards/&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few small touches I'm proud of
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A preview that tells the truth.&lt;/strong&gt; It shows your README inside a mock GitHub profile at GitHub's real widths (896px desktop, 390px phone), with light/dark switching.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text that always fits.&lt;/strong&gt; A fuzz tool renders about 1,800 cards with extreme repo names (90 characters, million-star counts) in a real browser and measures every text box so nothing collides.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Motion that respects people.&lt;/strong&gt; Animations are plain CSS inside the SVGs. With "reduce motion" on, visitors see the finished still image.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Share links&lt;/strong&gt; like &lt;code&gt;?user=octocat&amp;amp;theme=cyber&lt;/code&gt; rebuild the same setup, and a &lt;strong&gt;1280×640 share image&lt;/strong&gt; is ready for LinkedIn or X.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A "Make it even better" checklist&lt;/strong&gt; scores your profile and points to what's missing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it and tell me what you think
&lt;/h2&gt;

&lt;p&gt;It's free, open source (MIT), and runs entirely in your browser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;strong&gt;Web app:&lt;/strong&gt; &lt;a href="https://readme-glassfolio.in/" rel="noopener noreferrer"&gt;readme-glassfolio.in&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/SandeepKomal/README-Glassfolio" rel="noopener noreferrer"&gt;SandeepKomal/README-Glassfolio&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you make your profile with it, &lt;strong&gt;drop your GitHub link in the comments.&lt;/strong&gt; I'd love to see what themes people pick. A ⭐ on the repo helps more developers find it, and issues and PRs are welcome. Next on my list is a compact card design that reads better on phones.&lt;/p&gt;

&lt;p&gt;Happy profile-polishing! ✨&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>javascript</category>
      <category>githubactions</category>
      <category>github</category>
    </item>
    <item>
      <title>How I Reduced Docker Pull Time from 3 Minutes to 3 Seconds</title>
      <dc:creator>SandeepKomal</dc:creator>
      <pubDate>Sun, 26 Oct 2025 08:45:51 +0000</pubDate>
      <link>https://dev.to/sandeepkomal/how-i-reduced-docker-pull-time-from-3-minutes-to-3-seconds-b54</link>
      <guid>https://dev.to/sandeepkomal/how-i-reduced-docker-pull-time-from-3-minutes-to-3-seconds-b54</guid>
      <description>&lt;p&gt;Optimizing Docker performance often starts with small changes that lead to massive results. Slow image pulls can severely impact developer productivity, CI/CD efficiency, and deployment times. In my environment, pulling a single image used to take close to three minutes. After a series of systematic optimizations, I reduced that time to just three seconds.&lt;/p&gt;

&lt;p&gt;This article walks through both the practical steps I followed and general best practices that can help any team achieve similar improvements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understanding the Bottleneck&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When analyzing CI/CD pipelines, I discovered that over 30% of the total job time was spent pulling Docker images from a remote registry. The image was over 1 GB in size and included build dependencies, unused tools, and large OS layers.&lt;/p&gt;

&lt;p&gt;Running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker pull myregistry.com/app/backend:latest &lt;span class="nt"&gt;--verbose&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;showed sequential layer downloads and poor caching utilization. The problem wasn’t Docker itself but rather &lt;strong&gt;image design, caching strategy, and network latency&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Optimize the Docker Image (Java Example)
&lt;/h2&gt;

&lt;p&gt;The original Dockerfile was straightforward but inefficient:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; openjdk:11&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . /app&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;./gradlew build
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["java", "-jar", "build/libs/app.jar"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup embedded both build and runtime dependencies in a single layer. The result was a 1.1 GB image.&lt;/p&gt;

&lt;p&gt;The optimized version used a &lt;strong&gt;multi-stage build&lt;/strong&gt; with a minimal runtime image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stage 1: Build the application&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;gradle:7.6-jdk17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;gradle clean build &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="c"&gt;# Stage 2: Run the application&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; eclipse-temurin:17-jre-alpine&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/build/libs/app.jar .&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 8080&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["java", "-jar", "app.jar"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; Image size reduced to ~240 MB.&lt;br&gt;
&lt;strong&gt;Approach:&lt;/strong&gt; Separated build tools from runtime, reduced layers, and used a lightweight base image.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2: Enable Layer Caching in CI/CD Pipelines
&lt;/h2&gt;

&lt;p&gt;Next, I enabled caching for image layers across builds. Using Docker Buildx in GitHub Actions:&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="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;Set up Docker Buildx&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/setup-buildx-action@v3&lt;/span&gt;

&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and push&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v6&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myregistry.com/app/backend:latest&lt;/span&gt;
    &lt;span class="na"&gt;cache-from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=registry,ref=myregistry.com/app/backend:cache&lt;/span&gt;
    &lt;span class="na"&gt;cache-to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;type=registry,ref=myregistry.com/app/backend:cache,mode=max&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allowed CI/CD pipelines to reuse existing layers instead of redownloading or rebuilding identical ones. Pull time dropped from 180 seconds to roughly 20 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Set Up a Local Registry Mirror
&lt;/h2&gt;

&lt;p&gt;To eliminate external network latency, I configured a local Docker registry mirror:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; 5001:5000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /opt/registry-mirror:/var/lib/registry &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; registry-mirror &lt;span class="se"&gt;\&lt;/span&gt;
  registry:2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then updated &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"registry-mirrors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:5001"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From this point, frequently used images were fetched locally rather than from remote registries. Pull time dropped to three seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Apply Docker Image Optimization Best Practices
&lt;/h2&gt;

&lt;p&gt;Beyond specific optimizations, several universal Dockerfile best practices contribute to faster image builds, smaller layers, and better cache utilization.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Choose a Minimal Base Image
&lt;/h3&gt;

&lt;p&gt;Use small base images such as Alpine or Scratch instead of large distributions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Bad (large)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; ubuntu:20.04&lt;/span&gt;

&lt;span class="c"&gt;# Good (small)&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; alpine:3.19&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alpine is roughly 5 MB, compared to Ubuntu’s 70–100 MB footprint.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Use Multi-Stage Builds
&lt;/h3&gt;

&lt;p&gt;Compile your application in one stage and copy only the final output into a minimal runtime stage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stage 1: Build&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;golang:1.22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;go build &lt;span class="nt"&gt;-o&lt;/span&gt; myapp .

&lt;span class="c"&gt;# Stage 2: Minimal runtime&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; alpine:3.19&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=builder /app/myapp .&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["./myapp"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Only the compiled binary is included in production, not build tools or dependencies.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Remove Unnecessary Files
&lt;/h3&gt;

&lt;p&gt;Clear package caches and temporary files after installation to prevent bloat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example (Alpine):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apk add &lt;span class="nt"&gt;--no-cache&lt;/span&gt; git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/cache/apk/&lt;span class="k"&gt;*&lt;/span&gt; /tmp/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example (Debian/Ubuntu):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Combine RUN Instructions
&lt;/h3&gt;

&lt;p&gt;Each &lt;code&gt;RUN&lt;/code&gt; command creates a new layer. Combine related operations to reduce layers and image size.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Bad&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; git
&lt;span class="k"&gt;RUN &lt;/span&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="c"&gt;# Good&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; git &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Use &lt;code&gt;.dockerignore&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Prevent unnecessary files (e.g., &lt;code&gt;.git&lt;/code&gt;, logs, and node_modules) from being sent to the Docker build context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example &lt;code&gt;.dockerignore&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.git
node_modules
*.log
*.tmp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures a smaller build context and faster build times.&lt;/p&gt;

&lt;h3&gt;
  
  
  Summary of Best Practices
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use small base images (e.g., Alpine, slim, scratch).&lt;/li&gt;
&lt;li&gt;Apply multi-stage builds.&lt;/li&gt;
&lt;li&gt;Remove caches and temporary files.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;.dockerignore&lt;/code&gt; effectively.&lt;/li&gt;
&lt;li&gt;Combine related commands to minimize layers.&lt;/li&gt;
&lt;li&gt;Avoid copying unnecessary files into the image.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 5: (Optional) Use CDN Acceleration
&lt;/h2&gt;

&lt;p&gt;For distributed or multi-region teams, host your registry (ECR, Harbor, or Artifactory) behind a CDN such as AWS CloudFront or Cloudflare. This ensures geographically optimized image pulls for global developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Results
&lt;/h2&gt;

&lt;p&gt;After implementing all these optimizations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pull time reduced from &lt;strong&gt;3 minutes to 3 seconds&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;CI/CD execution time improved by over 60%.&lt;/li&gt;
&lt;li&gt;Network utilization became predictable and efficient.&lt;/li&gt;
&lt;li&gt;Developer feedback loops became almost instantaneous.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Docker image optimization is often undervalued, but its impact is significant. Through smaller base images, efficient multi-stage builds, cache utilization, and registry mirroring, I reduced image pull time from minutes to seconds.&lt;/p&gt;

&lt;p&gt;These practices don’t just improve performance — they scale across environments, pipelines, and teams, forming the foundation of efficient containerized systems.&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%2Fvv8bafp2akzea9ia62kw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvv8bafp2akzea9ia62kw.jpg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>containers</category>
      <category>kubernetes</category>
    </item>
  </channel>
</rss>
