<?xml version="1.0" encoding="UTF-8"?>
<rss 
    version="2.0"
    xmlns:dc="http://purl.org/dc/elements/1.1/" 
    xmlns:content="http://purl.org/rss/1.0/modules/content/" 
    xmlns:atom="http://www.w3.org/2005/Atom" 
    xmlns:media="http://search.yahoo.com/mrss/" 
>
    <channel>
        <title><![CDATA[Linux Handbook]]></title>
        <description><![CDATA[An independent, reader-supported publication focusing on Linux Command Line, Server, Self-hosting, DevOps and Cloud Learning]]></description>
        <link>https://linuxhandbook.com</link>
        <image>
            <url>https://linuxhandbook.com/favicon.png</url>
            <title>Linux Handbook</title>
            <link>https://linuxhandbook.com</link>
        </image>
        <generator>Ghost 6.27</generator>
        <lastBuildDate>Tue, 21 Apr 2026 11:22:00 +0530</lastBuildDate>
        <atom:link href="https://linuxhandbook.com" rel="self" type="application/rss+xml"/>
        <ttl>60</ttl>

                <item>
                    <title><![CDATA[I Tried Self-Hosting This Authentication Project from CNCF (And It Was a Humbling Experience)]]></title>
                    <description><![CDATA[I found setting up Keycloak challengeing. It was a good challenge and a learning experience that I share with you.]]></description>
                    <link>https://linuxhandbook.com/blog/keycloak-experiment/</link>
                    <guid isPermaLink="false">69945e40f7d3c300011c4d8a</guid>

                        <category><![CDATA[blog]]></category>
                        <category><![CDATA[Self Hosting Tutorials]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 20 Apr 2026 16:08:06 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/02/keycloak.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/02/keycloak.png" alt="I Tried Self-Hosting This Authentication Project from CNCF (And It Was a Humbling Experience)"/> <p>In a world where authentication services charge per user and lock you into their ecosystem, Keycloak offers something rare: enterprise-grade identity management that you can run on your own infrastructure, completely free. No vendor lock-in, no monthly bills, no user limits.</p><p>After spending several days setting up <a href="https://github.com/keycloak/keycloak?ref=linuxhandbook.com">Keycloak</a>, integrating it with Portainer via OAuth, configuring social login with GitHub, and wrestling with the documentation gaps, here's what you need to know before diving in.</p><h2 id="what-is-keycloak">What is Keycloak?</h2><p>Keycloak is an open-source Identity and Access Management (IAM) solution that handles authentication and authorization for modern applications. Think of it as a self-hosted alternative to Auth0, Okta, or AWS Cognito, but without the per-user pricing or vendor lock-in.</p><p>It's a <a href="https://www.cncf.io/?ref=linuxhandbook.com">CNCF</a> (Cloud Native Computing Foundation) project under the Apache 2.0 license, which means it's backed by a strong community and actively developed. It includes featuers like Single Sign-On (SSO), Social login (GitHub, Google, Gitlab, etc.), OAuth 2.0 and OpenID Connect (OIDC) and many more.</p><p>The selling point isn't just the feature list - it's that you get all of this without paying per user or worrying about what happens if the vendor shuts down.</p><h2 id="the-setup-challenge">The Setup Challenge</h2><p>Yes, I am mentioning it as a challenge because in the official documentation, there is no proper <code>docker-compose</code> file to set up the whole database with Keycloak. You're left piecing together environment variables from different documentation pages. After many trial-and-error attempts, here's my custom <code>docker-compose.yml</code> that actually works:</p><pre><code class="language-YAML">services:
  postgresql:
    image: postgres:16
    container_name: keycloak_db
    environment:
      POSTGRES_USER: keycloak
      POSTGRES_DB: keycloak
      POSTGRES_PASSWORD: SUPERsecret
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    networks:
      - keycloak

  keycloak:
    image: quay.io/keycloak/keycloak:26.5.3
    container_name: keycloak
    depends_on:
      - postgresql
    command: start-dev
    environment:
      - KC_BOOTSTRAP_ADMIN_USERNAME=admin
      - KC_BOOTSTRAP_ADMIN_PASSWORD=admin
      - KC_DB=postgres
      - KC_DB_URL=jdbc:postgresql://postgresql:5432/keycloak
      - KC_DB_USERNAME=keycloak
      - KC_DB_PASSWORD=SUPERsecret
    ports:
      - "8081:8080"
    networks:
      - keycloak

networks:
  keycloak:
</code></pre><p>In this,<strong> </strong>we have mentioned PostgreSQL container for the database, <code>./postgres_data</code> ensures your users and configurations survive container restarts and stay persistent using volumes, <code>KC_BOOTSTRAP_ADMIN_USERNAME</code>&nbsp;and&nbsp;<code>KC_BOOTSTRAP_ADMIN_PASSWORD</code>&nbsp;create the initial admin account, port mapping is done as <code>8081:8080</code>&nbsp;because port 8080 is often already taken on development machines, a <strong>it, </strong>custom network <code>keycloak</code> ensures Keycloak and PostgreSQL can communicate by service name.</p><p>Save the above file as docker-compose.yml and run the following command: </p><pre><code class="language-bash">mkdir -p keycloak &amp;&amp; cd keycloak
# Save the compose file above
docker-compose up -d
</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/image-29.png" class="kg-image" alt="Keycloak running as a container." loading="lazy" width="1149" height="450" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/image-29.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/02/image-29.png 1000w, https://linuxhandbook.com/content/images/2026/02/image-29.png 1149w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Keycloak running as a container.</span></figcaption></figure><p>Within 30-60 seconds, you'll have Keycloak running at&nbsp;<code>http://localhost:8081</code>.</p><h2 id="initial-configuration">Initial Configuration</h2><p>When you first access Keycloak, you'll land on the admin console login page. Use the credentials you set in&nbsp;<code>username</code>&nbsp;and <code>password</code>&nbsp;(in this case,&nbsp;<code>admin</code>&nbsp;/&nbsp;<code>admin</code>).</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/Screenshot-from-2026-02-17-10-37-55.png" class="kg-image" alt="Initial Login Page." loading="lazy" width="1909" height="992" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/Screenshot-from-2026-02-17-10-37-55.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/02/Screenshot-from-2026-02-17-10-37-55.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/02/Screenshot-from-2026-02-17-10-37-55.png 1600w, https://linuxhandbook.com/content/images/2026/02/Screenshot-from-2026-02-17-10-37-55.png 1909w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Initial Login Page.</span></figcaption></figure><p>Once logged in, you'll see the&nbsp;<strong>master realm</strong>. Realms in Keycloak are isolated spaces for managing users, clients, and authentication policies. The master realm is for administrative purposes only - you can create a separate realm for different applications.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/image-30.png" class="kg-image" alt="Managing realms in keycloak." loading="lazy" width="1920" height="937" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/image-30.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/02/image-30.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/02/image-30.png 1600w, https://linuxhandbook.com/content/images/2026/02/image-30.png 1920w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Managing realms in keycloak.</span></figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/image-38.png" class="kg-image" alt="Authentication and Users in keycloak." loading="lazy" width="875" height="707" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/image-38.png 600w, https://linuxhandbook.com/content/images/2026/02/image-38.png 875w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Authentication and Users in keycloak.</span></figcaption></figure><p>You can add Users, Groups, Events, etc., for your specific realm. You can add an email and verify it, <strong> </strong>which can be used later to add users and authenticate them.</p><h2 id="real-world-test-portainer-oauth-integration">Real-World Test: Portainer OAuth Integration</h2><p>The best way to understand Keycloak is to integrate it with a real application. Portainer (a Docker management UI) supports OAuth authentication, making it a perfect test case.</p><p>For this purpose, I have my Portainer running on port 9000, which shows me all the containers, images, networks, services, etc., running on my host machine.</p><p>You can run Portainer on your own by using the following command:</p><pre><code class="language-bash">docker run -d -p 9000:9000 -p 9443:9443 --name portainer --restart=always -v /var/run/docker.sock:/var/run/docker.sock -v portainer_data:/data portainer/portainer-ce:lts</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/image-31.png" class="kg-image" alt="Self hosted Portainer running on localhost:9000. " loading="lazy" width="1375" height="1018" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/image-31.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/02/image-31.png 1000w, https://linuxhandbook.com/content/images/2026/02/image-31.png 1375w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Self hosted Portainer running on localhost:9000. </span></figcaption></figure><p>You will see the Portainer running on <code>localhost:9000</code> and showing all the results of your Docker stuff.<br><br><strong>Creating an OAuth Client: </strong>For this, navigate to your <strong>realm,</strong> then open&nbsp;<strong>Clients </strong>and click on <strong>create client</strong>, here you need to paste the following so that it successfully connects to the portainer running on the system.</p><pre><code class="language-Text">Client ID: portainer
Client authentication: ON (this generates a client secret)
Valid redirect URIs: http://localhost:9000/*
Valid post logout redirect URIs: http://localhost:9000/*
Web origins: http://localhost:9000</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/image-32.png" class="kg-image" alt="Client configurations in keycloak." loading="lazy" width="1547" height="946" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/image-32.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/02/image-32.png 1000w, https://linuxhandbook.com/content/images/2026/02/image-32.png 1547w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Client configurations in keycloak.</span></figcaption></figure><p>Save the client, then go to the&nbsp;<strong>Credentials</strong>&nbsp;tab and copy the&nbsp;<strong>Client Secret</strong>. You'll need this for Portainer.</p><p><strong>Configuring Portainer: </strong>In Portainer, go to&nbsp;<strong>Settings,</strong>&nbsp;then&nbsp;<strong>Authentication,</strong>,<strong> </strong>navigate to &nbsp;<strong>OAuth</strong>, where you need to configure some things inorder to connect to the client created at keycloak and the portainer Oauth.</p><pre><code class="language-Text">Client ID: portainer
Client secret: (paste the secret from Keycloak)
Authorization URL: http://localhost:8081/realms/myrealm/protocol/openid-connect/auth
Access token URL: http://localhost:8081/realms/myrealm/protocol/openid-connect/token
Resource URL: http://localhost:8081/realms/myrealm/protocol/openid-connect/userinfo
Redirect URL: http://localhost:9000/
User identifier: email
Scopes: email openid profile</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/image-33.png" class="kg-image" alt="Custom auth support in Portainer." loading="lazy" width="1911" height="941" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/image-33.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/02/image-33.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/02/image-33.png 1600w, https://linuxhandbook.com/content/images/2026/02/image-33.png 1911w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Custom auth support in Portainer.</span></figcaption></figure><p>Then save the configurations and you are ready to test your Keycloak authentication. </p><p><strong>Testing the flow: </strong>The actual test is to see if we can log out from the Portainer and see the login with OAuth, and as expected, after logging out from the portainer the login with OAuth button is visible in the Portainer.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/Screenshot-from-2026-02-17-11-54-45.png" class="kg-image" alt="Keycloak OAuth in action." loading="lazy" width="1920" height="975" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/Screenshot-from-2026-02-17-11-54-45.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/02/Screenshot-from-2026-02-17-11-54-45.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/02/Screenshot-from-2026-02-17-11-54-45.png 1600w, https://linuxhandbook.com/content/images/2026/02/Screenshot-from-2026-02-17-11-54-45.png 1920w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Keycloak OAuth in action.</span></figcaption></figure><p>which redirects to the Keycloak sign-in page and if you have added the same user in the Keycloak with an active login session, then you will be able to log in to Portainer and be redirected to the homescreen with that user; the entire process happens seamlessly.</p><p>To be honest, as it is seamless in execution, I found it very complex and time consuming to configure the proper urls, as for the self hosted websites and architechture you need to configure the urls correctly handling the routes perfectly, otherwise there are many errors, like not redirecting to the correct destination, OAuth failed, url does not contains needed parameter, etc. that I faced during the configuration. </p><h2 id="social-login-integration">Social Login Integration</h2><p>One of Keycloak's standout features is built-in support for social login providers. Adding GitHub authentication takes about 5 minutes. I tested with GitHub Identity Provider.</p><p><strong>Setting Up: </strong> In Keycloak, you can have options to add an <strong>Identity Provider; </strong>I have taken GitHub for example. There is a list of options for the Identity provider, you can choose any as per your need. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/image-34.png" class="kg-image" alt="Identity providers supported in keycloak." loading="lazy" width="349" height="666"><figcaption><span style="white-space: pre-wrap;">Identity providers supported in keycloak.</span></figcaption></figure><p>For GitHub, you need to go to your GitHub Profile → Settings → Developer settings → OAuth Apps → New OAuth App and set the Auth callback URL as <code>http://localhost:8081/realms/master/broker/github/endpoint</code></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/image-35.png" class="kg-image" alt="Setting OAuth for Github through keycloak." loading="lazy" width="808" height="912" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/image-35.png 600w, https://linuxhandbook.com/content/images/2026/02/image-35.png 808w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Setting OAuth for Github through keycloak.</span></figcaption></figure><p>Copy the&nbsp;<strong>Client ID</strong>&nbsp;and&nbsp;<strong>Client Secret</strong>&nbsp;from GitHub into Keycloak and save the identity provider configuration.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/image-36.png" class="kg-image" alt="Settings for Identity Provider with credentials." loading="lazy" width="956" height="738" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/image-36.png 600w, https://linuxhandbook.com/content/images/2026/02/image-36.png 956w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Settings for Identity Provider with credentials.</span></figcaption></figure><p>When a user logs in via GitHub for the first time, Keycloak automatically creates a user account and links it to their GitHub identity. You can see linked accounts in the user's account console.</p><p>After doing this, I was able to get the expected GitHub Identity Provider in the login window.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/Screenshot-from-2026-02-17-11-15-44.png" class="kg-image" alt="GitHub added as Sign In option in keycloak." loading="lazy" width="1920" height="975" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/Screenshot-from-2026-02-17-11-15-44.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/02/Screenshot-from-2026-02-17-11-15-44.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/02/Screenshot-from-2026-02-17-11-15-44.png 1600w, https://linuxhandbook.com/content/images/2026/02/Screenshot-from-2026-02-17-11-15-44.png 1920w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">GitHub added as Sign In option in keycloak.</span></figcaption></figure><p>This same process works for Google, Facebook, Twitter, Microsoft, and 20+ other providers. You can even enable multiple social logins simultaneously, giving users the choice.</p><h2 id="what-works-really-well-in-keycloak">What Works Really Well In Keycloak</h2><p>Multi-factor authentication, social login, user federation with LDAP/Active Directory and fine-grained authorization policies - features that cost hundreds of dollars per month on SaaS platforms are all included. No per-user pricing, no feature gates. Which gives <strong>Enterprise Features for free</strong>.</p><p>Keycloak implements OAuth 2.0, OpenID Connect, and SAML 2.0 correctly. This means it works with virtually any modern application that supports these protocols. You're not locked into proprietary APIs.</p><p>You can customize login themes to match your brand, create custom authentication flows (e.g., require email verification before MFA), and even write custom extensions in Java. The level of control is unmatched, giving <strong>Flexibility and customization</strong>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/02/image-39.png" class="kg-image" alt="Customization options in keycloak." loading="lazy" width="957" height="561" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/image-39.png 600w, https://linuxhandbook.com/content/images/2026/02/image-39.png 957w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Customization options in keycloak.</span></figcaption></figure><p>As a CNCF project with backing from Red Hat, Keycloak receives regular updates, security patches, and new features. The community is active, and GitHub issues get responses signifying <strong>active development</strong>.</p><p>The experience of testing the Keycloak was seamless in terms of <strong>performance</strong>.</p><h2 id="where-keycloak-falls-short">Where Keycloak Falls Short</h2><p>No tool is perfect, and Keycloak has some significant limitations you should know about upfront.</p><p><strong>Documentation gaps.</strong>&nbsp;The official docs are comprehensive but scattered. The biggest pain point: there's no official <code>docker-compose</code> example that includes a production database. You're left piecing together environment variables from different pages. This is why the custom <code>docker-compose</code> file above took trial and error to get right.</p><p><strong>Steep learning curve.</strong>&nbsp;Keycloak has a lot of concepts: realms, clients, client scopes, protocol mappers, identity providers, user federation, and authentication flows. For someone new to IAM, the admin console can be overwhelming. Expect to spend a few days just understanding the terminology.</p><p><strong>Scalability and Multi-Tenancy.</strong>&nbsp;Keycloak can struggle with a high number of realms (multi-tenant environments), experiencing performance degradation in the Admin Console and realm management. While newer versions are improving,, earlier and default configurations have limitations.</p><p><strong>Resource hungry.</strong>&nbsp;Keycloak is a Java application that needs a PostgreSQL database. It's not lightweight like some self-hosted tools. Expect at least 512MB of RAM for Keycloak alone, plus database overhead. Startup time is 30-60 seconds, not instant.<strong> </strong></p><p><strong>Default Security Configuration.</strong>&nbsp;The default password hashing iterations are low, which requires administrators to manually tune security to prevent brute-force attacks. Keycloak can struggle with a high number of realms (multi-tenant environments), experiencing performance degradation. While newer versions are improving, earlier and default configurations have limitations.</p><h2 id="conclusion">Conclusion</h2><p>Keycloak delivers enterprise-grade identity and access management without the enterprise price tag. The setup complexity is real - the lack of official Docker Compose examples and the steep learning curve are genuine barriers - but the features you get in return make it worthwhile.</p><p>Is it overkill for a simple single-app project? Absolutely. If you just need basic username/password authentication, Keycloak is too much. But if you're building a multi-app ecosystem, need SSO across services, want social login without vendor lock-in, or require features like MFA and user federation, Keycloak is one of the best self-hosted options available.</p><p>The <code>docker-compose</code> file above solves the biggest setup hurdle. Once you're past the initial configuration, Keycloak is remarkably powerful and flexible.</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[LHB Linux Digest #26.06: DIY Linux Learning Labs, Docker Tools, Drone Logs and More Linux Stuff]]></title>
                    <description><![CDATA[Lab is the differentiator.]]></description>
                    <link>https://linuxhandbook.com/newsletter/26-06/</link>
                    <guid isPermaLink="false">69c9f7b1df009b000197e832</guid>

                        <category><![CDATA[Newsletter]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Tue, 07 Apr 2026 20:11:32 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/04/lhb-newsletter.webp" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/04/lhb-newsletter.webp" alt="LHB Linux Digest #26.06: DIY Linux Learning Labs, Docker Tools, Drone Logs and More Linux Stuff"/> <p>True learning begins when you actively work on something. That’s why a balance of theory and hands-on practice is essential.</p><p>To address this, we are creating labs. These are small, guided projects designed to help you practice on your Linux system. When you work through them yourself, you naturally encounter challenges you didn’t anticipate. In this way, these labs help prepare you for real-world scenarios.</p><p>You can test it out with this lab where <a href="https://linuxhandbook.com/labs/automated-image-optimization/">you have to build an automated image optimization system</a>. </p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://linuxhandbook.com/labs/automated-image-optimization/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Building an Automated Image Optimization Pipeline</div><div class="kg-bookmark-description">In this lab, you’ll build an automated process that watches a folder for new images and automatically optimizes them.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/Linux-Handbook-New-Logo-197.png" alt=""><span class="kg-bookmark-author">Linux Handbook</span><span class="kg-bookmark-publisher">Roland Taylor</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/image-optimization-lab.webp" alt="" onerror="this.style.display = 'none'"></div></a></figure><p>I'll be making a collection of such labs for your learning pleasure. Stay tuned.</p><p>That's not the only change. We have a <a href="https://linuxhandbook.com/blog/">blog section</a> now. As I am reorganizing the content on Linux Handbook, it makes sense to write blogs around tools and tips we discover as a Linux user.</p>

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">
        <div data-sx-content-cta-blur class="absolute w-full start-0 -top-0.5 -translate-y-full bg-linear-to-b to-70% from-black/0 to-background dark:to-background-dark pointer-events-none">
            &nbsp; <br> &nbsp; <br> &nbsp;
        </div>

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                        <span class="hidden first:inline">
                        This post is for subscribers only
                    </span>                

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Building an Automated Image Optimization Pipeline]]></title>
                    <description><![CDATA[In this lab, you&#x27;ll build an automated process that watches a folder for new images and automatically optimizes them.]]></description>
                    <link>https://linuxhandbook.com/labs/automated-image-optimization/</link>
                    <guid isPermaLink="false">692602d77f7be70001e8e828</guid>

                        <category><![CDATA[Labs]]></category>

                        <dc:creator><![CDATA[Roland Taylor]]></dc:creator>

                    <pubDate>Tue, 07 Apr 2026 19:27:04 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/04/image-optimization-lab.webp" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/04/image-optimization-lab.webp" alt="Building an Automated Image Optimization Pipeline"/> <p>Optimizing images for the web is a common step in website design and development, but it can also be one of the most tedious. With all the steps like resizing, compressing, stripping metadata, and exporting multiple formats, it can eat chunks of time that rack up quickly when you’re just trying to work your blog, portfolio, or even a small business website.</p><p>This lab exercises will show you how to not only make that process easier, but automate it in a way that can be replicated on your own system or even a Linux server.</p><h2 id="%F0%9F%8E%AF-the-goal">🎯 The goal</h2><p>For this Linux Lab project, we'll be building a simple, fully automated image processing pipeline that does the following:</p><ul><li>Watches a specific folder for new images</li><li>Automatically optimizes them using ImageMagick</li><li>(Optionally) Generates web-friendly WebP copies</li><li>(Optionally) Moves images into section-specific folders like <code>optimized/blog/img/</code> for rapid reference and deployment</li><li>(Preferably) Runs the automation as a systemd user service</li></ul><p>By the time we're finished, you’ll have a reusable automation that you can implement on your desktop or server, with minimal overhead, no need for configuration, and <strong>no need for Docker or any external services</strong>.</p><h2 id="prerequisites">Prerequisites</h2><p>Before you dive in, there are a few dependencies that should be taken care of first. The details may differ slightly for your distro, so please be aware that you may need to consult your distro's documentation where necessary to install the correct packages. Once this stage is done, however, you should be able to follow everything just the same on most distributions.</p><p><strong>You'll need to install:</strong></p><ul><li>ImageMagick: for resizing and compressing images in common formats</li><li>inotify-tools: for watching the target folder for any new files</li><li>(optionally) webp: for converting images to the WebP format</li></ul><p><strong>On Ubuntu systems, you can run:</strong></p><pre><code class="language-bash">sudo apt update
sudo apt install -y imagemagick inotify-tools webp</code></pre><p><strong>On Fedora, you can use:</strong></p><pre><code class="language-bash">sudo dnf -y install ImageMagick inotify-tools libwebp-tools</code></pre><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-emoji">📋</div><div class="kg-callout-text">As with Fedora, the ImageMagick package may not always be called <code spellcheck="false" style="white-space: pre-wrap;">imagemagick</code> in your distro repository. Be sure to check before attempting to install on other distros, as package names are typically case-sensitive.</div></div><p>Once you've installed these packages, you're ready to move on to setting up the project folders.</p><h2 id="building-out-the-project-folders">Building out the project folders</h2><p>For this endeavor, we'll build a single parent folder with three sub-directories. Technically, you can place the three sub-directories anywhere you like, but for keeping things organized, we'll keep them in a dedicated folder for this tutorial.</p><p><strong>The structure we'll use looks something like this:</strong></p><ul><li><code>~/image-lab:</code> the parent folder<ul><li><code>/incoming:</code> where you'll drop original images for optimization</li><li><code>/optimized:</code> where optimized images will be saved</li><li><code>/logs:</code> for storing a simple log file with timestamps and actions</li></ul></li></ul><p><strong>To create these folders, you just need to run the following command:</strong></p><pre><code class="language-bash">mkdir -p ~/image-lab/{incoming,optimized,logs}</code></pre><p>This will automatically create the sub-directories with <code>~/image-lab</code> for you.</p>

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">
        <div data-sx-content-cta-blur class="absolute w-full start-0 -top-0.5 -translate-y-full bg-linear-to-b to-70% from-black/0 to-background dark:to-background-dark pointer-events-none">
            &nbsp; <br> &nbsp; <br> &nbsp;
        </div>

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                        <span class="hidden first:inline">
                        This post is for subscribers only
                    </span>                

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Watchtower Discontinued! Here Are Alternative Projects for Your Docker Containers]]></title>
                    <description><![CDATA[Watchtower was the goto tool for keeping the containers updated timely. It&#x27;s not developed anymore. I explored a few alternatives.]]></description>
                    <link>https://linuxhandbook.com/blog/watchtower-like-docker-tools/</link>
                    <guid isPermaLink="false">69b90f2edf009b000197bec3</guid>

                        <category><![CDATA[blog]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Sat, 04 Apr 2026 16:44:23 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/04/penguin-with-telescope.webp" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/04/penguin-with-telescope.webp" alt="Watchtower Discontinued! Here Are Alternative Projects for Your Docker Containers"/> <p>There are plenty of <a href="https://linuxhandbook.com/blog/docker-workflow-tools/">tools that help you use Docker containers more effectively and smoothly</a>. One of the most popular was Watchtower. Was...because the project has been discontinued in December 2025.</p><p>If you've been running Watchtower to automatically keep your containers updated, you're not alone in suddenly wondering what's next after <a href="https://github.com/containrrr/watchtower?ref=linuxhandbook.com">the repo has been archived</a>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-36.png" class="kg-image" alt="" loading="lazy" width="1024" height="1024" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-36.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-36.png 1000w, https://linuxhandbook.com/content/images/2026/03/image-36.png 1024w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Watchtower's GitHub repo was archived on </span><b><strong style="white-space: pre-wrap;">December 17, 2025</strong></b><span style="white-space: pre-wrap;">. Read-only. Done.</span></figcaption></figure><p>Good news - the alternatives are actually <strong><em>better</em></strong>. Here are some solid tools worth your time in my opinion and experience.</p><h2 id="diundocker-image-update-notifier"><strong>Diun - D</strong>ocker&nbsp;<strong>I</strong>mage&nbsp;<strong>U</strong>pdate&nbsp;<strong>N</strong>otifier</h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-44.png" class="kg-image" alt="" loading="lazy" width="445" height="213"></figure><p>It is a CLI application written in&nbsp;<a href="https://golang.org/?ref=linuxhandbook.com">Go</a>&nbsp;and delivered as a&nbsp;<a href="https://github.com/crazy-max/diun/releases/latest?ref=linuxhandbook.com">single executable</a>&nbsp;(and a&nbsp;<a href="https://crazymax.dev/diun/install/docker/?ref=linuxhandbook.com">Docker image</a>) to receive notifications when a Docker image is updated on a Docker registry.</p><p>Diun does one thing: <strong>watches your images and notifies you when they're updated</strong>. It will not touch your containers. That's intentional. If you've ever had Watchtower silently pull a Postgres major version upgrade at 2 am, you'll appreciate this approach. You stay in control of when the actual update happens.</p><p><strong>Quick compose setup:</strong></p><pre><code class="language-yaml">services:
  diun:
    image: crazymax/diun:latest
    volumes:
      - "./data:/data"
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "./diun.yml:/diun.yml:ro"
    environment:
      - "DIUN_WATCH_SCHEDULE=0 */6 * * *"
    restart: always</code></pre><p>and make one <code>diun.yml</code>: </p><pre><code class="language-yaml"># diun.yml
watch:
  schedule: "0 */6 * * *"
providers:
  docker:
    watchStopped: true
notif:
  discord:
    webhookURL: https://discordapp.com/api/YOUR/WEBHOOK</code></pre><p>You can mention your webhook URL for Slack, Telegram, Discord, etc. if there is any update, you will receive it like: </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-37.png" class="kg-image" alt="" loading="lazy" width="550" height="449"><figcaption><span style="white-space: pre-wrap;">credit: </span><a href="https://crazymax.dev/diun?ref=linuxhandbook.com"><span style="white-space: pre-wrap;">crazymax.dev/diun</span></a></figcaption></figure><p>This will notify you in all supported applications, just like what we have received on Discord: the hostname, provider, the date it was created, platform and the Docker Hub link.</p><p><strong>Use this if:</strong> You want awareness without the risk of surprise updates. Great for production-adjacent setups.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/crazy-max/diun?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Diun</a></div><h2 id="tugtainer"><strong>Tugtainer</strong></h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-41.png" class="kg-image" alt="" loading="lazy" width="897" height="343" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-41.png 600w, https://linuxhandbook.com/content/images/2026/03/image-41.png 897w" sizes="(min-width: 720px) 720px"></figure><p>Tugtainer is a self-hosted app for automating updates of your Docker containers. Relatively new (October 2025), devs say not production-ready yet. But moves fast — v1.25.0 dropped March 2026.</p><p>Tugtainer gives you a proper web dashboard to manage container updates. Think Portainer, but focused specifically on the update workflow.</p><p><strong>Quick setup:</strong></p><pre><code class="language-bash"># create volume
docker volume create tugtainer_data

# pull image
docker pull ghcr.io/quenary/tugtainer:1

# run container
docker run -d -p 9412:80 \
    --name=tugtainer \
    --restart=unless-stopped \
    -v tugtainer_data:/tugtainer \
    -v /var/run/docker.sock:/var/run/docker.sock:ro \
    ghcr.io/quenary/tugtainer:1</code></pre><p>Hit <code>http://your-server:3000</code> and you get this:</p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-38.png" class="kg-image" alt="" loading="lazy" width="1920" height="858" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-38.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-38.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/03/image-38.png 1600w, https://linuxhandbook.com/content/images/2026/03/image-38.png 1920w" sizes="(min-width: 720px) 720px"></figure><p>Some of the main features are: Notifications to a wide range of services, Per-container config (check only or auto-update), Automatic/manual check and update, Automatic/manual image pruning and Linked containers support (compose and custom).</p><p><strong>Use this if:</strong> You want a UI to manage your homelab updates. Especially good for Docker Compose setups.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/Quenary/tugtainer?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Tugtainer</a></div><h2 id="wudwhats-up-docker"><strong>WUD</strong> - <strong>What's Up Docker </strong></h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-42.png" class="kg-image" alt="" loading="lazy" width="515" height="387"></figure><p>WUD is the closest thing to a drop-in Watchtower replacement - but it's smarter. It has a web dashboard, notification support, and can auto-update containers. The key difference? It lets you set <strong>thresholds</strong>.</p><pre><code class="language-bash">WUD_TRIGGER_DOCKER_LOCAL_THRESHOLD=patch
</code></pre><p>With that set, WUD auto-updates <code>1.2.3 → 1.2.4</code> but just <strong><em>notifies</em></strong> you for <code>1.2.3 → 1.3.0</code> or a major bump. Watchtower had no concept of this.</p><p><strong>Quick setup:</strong></p><pre><code class="language-yaml">services:
  wud:
    image: getwud/wud:latest
    ports:
      - "3000:3000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WUD_NOTIFIER_TELEGRAM_BOTTOKEN=your-token
      - WUD_NOTIFIER_TELEGRAM_CHATID=your-chat-id
      - WUD_TRIGGER_DOCKER_LOCAL_THRESHOLD=patch
    restart: unless-stopped</code></pre><p>If you hit <code>localhost:3000</code> you will get a simple, minimalist UI.</p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-39.png" class="kg-image" alt="" loading="lazy" width="1920" height="975" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-39.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-39.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/03/image-39.png 1600w, https://linuxhandbook.com/content/images/2026/03/image-39.png 1920w" sizes="(min-width: 720px) 720px"></figure><p>Notifications go to Slack, Telegram, Discord, Gotify, Ntfy, Pushover, email and more. </p><p><strong>Use this if</strong>: You want something close to Watchtower's auto-update behavior, but with actual guardrails and a dashboard.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/getwud/wud?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | WUD</a></div><h2 id="dockcheck"><strong>dockcheck</strong></h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-43.png" class="kg-image" alt="" loading="lazy" width="601" height="430" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-43.png 600w, https://linuxhandbook.com/content/images/2026/03/image-43.png 601w"></figure><p>The odd one out - it's a bash script. And it's my personal favorite.</p><p>The trick: dockcheck uses <code>regctl</code> to <strong>compare image digests directly</strong> against the registry. It never pre-pulls images just to check for updates. Saves bandwidth, doesn't hit Docker Hub rate limits, and is just plain faster.</p><p>Install <code>regctl</code> first:</p><pre><code class="language-bash">curl -L https://github.com/regclient/regclient/releases/latest/download/regctl-linux-amd64 \
  -o /usr/local/bin/regctl &amp;&amp; chmod +x /usr/local/bin/regctl</code></pre><pre><code class="language-bash">curl -fsSL https://raw.githubusercontent.com/mag37/dockcheck/main/dockcheck.sh -o dockcheck.sh
chmod +x dockcheck.sh
./dockcheck.sh</code></pre><p>You will get output like this:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-40.png" class="kg-image" alt="" loading="lazy" width="885" height="562" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-40.png 600w, https://linuxhandbook.com/content/images/2026/03/image-40.png 885w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">credit: cdn.jsdelivr.net</span></figcaption></figure><p>You get a numbered list of containers with updates available. Pick which ones to update, or type <code>a</code> for all. Clean and simple.</p><p>To automate it, just cron it:</p><pre><code class="language-bash"># Every Sunday at 3AM, auto-update all, send notification
0 3 * * 0 /home/user/dockcheck.sh -a -n &gt;&gt; /var/log/dockcheck.log 2&gt;&amp;1</code></pre><p>It also supports image backups <code>-b</code> so you can roll back if something breaks, and parallel checks with <code>-x N</code>, for more flag you can check <code>-h</code> flag for help.</p><p><strong>Use this if:</strong> You're comfortable with the terminal, run a Linux homelab, and want something lightweight and auditable (it's a bash script, you can read the whole thing).</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/mag37/dockcheck?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | dockcheck</a></div><h2 id="cup"><strong>Cup</strong></h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-54.png" class="kg-image" alt="" loading="lazy" width="584" height="394"></figure><p>Cup might be the fastest update checker on this list. It claims to scan <strong>58 images in 3.7 seconds</strong> on a <strong>Raspberry Pi 5</strong>!</p><p>The secret is that instead of pulling images to compare them, it makes minimal API calls - one auth request per registry, then lightweight manifest HEAD requests. This means it <strong>never burns through Docker Hub's pull rate limits</strong>, which matters a lot now that Docker Hub has been tightening limits for unauthenticated users.</p><p><strong>Quick setup:</strong></p><pre><code class="language-bash">#Pull the image 
docker pull ghcr.io/sergi0g/cup

#Run the image with port mapping
docker run -tv /var/run/docker.sock:/var/run/docker.sock -p 9001:9001 ghcr.io/sergi0g/cup serve -p 9001</code></pre><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-48.webp" class="kg-image" alt="" loading="lazy" width="1100" height="479" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-48.webp 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-48.webp 1000w, https://linuxhandbook.com/content/images/2026/03/image-48.webp 1100w" sizes="(min-width: 720px) 720px"></figure><p>Then, if you visit <code>localhost:9001</code> you will get a simple look where you will see all the monitored images, updates available and up-to-date images with a command given to update to the latest image.</p><p>It tells you what's out of date and leaves the rest to you - via a cron job, a webhook consumer, or just checking the dashboard manually. It supports Docker Hub, ghcr.io, Quay, lscr.io, Gitea and more.</p><p><strong>Use this if:</strong> You're hitting Docker Hub rate limits with other tools, or just want the fastest possible update check without anything auto-touching your containers.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/sergi0g/cup?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Cup</a></div><h2 id="dockwatch"><strong>Dockwatch</strong></h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-53.png" class="kg-image" alt="" loading="lazy" width="644" height="587" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-53.png 600w, https://linuxhandbook.com/content/images/2026/03/image-53.png 644w"></figure><p>Simple UI driven way to manage updates &amp; notifications for Docker containers. Dockwatch comes from the <strong>Notifiarr</strong> team; the same folks who built one of the best notification routing systems in the self-hosted world. That DNA shows.</p><p>It's built around a beautiful web UI and a genuinely impressive notification system. The kind of thing you'd show someone to convince them that self-hosting is actually fun.</p><p><strong>Quick compose setup:</strong></p><pre><code class="language-yaml">services:
  dockwatch:
    image: ghcr.io/notifiarr/dockwatch:latest
    ports:
      - "3001:80"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./dockwatch/config:/config
    restart: unless-stopped</code></pre><p>Once you're done, run the command:</p><pre><code class="language-bash">docker compose up -d
</code></pre><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-50.png" class="kg-image" alt="" loading="lazy" width="1119" height="485" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-50.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-50.png 1000w, https://linuxhandbook.com/content/images/2026/03/image-50.png 1119w" sizes="(min-width: 720px) 720px"></figure><p>Then visit the <code>localhost:3001</code>, you will see the advanced setup, which shows a beautiful UI giving you information about disk usage, network I/O, CPU usage, memory usage and updates available for the images.</p><p><strong>Use this if</strong>: You want a feature-rich dashboard with serious notification chops, especially if you're already in the Notifiarr/Servarr ecosystem.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/Notifiarr/dockwatch?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Dockwatch</a></div><h2 id="nicholas-fedorwatchtower"><strong>nicholas-fedor/watchtower</strong></h2><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-52.png" class="kg-image" alt="" loading="lazy" width="644" height="587" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-52.png 600w, https://linuxhandbook.com/content/images/2026/03/image-52.png 644w"></figure><p>For Those Who Don't Want to Change Anything. Okay, real talk. Maybe you've been running Watchtower for years. Your whole homelab is tuned around it. Your cron jobs reference it. Your muscle memory knows the flags. You don't want to learn a new tool.</p><p>Fair. Enter <strong>nicholas-fedor/watchtower</strong> - a community-maintained fork that picks up exactly where the archived original left off.</p><pre><code class="language-bash"># Before (archived, no longer works on newer Docker versions):
image: containrrr/watchtower

# After (actively maintained):
image: nickfedor/watchtower</code></pre><p><strong>Quick setup:</strong></p><pre><code class="language-yaml"># Get the compose file 
curl -L https://raw.githubusercontent.com/nicholas-fedor/watchtower/refs/heads/main/examples/default/docker-compose.yaml -o docker-compose.yaml

# Run command
docker compose up -d</code></pre><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/image-51.png" class="kg-image" alt="" loading="lazy" width="1418" height="477" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-51.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-51.png 1000w, https://linuxhandbook.com/content/images/2026/03/image-51.png 1418w" sizes="(min-width: 720px) 720px"></figure><p>After this, the expected behaviour is it will monitor all running containers on the host and every 24 hours, it will poll if the monitored containers have updated image digests; if available, it will pull the updated image without changing the previous configurations.</p><p> auto-updates everything it can see, by default. There's no semantic versioning awareness, no dashboard, no diff before it updates</p><p><strong>Use this if:</strong> You want zero migration friction and just need the original Watchtower to keep running on modern Docker.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/nicholas-fedor/watchtower?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | nicholas-fedor/watchtower</a></div><h2 id="so-which-one-to-choose"><strong>So, which one to choose?</strong></h2><p>Yes, if you are impressed with all of these here, I will give you one line suggestions: </p><p>Want notification-only, no auto-updates - <strong>Diun </strong>or<strong> Cup</strong>,  Want a web UI for your homelab - <strong>Tugtainer</strong> or <strong>WUD </strong>or <strong>Dockwatch</strong>,  Closest Watchtower replacement with smarter auto-updates - <strong>WUD</strong>, Terminal-first, minimal dependencies - <strong>dockcheck</strong>, Running Kubernetes or Swarm - Only <strong>Diun</strong> supports that, Want zero migration from the original Watchtower - <strong>nicholas-fedor/watchtower</strong>, Already in the Notifiarr/Servarr ecosystem - <strong>Dockwatch</strong> is a natural fit.</p><p><strong><em>Know another tool worth adding? Drop it in the comments.</em></strong></p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[I Like This Fuzzy Search Finder Better Than Find Command in Linux]]></title>
                    <description><![CDATA[fzf is an interactive fuzzy finder for Linux that makes navigating files, command history, and directories faster and easier than the find command.]]></description>
                    <link>https://linuxhandbook.com/blog/fzf-command/</link>
                    <guid isPermaLink="false">69ca44afdf009b000197e97c</guid>

                        <category><![CDATA[blog]]></category>

                        <dc:creator><![CDATA[LHB Community]]></dc:creator>

                    <pubDate>Mon, 30 Mar 2026 16:36:23 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/03/fzf-find-fuzzy-search.webp" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/03/fzf-find-fuzzy-search.webp" alt="I Like This Fuzzy Search Finder Better Than Find Command in Linux"/> <p>There are two main tools for searching files in Linux:</p><ul><li>find for <a href="https://linuxhandbook.com/find-files-by-name/" rel="noreferrer">finding files by names</a> and attributes</li><li><a href="https://linuxhandbook.com/grep-command-examples/" rel="noreferrer">grep for finding files</a> by its content</li></ul><p>You <a href="https://linuxhandbook.com/xargs-command/" rel="noreferrer">combine find with xargs</a> and you have an outstanding search tool in your hands.</p><p>I am not denying the power of find command. I have just explored another tool that does the same job with much more ease.</p><p>That tool is fzf, an interactive command line utility that implements a fuzzy search algorithm to search through all sorts of list: files, command history, processes, hostnames, bookmarks, git commits, and so on. </p><p>As you can imagine, it has the ability to make your life a lot easier.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">💡</div><div class="kg-callout-text">Fuzzy searching means the tool will search through the files for not exact matches, but approximate matches.</div></div><p>I have explored fzf, liked it and I am going to share the features I love in fzf. I hardly touch find now.</p><h2 id="search-and-selection">Search and Selection</h2><p><a href="https://github.com/junegunn/fzf?ref=linuxhandbook.com">fzf</a> can be run by simply entering the command in the terminal. It searches through all the files that are the working directory where the command is being run. The basic usage is quite simple and can be understood easily. To start, just enter:</p><pre><code>fzf</code></pre><p>As soon as you run the command, fzf opens up and starts listing all the files inside the current working directory. You can see at the bottom two numbers in a fraction, the numerator denoting how many files match the search prompt and the denominator denoting how many total files it is searching through.</p><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/03/fzf_search-example_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/03/fzf_search-example.webm" poster="https://img.spacergif.org/v1/945x701/0a/spacer.png" width="945" height="701" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="background: transparent url('https://linuxhandbook.com/content/media/2026/03/fzf_search-example_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:06</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🚧</div><div class="kg-callout-text">If you run the command and not input anything, it will keep evaluating the files in the working directory, more often than not spiking the CPU and RAM usage.</div></div><p>There are a number of ways to input the search, which work like this:</p><p>To fuzzy search for a keyword simply as it is:</p><pre><code>keyword</code></pre><p>This is the way to get exact-matched results, i.e. item that include the keyword:</p><pre><code>'keyword</code></pre><p>This is how you look for items that either start or end with the keyword:</p><pre><code>'keyword'</code></pre><p>To find items that start with the keyword:</p><pre><code>^keyword</code></pre><p>To find files that end with .ext extension.</p><pre><code>.ext$</code></pre><p>There are options using which you can find anything <em>but</em> the keyword you're looking for.</p><p>To find all files which do not include the keyword:</p><pre><code>!keyword</code></pre><p>This finds all files to that do start with the keyword:</p><pre><code>!^keyword</code></pre><p>Find all the files that do not have the .ext extension:</p><pre><code>!.ext$</code></pre><p>These options might seem like they're a bit much to remember, but as you get used to the program, remembering the syntax will become second nature. </p><p>After you give the input, you get the list of items matching the criteria, with the most relevant results closest to the search bar at the bottom. When you press enter on a result, fzf exits with the file location displayed. You can even navigate using the mouse, scrolling and clicking the results.</p><h2 id="preview-mode">Preview Mode</h2><p>Using the preview mode, you can run a command that you specify for every selection that you get from fzf. </p><p>For example, if you want to read every single file that you select when you search for something, you can use the <em>cat</em> command to do so:</p><pre><code>fzf --preview 'cat {}'</code></pre><p>The working of this command can be seen better in a video.</p><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/03/fzf_preview_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/03/fzf_preview.webm" poster="https://img.spacergif.org/v1/945x701/0a/spacer.png" width="945" height="701" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="background: transparent url('https://linuxhandbook.com/content/media/2026/03/fzf_preview_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:09</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><h3 id="previewing-images">Previewing Images</h3><p>You can use the preview window to even see photos on a terminal that supports graphics (duch has <a href="https://itsfoss.com/ghostty-terminal-features/?ref=linuxhandbook.com" rel="noreferrer">Ghostty</a>) using Chafa, Kitty, ImgCat etc. The best, in my experience, has been Chafa. You can see how to install it <a href="https://hpjansson.org/chafa/download/?ref=linuxhandbook.com" rel="noreferrer">here</a>. Now to preview images, enter this command:</p><pre><code>fzf --preview 'chafa {}'</code></pre><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/03/fzf_preview-images_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/03/fzf_preview-images.webm" poster="https://img.spacergif.org/v1/1020x766/0a/spacer.png" width="1020" height="766" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="background: transparent url('https://linuxhandbook.com/content/media/2026/03/fzf_preview-images_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:09</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><h2 id="display-modes">Display Modes</h2><p>There are 3 different display modes that come with fzf: default, full and minimal modes. On plain application with the command, the difference in the interface doesn't seem like much:</p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/fzf_display-styles.webp" class="kg-image" alt="display modes with fzf" loading="lazy" width="1399" height="1159" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/fzf_display-styles.webp 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/fzf_display-styles.webp 1000w, https://linuxhandbook.com/content/images/2026/03/fzf_display-styles.webp 1399w" sizes="(min-width: 720px) 720px"></figure><p>But there are a huge number of attributes you can modify to change the look of fzf as you please. Some of the most useful ones are:</p><h3 id="height">Height</h3><p>Using this, you can choose how much of the terminal window fzf will occupy:</p><pre><code>fzf --height=40%</code></pre><p>Setting the value at ~100 will cause fzf to occupy the entire window.</p><h3 id="border">Border</h3><p>By default, fzf has no solid border. But it does offer a number of options if you want one:</p><pre><code>fzf --border=&lt;style&gt;</code></pre><p>Some of the styles that it offers are:</p><ul><li><strong>rounded:</strong> gives (obviously) round borders.</li><li><strong>sharp:</strong> gives (again, obviously) sharp borders.</li><li><strong>bold:</strong> bold-line borders.</li><li><strong>double:</strong> double-lined borders.</li><li><strong>horizontal:</strong> borders only at the top and the bottom.</li><li><strong>vertical:</strong> borders only on right and left edges.</li><li><strong>top:</strong> only at the top.</li><li><strong>bottom:</strong> only at the bottom.</li><li><strong>left:</strong> only on the left.</li><li><strong>right:</strong> only on the right.</li></ul><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/fzf_double-borders.webp" class="kg-image" alt="double border with fzf" loading="lazy" width="1564" height="1174" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/fzf_double-borders.webp 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/fzf_double-borders.webp 1000w, https://linuxhandbook.com/content/images/2026/03/fzf_double-borders.webp 1564w" sizes="(min-width: 720px) 720px"></figure><p>There are other options as well.</p><h3 id="layout">Layout</h3><p>In the default settings, the fzf starts from the bottom of the screen, but you can reverse that using:</p><pre><code>fzf --layout=reverse</code></pre><p>A simpler command to do the same is:</p><pre><code>fzf --reverse</code></pre><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/03/fzf_reverse.webp" class="kg-image" alt="reverse search result with fzf fuzzy search" loading="lazy" width="1564" height="1174" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/fzf_reverse.webp 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/fzf_reverse.webp 1000w, https://linuxhandbook.com/content/images/2026/03/fzf_reverse.webp 1564w" sizes="(min-width: 720px) 720px"></figure><p>There is even a specific case where you can get fzf starting from the top of the window, but the prompt will be at the bottom:</p><pre><code>fzf --layout=reverse-list</code></pre><h3 id="margin">Margin</h3><p>You can add a margin with a command with the following syntax:</p><pre><code>fzf --margin T%, R%, B%, L%</code></pre><p>Where T, R, B and L stand for top, right, bottom and left respectively. To have the same margin in all directions, you can simply enter a single value.</p><h3 id="padding">Padding</h3><p>The padding option is relevant only if you're using a border as well. This is the gap between the actual contents of the command and the border of the same. It works the same way as margin:</p><pre><code>fzf --padding T%, R%, B%, L%</code></pre><p>where T, R, B and L are top, right, bottom and left percentages respectively.</p><p>There are more advanced options for modifications which change how the list section or the input section look. For the list section, you can enable/disable multi-selection, highlighting, line wrapping, and a scrollbar. You can even enable tracking, in which case the selected result will be tracked while the results are being updated. You can add a gap between result lines (<em>and</em> modify what the gap looks like).</p><p>For the input section, you can change the prompt, information style, enable/disable a separator, add ghost text, add borders or label, or even disable the section entirely! There are more options for modification of both of these sections, in case this doesn't satiate you.</p><p>You can see all of these options using:</p><pre><code>fzf --man</code></pre><h2 id="stdin">stdin</h2><p>fzf works on standard input as well, and you can pipe reults into it to search through them. For example, for searching only through the results of the <em>ls</em> command, you can enter:</p><pre><code>ls | fzf</code></pre><p>This doesn't have to be just <em>ls</em>, it can be the result of any command that you would want to search through.</p><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/03/fzf_stdin_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/03/fzf_stdin.webm" poster="https://img.spacergif.org/v1/945x701/0a/spacer.png" width="945" height="701" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="background: transparent url('https://linuxhandbook.com/content/media/2026/03/fzf_stdin_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:08</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><h2 id="shell-integration">Shell Integration</h2><p>One of the most useful features of fzf is that it can directly integrate into your terminal of choice. This is great, especially if you spend a lot of time at the terminal. There are various shortcuts that search with different intentions, which are:</p><ul><li><strong>Ctrl+R:</strong> To search through the command history.</li><li><strong>Ctrl+T:</strong> To search for files in the working directory, as you would when using fzf normally.</li><li><strong>Alt+C:</strong> To search for directories within the working directory.</li></ul><p>But first, you need to integrate it into your terminal. Various shells work with different commands:</p><p>For bash:</p><pre><code>eval "$(fzf --bash)"</code></pre><p>For zsh:</p><pre><code>source &lt;(fzf --zsh)</code></pre><p>For fish:</p><pre><code>fzf --fish | source</code></pre><p>Run these commands depending on what shell you're using, and you're good to go.</p><h2 id="fuzzy-completion-in-terminal">Fuzzy Completion in Terminal</h2><p>You can use fzf to enhance the autocompletion that the terminal provides. This feature is valid only for bash and zsh, however. For any command where you have to give the location of a file or a directory, you can do with fzf integrated, simply by putting "**" before pressing Tab key. So for example, if I want to <em>cd</em> into a directory that is deep within my working directory, I can just type:</p><pre><code>cd **&lt;Tab&gt;directory keyword</code></pre><p>This is better shown in action in this video:</p><figure class="kg-card kg-video-card kg-width-regular" data-kg-thumbnail="https://linuxhandbook.com/content/media/2026/03/fzf_fuzzy-completion_thumb.jpg" data-kg-custom-thumbnail="">
            <div class="kg-video-container">
                <video src="https://linuxhandbook.com/content/media/2026/03/fzf_fuzzy-completion.webm" poster="https://img.spacergif.org/v1/939x701/0a/spacer.png" width="939" height="701" loop="" autoplay="" muted="" playsinline="" preload="metadata" style="background: transparent url('https://linuxhandbook.com/content/media/2026/03/fzf_fuzzy-completion_thumb.jpg') 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon" aria-label="Play video">
                        <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container kg-video-hide">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon" aria-label="Play video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide" aria-label="Pause video">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"></rect>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:09</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate" aria-label="Adjust playback speed">1×</button>
                        <button class="kg-video-unmute-icon" aria-label="Unmute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"></path>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide" aria-label="Mute">
                            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"></path>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            
        </figure><p>Similarly, you can use the same method to use <em>kill</em>/<em>pkill</em> to kill processes, or <em>nano</em>/<em>vim</em> files that you want to edit, and so on. It is extremely convenient as long as what you're looking for is within your working directory, working almost like Harry Potter's <em>accio</em> spell.</p><h2 id="changing-the-search-parameters">Changing the Search Parameters</h2><p>There are various options to even modify how the searching works on fzf. By default, the search works on extended mode, other than that, you can toggle case sensitivity using <em>--ignore-case</em> or <em>--no-ignore-case</em> or even use <em>--smart-case</em>, where the case sensitivity is off by default, but turned on if there are any uppercase letters in the input.</p><p>It also offers two searching algorithms, where the default one is v2. The algorithm v1 is supposed to be faster but not as accurate as v2. You can change it using <em>--algo=v1</em>.</p><h2 id="vim-integration">Vim Integration</h2><p>In case you use Vim, here's another extra feature for you. You can enable it within the editor by adding a line to your Vim configuration file, which looks like this:</p><pre><code>set rtp+=&lt;fzf location&gt;</code></pre><p>This location is usually /usr/bin/fzf on Linux, but can be /usr/local/opt/fzf if you've used Homebrew to install it.</p><h2 id="how-to-get-fzf">How to get fzf</h2><p>fzf is available on the default repositories of most distributions, making it very easy to install. On Ubuntu based systems, just enter:</p><pre><code>sudo apt install fzf</code></pre><p>On Fedora based systems:</p><pre><code>sudo dnf install fzf</code></pre><p>You can use Homebrew on macOS:</p><pre><code>brew install fzf</code></pre><p>If you want to find the instructions for any other systems, you can find it on the website quite easily.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/junegunn/fzf?tab=readme-ov-file&ref=linuxhandbook.com#installation" class="kg-btn kg-btn-accent">Install fzf</a></div><h2 id="final-thoughts">Final Thoughts</h2><p>There are still many more advanced features that fzf provides, which can all be found on the official GitHub page <a href="https://github.com/junegunn/fzf?ref=linuxhandbook.com" rel="noreferrer">right here</a>. If not the page, you can visit the <em>man</em> page of fzf (which is extremely well written) to find everything modifiable on fzf. With the exhaustingly immense amount of thematic as well as search-parameter customization that fzf gives you, it can be one of the most effective tools in your roster.</p><p>Let us know what you think about this tool in the comments. Cheers!</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[These 11 Open Source Tools Completely Improved My Docker Workflow]]></title>
                    <description><![CDATA[I tested dozens of Docker tools in my life so far. These 11 open source picks actually improved my workflow. Make Docker easier, faster, and more efficient.]]></description>
                    <link>https://linuxhandbook.com/blog/docker-workflow-tools/</link>
                    <guid isPermaLink="false">69bbb872df009b000197caf4</guid>

                        <category><![CDATA[blog]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Wed, 25 Mar 2026 20:03:42 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/03/docker-management-tools.webp" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/03/docker-management-tools.webp" alt="These 11 Open Source Tools Completely Improved My Docker Workflow"/> <p>Once you're running more than 3-4 containers, you'll run into the same questions: <em><strong>Which container is eating my RAM? Why did this crash at 3 am? My images are 800 MB and I have no idea why</strong>.</em> </p><p>Here's the thing. Docker is an ecosystem and there exist tools that can help you deal with Docker containers and images more effectively.</p><p>For past couple of years, I have tried many such tools. I have used them across real scenarios and dev setups that usually involve monitoring tools, TUIs, log viewers, image analyzers, and more; and narrowed it down to the ones that actually solve real problems, which enhances the total experience of your Docker.</p><p>These tools exist specifically to answer those questions and I'll tell you exactly which situations each one is built for.</p><p><strong>Short on time?</strong> See the details in the table below: Here's a quick overview before the full breakdowns.</p><h2 id="comparison-table">Comparison Table</h2><table>
<thead>
<tr>
<th>Tool</th>
<th>Best For</th>
<th>Interface</th>
<th>Auto-Action</th>
<th>Our Pick</th>
</tr>
</thead>
<tbody>
<tr>
<td>Lazydocker</td>
<td>Terminal power users</td>
<td>TUI</td>
<td>✅ restart/rebuild</td>
<td>🏆 Top Pick</td>
</tr>
<tr>
<td>Oxker</td>
<td>Speed + zero deps</td>
<td>TUI</td>
<td>✅ start/stop/exec</td>
<td>Best lean TUI</td>
</tr>
<tr>
<td>Dockge</td>
<td>Compose stack management</td>
<td>Web UI</td>
<td>✅ stack up/down</td>
<td>Best Compose UI</td>
</tr>
<tr>
<td>Dozzle</td>
<td>Live log viewing</td>
<td>Web UI</td>
<td>❌</td>
<td>Best log viewer</td>
</tr>
<tr>
<td>Dive</td>
<td>Image layer analysis</td>
<td>TUI</td>
<td>❌</td>
<td>Best image debugger</td>
</tr>
<tr>
<td>Dockhand</td>
<td>Security-first Docker management</td>
<td>Web UI</td>
<td>✅ safe-pull scan</td>
<td>Best security pick</td>
</tr>
<tr>
<td>Kompose</td>
<td>Compose → Kubernetes migration</td>
<td>CLI</td>
<td>✅ convert</td>
<td>Best for K8s movers</td>
</tr>
<tr>
<td>Docker Slim</td>
<td>Image size optimization</td>
<td>CLI</td>
<td>✅ builds slim image</td>
<td>Best image shrinker</td>
</tr>
<tr>
<td>Docker Autoheal</td>
<td>Self-healing containers</td>
<td>Labels</td>
<td>✅ restart</td>
<td>Best reliability pick</td>
</tr>
<tr>
<td>Cup</td>
<td>Image update awareness</td>
<td>TUI + Web</td>
<td>❌ notify only</td>
<td>Best rate-limit safe</td>
</tr>
<tr>
<td>ctop</td>
<td>Real-time resource monitoring</td>
<td>TUI</td>
<td>❌</td>
<td>🏆 Editor's Pick</td>
</tr>
</tbody>
</table>
<p>Now let's go through each one.</p><h2 id="lazydockerall-in-one-terminal-ui-for-docker-management">Lazydocker - All-in-one terminal UI for Docker management</h2><p> Lazydocker is a keyboard-driven terminal UI that brings containers, logs, stats, images, and volumes into a single split-panel view - making it the most practical way to manage Docker entirely from the terminal without memorizing dozens of commands.</p><p><strong>Who it's best for: </strong>Developers and homelabbers who live in the terminal and want a single interface to replace <code>docker ps</code>, <code>docker logs</code>, <code>docker stats</code>, and <code>docker exec</code> all at once.</p><p><strong>Quick Setup:</strong></p><pre><code class="language-bash"># Homebrew (Linux or macOS):
brew install lazydocker

# Or via Go:
go install github.com/jesseduffield/lazydocker@latest

# No install needed — run via Docker:
docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  lazyteam/lazydocker</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-55.png" class="kg-image" alt="Lazydocker showing running containers, images, volumes, etc." loading="lazy" width="1315" height="594" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-55.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-55.png 1000w, https://linuxhandbook.com/content/images/2026/03/image-55.png 1315w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Lazydocker showing running containers, images, volumes, etc.</span></figcaption></figure><p>You can see on the left side, there is a normal Docker ps command and on the right side, there is <code>lazydocker</code> runnning showing all running containers, images, volumes, also logs, stats, config, CPU usage, etc.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-56.png" class="kg-image" alt="Lazydocker terminal command options" loading="lazy" width="1315" height="594" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-56.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-56.png 1000w, https://linuxhandbook.com/content/images/2026/03/image-56.png 1315w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Lazydocker terminal command options</span></figcaption></figure><p>It has many more commands to perform as shown below: you can see them by typing <code>x</code> in the terminal.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros: </strong></b><br>- Real-time CPU/memory graphs per container<br>- Compose-aware - groups services instead of a flat container list- Restart, exec, remove, rebuild <br>- all without leaving the TUI- Extremely polished for a terminal tool</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Keyboard navigation learning curve: takes about 10-15 minutes to feel comfortable<br>- No multi-host support - manages one Docker daemon at a time</div></div><p><strong>Verdict:</strong> The safe default for anyone who prefers the terminal. Install it once, and you'll stop missing raw Docker commands within 20 minutes.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/jesseduffield/lazydocker?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Lazydocker</a></div><h2 id="oxkerlightweight-tui-for-speed-and-zero-dependencies">Oxker - Lightweight TUI for speed and zero dependencies</h2><p>Oxker is a Docker container TUI written in Rust that delivers a multi-panel interface including a live container list, log streaming, and resource stats, in a single binary with no runtime dependencies whatsoever.</p><p><strong>Who it's best for: </strong>Terminal users who want Lazydocker-style visibility but with a leaner footprint - no Go runtime, no Node.js, nothing. Also great for Rust fans and anyone in constrained environments.</p><p><strong>Quick Setup:</strong></p><pre><code class="language-bash"># Cargo:
cargo install oxker

# Homebrew:
brew install oxker

# Zero-install via Docker (read-only socket):
docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock:ro \
  ghcr.io/mrjackwills/oxker

# Arch Linux AUR:
paru -S oxker</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-57.png" class="kg-image" alt="Oxker in action showing CPU, Memory and containers. " loading="lazy" width="1266" height="783" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-57.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-57.png 1000w, https://linuxhandbook.com/content/images/2026/03/image-57.png 1266w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Oxker in action showing CPU, Memory and containers. </span></figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-58.png" class="kg-image" alt="Oxker keymapping in terminal." loading="lazy" width="1154" height="461" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-58.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-58.png 1000w, https://linuxhandbook.com/content/images/2026/03/image-58.png 1154w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Oxker keymapping in terminal.</span></figcaption></figure><p>After running the commands, you can see a beautiful TUI running showing containers, CPU, Memory, Ports and you can see the helpful commands to run inside, using <code>h</code> If you need to execute, you can use <code>e</code> after selecting the container, use <code>q</code> to quit from the current session.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Single Rust binary having truly zero dependencies<br>- Multi-panel layout including container list + logs + resource stats <br>- Compose-aware (shows which project a container belongs to)<br>- Can run with read-only socket mount for extra safety</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- ~1.5k GitHub stars; smaller community, fewer tutorials if you get stuck<br>- Strictly container-focused - no image or volume management<br>- Cargo install requires Rust toolchain (use Docker method to skip this)</div></div><p><strong>Verdict:</strong> Way better than its star count suggests. If you want a leaner, faster alternative to Lazydocker with zero dependencies, give Oxker 5 minutes; you might just switch.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/mrjackwills/oxker?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Oxker</a></div><h2 id="dockgeweb-ui-for-docker-compose-stack-management">Dockge - Web UI for Docker Compose stack management</h2><p>Dockge is a self-hosted web UI built specifically for Docker Compose stack management, letting you create, edit, start, stop, and monitor compose stacks through a clean browser interface, while keeping your <code>compose.yaml</code> files exactly where they are on disk.</p><p><strong>Who it's best for: </strong>Homelab users and solo developers who manage multiple compose stacks and want a visual interface for them without switching to a heavy all-in-one tool like Portainer.</p><p><strong>Quick Setup:</strong></p><pre><code class="language-bash"># Create directories that store your stacks and stores Dockge's stack
mkdir -p /opt/stacks /opt/dockge
cd /opt/dockge

# Download the compose.yaml
curl https://raw.githubusercontent.com/louislam/dockge/master/compose.yaml --output compose.yaml

# Start the server
docker compose up -d

# If you are using docker-compose V1 or Podman
# docker-compose up -d</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-61.png" class="kg-image" alt="Dockge self-hosted Web-UI." loading="lazy" width="1913" height="972" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-61.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-61.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/03/image-61.png 1600w, https://linuxhandbook.com/content/images/2026/03/image-61.png 1913w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Dockge self-hosted Web-UI.</span></figcaption></figure><p>After running commads you'll have a Dashboard UI on the web at <code>customised</code>, where you can see the stack, compose and also you can deploy your own customised stack by defining the containers and env variables, networks, ports, etc.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-60.png" class="kg-image" alt="Dockge inbuilt docker run to compose.yaml converter." loading="lazy" width="1913" height="972" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-60.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-60.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/03/image-60.png 1600w, https://linuxhandbook.com/content/images/2026/03/image-60.png 1913w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Dockge inbuilt docker run to compose.yaml converter.</span></figcaption></figure><p>Dockge has a built-in <code>docker run</code> to <code>compose.yaml</code> converter. Paste in a run command from Docker Hub and get a formatted compose file out. This alone saves 10 minutes every time.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros: </strong></b><br>- Beautiful, reactive UI, feels modern and fast<br>- File-based storage, no database lock-in, your files stay portable<br>- Live terminal output when bringing stacks up/down<br>- Built-in <code spellcheck="false" style="white-space: pre-wrap;">docker run</code> → <code spellcheck="false" style="white-space: pre-wrap;">compose.yaml</code> converter</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br><b><strong style="white-space: pre-wrap;">-</strong></b> Compose-only, standalone containers are invisible to it<br>- Single-user design, no role-based access control<br>- Not suitable for team environments needing multi-user permissions<br>- No Kubernetes support</div></div><p><strong>Verdict:</strong> The best Compose stack UI for homelab setups, period. If you're already using compose-based setups, this replaces the <code>docker compose up -d</code> + vim loop entirely.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/louislam/dockge?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Dockge</a></div><h2 id="dozzleweb-based-real-time-container-log-viewer">Dozzle - Web-based real-time container log viewer</h2><p>Dozzle is a lightweight, self-hosted web application that streams <a href="https://linuxhandbook.com/docker-logging/" rel="noreferrer">Docker container logs</a> directly to your browser in real time - zero storage, zero persistence, just live log output from your containers, accessible from any device on your network.</p><p><strong>Who it's best for: </strong>Anyone who regularly SSHs into servers just to check container logs - especially useful for teams where non-SSH users need log visibility, or for checking logs from a phone or tablet.</p><p>Quick Setup:</p><pre><code class="language-bash"># Pull image
docker pull amir20/dozzle:latest

# Run the container
docker run --name dozzle -d --volume=/var/run/docker.sock:/var/run/docker.sock -p 8082:8080 amir20/dozzle:latest</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-62.png" class="kg-image" alt="Dozzle dashboard showing system overview." loading="lazy" width="1913" height="1016" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-62.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-62.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/03/image-62.png 1600w, https://linuxhandbook.com/content/images/2026/03/image-62.png 1913w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Dozzle dashboard showing system overview.</span></figcaption></figure><p>This one is one of the most elegant UI for browsers I have ever used and ever seen. You see a minimalist, simple and elegant presentation of your stack, containers, the CPU and memory usage for each stack. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-63.png" class="kg-image" alt="Dozzle SQL support for data retrieval." loading="lazy" width="1913" height="971" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-63.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-63.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/03/image-63.png 1600w, https://linuxhandbook.com/content/images/2026/03/image-63.png 1913w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Dozzle SQL support for data retrieval.</span></figcaption></figure><p>You also get the SQL analytics for your stack, so you can search and retrieve from your database.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br><b><strong style="white-space: pre-wrap;">-</strong></b> Zero storage footprint means purely streaming, nothing written to disk<br>- Multi-stream view so that you can watch several containers side by side<br>- Keyword search and highlighting in live streams<br>- Multi-host support via agent mode</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- No log persistence; can't look back at logs from before Dozzle was running<br>- No alerting, shows logs but doesn't act on them<br>- Basic auth only; not suitable for teams needing fine-grained access</div></div><p><strong>Verdict</strong>: One of the most immediately useful tools on this entire list. Bookmark it, use it from your phone at midnight when something breaks, never SSH in just for logs again.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/amir20/dozzle?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Dozzle</a></div><h2 id="divefor-analyzing-docker-image-content">Dive - For analyzing Docker image content</h2><p>Dive is an interactive terminal tool that lets you explore every layer of a Docker image, showing exactly which files each <code>RUN</code>, <code>COPY</code>, or <code>ADD</code> instruction added, modified, or deleted, so you can see precisely why your images are larger than they should be.</p><p><strong>Who it's best for: </strong>Developers who suspect their images are bloated but don't know where the size is coming from and anyone who wants to find and eliminate wasted space before shipping to production or a registry.</p><p><strong>Quick Setup:</strong></p><pre><code class="language-bash"># Set parameter
DIVE_VERSION=$(curl -sL "https://api.github.com/repos/wagoodman/dive/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')

# Download 
curl -fOL "https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}/dive_${DIVE_VERSION}_linux_amd64.deb"

# Install
sudo apt install ./dive_${DIVE_VERSION}_linux_amd64.deb</code></pre><p>Then, after installation, you have to run the command:</p><pre><code class="language-bash">dive &lt;image name&gt;</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-64.png" class="kg-image" alt="Dive showing image analysis in terminal." loading="lazy" width="1248" height="774" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-64.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-64.png 1000w, https://linuxhandbook.com/content/images/2026/03/image-64.png 1248w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Dive showing image analysis in terminal.</span></figcaption></figure><p>You will see the layers of the image, the layer contents, the layer details and Image details, along with the permissions and the file structure it holds.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Layer-by-layer visualization of exactly what's eating your image size<br>- Works against any image, local, registry, or built with Buildx<br>- CI mode for automated image efficiency checks<br>- 53k+ GitHub stars, one of the most trusted tools in the Docker ecosystem</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text">Cons: <br>- Shows you the problem, doesn't fix it, that's up to you <br>- Can be slow on images over 1GB while processing all layers<br>- Interactive TUI only, no automated reports or scheduled runs<br>- You need the image locally to analyze it</div></div><p><strong>Verdict:</strong> Run this on any image you've built yourself. I promise you'll find something to trim. It's now a standard step in my build process.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/wagoodman/dive?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Dive</a></div><h2 id="dockhanddocker-web-ui-with-built-in-security-scanning">Dockhand - Docker web UI with built-in security scanning</h2><p>Dockhand is a self-hosted Docker management web UI that scans images for vulnerabilities <strong><em>before</em></strong> deploying them, using a "safe-pull" approach where new image versions are scanned in a temporary tag and only promoted if they pass your configured CVE thresholds.</p><p><strong>Who it's best for: </strong>Teams and individuals who want a Docker web UI that actively prevents vulnerable images from reaching their servers, especially those who need SSO authentication without paying for Portainer Business.</p><p><strong>Quick Setup:</strong></p><pre><code class="language-bash">docker run -d \
  --name dockhand \
  --restart unless-stopped \
  -p 3000:3000 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v dockhand_data:/app/data \
  fnsys/dockhand:latest</code></pre><p>Just run this one single command and your <code>dockhand</code> is running on <code>localhost:3000</code></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-67.png" class="kg-image" alt="Dockhand showing environment overview." loading="lazy" width="1032" height="808" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-67.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-67.png 1000w, https://linuxhandbook.com/content/images/2026/03/image-67.png 1032w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Dockhand showing environment overview.</span></figcaption></figure><p>You need to add an environment first by giving the Public IP first then you can see all your images, containers, stacks, etc. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-68.png" class="kg-image" alt="Dockhand Auth support." loading="lazy" width="1914" height="765" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-68.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-68.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/03/image-68.png 1600w, https://linuxhandbook.com/content/images/2026/03/image-68.png 1914w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Dockhand Auth support with SSO.</span></figcaption></figure><p>It supports Google, Azure AD, Okta, Keycloak and Auth0 for authentication. Portainer charges for this in their Business tier. Dockh<br>and includes it in the free tier. </p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Scans images <i><b><strong class="italic" style="white-space: pre-wrap;">before</strong></b></i> they run, catches CVEs before they reach your server<br>- Free OIDC/SSO support: Google, Azure AD, Okta, Keycloak, Auth0- Git-based stack deployment for proper GitOps workflows<br>- Base image hardened with Wolfi packages (minimal CVE surface)</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- BSL 1.1 license, source is viewable but not OSI-certified; converts to Apache 2.0 in 2029<br>- Heavier than minimal UIs like Dockge<br>- RBAC and LDAP are paid enterprise-only features<br>- Smaller community than Portainer, fewer tutorials and third-party guides</div></div><p><strong>Verdict:</strong> The only Docker web UI I've seen that actively blocks vulnerable image deployments. If security matters in your setup and you want SSO without paying Portainer Business prices, Dockhand is worth knowing about.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/Finsys/dockhand?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Dockhand</a></div><h2 id="komposefor-k8s-migration">Kompose - For K8s Migration</h2><p>Kompose is a command-line tool that automatically translates Docker Compose files into Kubernetes manifests, generating Deployments, Services, PersistentVolumeClaims, and ConfigMaps so you have a working starting point for your Kubernetes migration instead of writing everything from scratch.</p><p><strong>Who it's best for: </strong>Developers and teams who have existing Docker Compose setups and are beginning a migration to Kubernetes; Kompose handles the mechanical translation work so you can focus on the Kubernetes-specific pieces.</p><p><strong>Quick Setup:</strong></p><pre><code class="language-bash"># Build Image
docker build -t kompose https://github.com/kubernetes/kompose.git\#main

# Run 
docker run --rm -it -v $PWD:/opt -w /opt kompose kompose convert
</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-69.png" class="kg-image" alt="Kompose coverting compose-files to manifest files." loading="lazy" width="787" height="869" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-69.png 600w, https://linuxhandbook.com/content/images/2026/03/image-69.png 787w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Kompose coverting compose-files to manifest files.</span></figcaption></figure><p>You can see the configmap, deployment and the service yaml files created after running the <code>kompose</code>. </p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Turns compose files into K8s manifests in one command<br>- Official Kubernetes project, actively maintained, not a side project<br>- Handles volumes, env vars, ports, and basic service dependencies<br>- Multiple output formats: YAML, JSON, and basic Helm chart output</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Output requires review before using in production<br>- No StatefulSets, HPA, or RBAC, you add those yourself<br>- Some compose features drop silently with no warning<br>- No reverse direction (Kubernetes → Compose)</div></div><p><strong>Verdict: </strong>The fastest way to get a working starting point for a Kubernetes migration. Run it, spend 20 minutes cleaning the output instead of 3+ hours writing everything manually.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/kubernetes/kompose?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Kompose</a></div><h2 id="docker-slimfor-docker-image-size-reduction">Docker Slim - For Docker image size reduction</h2><p>Docker Slim (now SlimToolkit) automatically reduces Docker image sizes by running your container, observing exactly which files and libraries it uses at runtime, then rebuilding a new image containing only those things, resulting in size reductions of 10 to 30x without modifying your Dockerfile or application code.</p><p><strong>Who it's best for: </strong>Developers shipping large Docker images to production who want dramatically smaller images for faster CI, faster deploys, and a meaningfully reduced attack surface, especially those using fat base images like Ubuntu, Debian, or full Python/node.</p><p><strong>Quick Setup:</strong></p><pre><code class="language-bash"># Download
curl -sL https://raw.githubusercontent.com/slimtoolkit/slim/master/scripts/install-slim.sh | sudo -E bash -

# Run command
docker-slim build --target &lt;image_name&gt; --http-probe=false</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-70.png" class="kg-image" alt="Docker slim in action compressing the size of the node image." loading="lazy" width="743" height="297" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-70.png 600w, https://linuxhandbook.com/content/images/2026/03/image-70.png 743w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Docker slim in action compressing the size of the node image.</span></figcaption></figure><p>Here you can see the difference between the <code>node:alpine</code> and the <code>node.slim</code> image size after using the <code>docker-slim</code>.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- 10-30x size reduction is realistic and documented across many languages/frameworks<br>- Generates Seccomp and AppArmor security profiles as a bonus side effect<br>- Non-destructive, the original image is always preserved untouched<br>- Works with any base image, any language</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Image quality depends on probe quality; incomplete probing = missing files at runtime<br>- Doesn't work cleanly with stateful apps without carefully designed custom probes<br>- Longer build times as it instruments and runs your container during analysis<br>- Dynamic languages (Python, Ruby, Node.js) need more thorough probing than compiled ones<br></div></div><p><strong>Verdict:</strong> If you're shipping 500MB+ images, Docker Slim should be your next step. Faster CI, faster deploys, smaller attack surface, it pays for the setup time almost immediately.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/slimtoolkit/slim?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Docker Slim</a></div><h2 id="docker-autohealfor-auto-restarting-your-unhealthy-containers">Docker Autoheal - For auto-restarting your unhealthy containers</h2><p>Docker Autoheal monitors running containers for failing health checks and automatically restarts them, filling a gap in Docker's native behavior where containers fail their <code>HEALTHCHECK</code> but Docker leaves them running in an unhealthy state indefinitely rather than restarting them.</p><p><strong>Who it's best for: </strong>Anyone running Docker containers with <code>HEALTHCHECK</code> defined who wants automatic recovery from unhealthy states without setting up Kubernetes or writing their own cron-based monitoring script.</p><p><strong>Quick Setup: </strong></p><pre><code class="language-bash">docker run -d \
    --name autoheal \
    --restart=always \
    -e AUTOHEAL_CONTAINER_LABEL=all \
    -v /var/run/docker.sock:/var/run/docker.sock \
    willfarrell/autoheal</code></pre><p>sample compose file:</p><pre><code class="language-yaml">services:
  autoheal:
    image: willfarrell/autoheal:latest
    restart: always
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - AUTOHEAL_CONTAINER_LABEL=autoheal
      - AUTOHEAL_INTERVAL=5

  my-app:
    image: nginx:alpine
    container_name: demo-app
    labels:
      - "autoheal=true"
    healthcheck:
      # Curl fails if the default Nginx page is missing
      test: ["CMD", "curl", "-f", "http://localhost/"]
      interval: 5s     # Check frequently for the demo
      timeout: 3s
      retries: 2       # Fail quickly
      start_period: 2s</code></pre><p>And now if there is any container in unhealthy status, it will restart that container withing the time interval mentioned in our case 5s.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-71.png" class="kg-image" alt="Docker Autoheal restarting unhealthy containers." loading="lazy" width="1851" height="406" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-71.png 600w, https://linuxhandbook.com/content/images/size/w1000/2026/03/image-71.png 1000w, https://linuxhandbook.com/content/images/size/w1600/2026/03/image-71.png 1600w, https://linuxhandbook.com/content/images/2026/03/image-71.png 1851w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Docker Autoheal restarting unhealthy containers.</span></figcaption></figure><p>Here it restarted the nginx container when it was showing unhealthy status and after some time its again started with status healthy.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Label-based opt-in keeps you explicitly in control of what gets healed<br>- Supports webhook notifications on restart events<br>- Lightweight, it's a bash script in a container, fully auditable</div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Does nothing if containers don't have <code spellcheck="false" style="white-space: pre-wrap;">HEALTHCHECK</code> defined<br>- Treats the symptom (crashes), not the cause; you still need to investigate root issues<br>- No circuit breaker, will keep restarting a broken container indefinitely<br></div></div><p><strong>Verdict:</strong> Small, unassuming, and genuinely useful. If your services have healthchecks and uptime matters, add Autoheal to your compose stack and stop worrying about containers quietly dying overnight.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/willfarrell/docker-autoheal?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Docker Autoheal</a></div><h2 id="cupfor-checking-image-updates-without-rate-limit-issues">Cup - For checking image updates without rate limit issues</h2><p>Cup is an image update checker that tells you which running containers have newer versions available in the registry, using minimal, lightweight API calls against image manifests instead of pulling images, so it never burns through Docker Hub's pull rate limits.</p><p><strong>Who it's best for: </strong>Users who want to stay aware of available image updates but are hitting Docker Hub rate limits with other tools, or who want a fast, lightweight checker that doesn't pollute their image cache.</p><p><strong>Quick Setup:</strong></p><pre><code class="language-bash"># Pull image
docker pull ghcr.io/sergi0g/cup

# Run the image
docker run -tv /var/run/docker.sock:/var/run/docker.sock ghcr.io/sergi0g/cup check &lt;image_name&gt;
</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-73.png" class="kg-image" alt="Cup giving information about available image updates." loading="lazy" width="795" height="600" srcset="https://linuxhandbook.com/content/images/size/w600/2026/03/image-73.png 600w, https://linuxhandbook.com/content/images/2026/03/image-73.png 795w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Cup giving information about available image updates. </span></figcaption></figure><p>Here you can see the node image having <code>14.10</code> tag showing there is a major update available, while when we checked with the <code>lts-krypton</code> its Up to date.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Checked 58 images in 3.7 seconds on a Raspberry Pi 5<br>- Designed from the ground up to not burn Docker Hub rate limits<br>- JSON API for Grafana, Home Assistant, or custom webhook integration<br>- The binary is 5.7MB, genuinely tiny<br></div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Notify-only by design, won't update containers for you<br>- No built-in alerting, use the JSON API + a webhook consumer for notifications<br>- Treats containers individually, no compose-stack grouping<br></div></div><p><strong>Verdict:</strong> The fastest, most rate-limit-friendly way to know which images need updating. Keep it running in server mode with the dashboard bookmarked, one less thing to chase manually.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/sergi0g/cup?tab=readme-ov-file&ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | Cup</a></div><h2 id="ctopreal-time-resource-monitor-for-docker-containers">ctop - Real-time resource monitor for Docker containers</h2><p>ctop is a <code>top</code> like terminal UI that displays real-time resource usage for all running Docker containers, CPU, memory, network I/O, and block I/O in a constantly updating, sortable, color-coded table, making it the fastest way to answer "what is my Docker host actually doing right now?"</p><p><strong>Who it's best for: </strong>Any Docker user who wants an instant, always-accurate view of container resource consumption, especially useful for debugging performance issues, chasing memory leaks, or just understanding what's happening on a new server.</p><p><strong>Quick Setup:</strong></p><pre><code class="language-bash">sudo curl -Lo /usr/local/bin/ctop https://github.com/bcicen/ctop/releases/download/v0.7.7/ctop-0.7.7-linux-amd64

sudo chmod +x /usr/local/bin/ctop</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://linuxhandbook.com/content/images/2026/03/image-74.png" class="kg-image" alt="ctop in action with TUI." loading="lazy" width="599" height="651"><figcaption><span style="white-space: pre-wrap;">ctop in action with TUI.</span></figcaption></figure><p>After installing, you can run the command <code>ctop</code> and can view this terminal UI where there are containers. If you press the right arrow, you can see the CPU, memory, I/O, Environment variables, etc. If you click on any container, you get options to view logs, start, remove, single view, etc.  </p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">✅</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Pros:</strong></b><br>- Sortable by CPU, memory, network I/O, block I/O<br>- Drill into any container for detailed graphs without leaving ctop<br>- Groups containers by their Compose project<br>- Single static binary, drops neatly into <code spellcheck="false" style="white-space: pre-wrap;">/usr/local/bin</code></div></div><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🔴</div><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">Cons:</strong></b><br>- Terminal-only, remote access requires SSH<br>- No historical data, current state only<br>- Not actively maintained (but the Docker stats API it uses doesn't change)<br>- No alerting, shows data, doesn't act on it<br></div></div><p><strong>Verdict:</strong> The first tool I install on any new Docker host. It answers "what's going on?" in two seconds, without opening a browser. If you pick exactly one tool from this list, make it this one.</p><div class="kg-card kg-button-card kg-align-center"><a href="https://github.com/bcicen/ctop?ref=linuxhandbook.com" class="kg-btn kg-btn-accent">GitHub | ctop</a></div><h2 id="faq">FAQ</h2><p>I know you will have some questions so let me answer them, well, at least some of them.</p><p><strong>Do I need all 11 of these tools?</strong><br>No. Most people will get immediate value from 2-3. Start with ctop and Dozzle; those solve universal problems. Add the others based on the specific pain points you're hitting: image size, security scanning, compose management, and so on.<br><br><strong>Are these tools safe to run on a production server?</strong><br>Most of them mount <code>/var/run/docker.sock</code>, which gives them root-equivalent access to your Docker daemon. Never expose Dockge, Dozzle, Dockhand, or Lazydocker directly to the public internet without authentication. Use Tailscale, a VPN, or, at a minimum, HTTPS + basic auth in front of them.<br><br><strong>Do any of these replace Portainer?</strong><br>Dockge is the closest in terms of compose management experience and is arguably better for solo homelab use. But it lacks Portainer's multi-user RBAC, Swarm support, and Kubernetes integration. For teams or larger production environments, Portainer CE or Portainer Business still makes sense. Dockhand replaces Portainer's paid SSO feature for free.<br><br><strong>Will Docker Slim break my application?</strong><br>It can, if the probe doesn't exercise all of your app's code paths. Always test `.slim` images thoroughly before deploying to production. Start with a non-critical service, validate the output image completely, then expand from there.<br><br><strong>Do any of these tools work with Podman?<br>Kompose:</strong> Yes, works with any compose file, runtime-agnostic<br><strong>Dive:</strong> Partial, can analyze OCI-compliant images directly<br><strong>Dockge, Lazydocker, Oxker, ctop, Dozzle, Dockhand:</strong> Docker socket only<br><strong>Docker Slim:</strong> Primarily Docker; SlimToolkit is expanding broader runtime support gradually<br><br><strong>Is ctop still actively maintained?</strong><br>Not with frequent releases, no. But the Docker stats API it uses is stable and doesn't change often, so ctop just keeps working. I've run it without issues for years.</p><h2 id="final-recommendation">Final recommendation</h2><p><strong>Terminal users -</strong> Lazydocker or Oxker give you full management without leaving the terminal.<strong> </strong></p><p><strong>Browser-first access -</strong> Dockge (compose management) + Dozzle (logs) together cover most daily needs. </p><p><strong>Images too big -</strong> Run Dive first to diagnose, then Docker Slim to fix.<strong> Security concerns</strong> - Dockhand scans before it deploys; add it if you care about CVEs reaching your server.<strong> </strong></p><p><strong>Moving to Kubernetes</strong> - Kompose is your first step in the migration</p><p>Use these tools together as they don't conflict. Lazydocker + ctop + Dozzle handles daily monitoring. Dive + Docker Slim handles image hygiene. Docker Autoheal + Cup handles reliability and update awareness.</p><p>If you know more such tools that could help enhance the Docker experience, feel free to drop them in the <strong>comments</strong>!</p>]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[LHB Linux Digest #26.05: New Advanced Docker Course, pingtrace, File Descriptors and More Linux Stuff]]></title>
                    <description><![CDATA[New month, new course!]]></description>
                    <link>https://linuxhandbook.com/newsletter/26-05/</link>
                    <guid isPermaLink="false">69b7cc8ddf009b00019743e1</guid>

                        <category><![CDATA[Newsletter]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 21:08:23 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/02/lhb-newsletter-1.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/02/lhb-newsletter-1.png" alt="LHB Linux Digest #26.05: New Advanced Docker Course, pingtrace, File Descriptors and More Linux Stuff"/> <p>You might remember that I mentioned working on an advanced Docker course a while back. <a href="https://linuxhandbook.com/courses/docker-level-up/">It’s now ready</a>.</p><p>This course focuses on understanding how containers actually work. You get to learn about namespaces, cgroups, networking, image optimization, observability, and container security.</p><p>If you already know <a href="https://linuxhandbook.com/courses/docker/">basic Docker</a> commands and want to <strong>go beyond <code>docker run</code></strong>, this course will help you understand Docker at a deeper level.</p><p>Each module also has a practice lab so that you can put your learning to some testing.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://linuxhandbook.com/courses/docker-level-up/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Advanced Docker Course: Container Internals, Networking, Security and Image Optimization</div><div class="kg-bookmark-description">Level up your Docker skills. Learn container internals, networking, image optimization, observability, and security in this practical course.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://linuxhandbook.com/content/images/icon/Linux-Handbook-New-Logo-194.png" alt=""><span class="kg-bookmark-author">Linux Handbook</span><span class="kg-bookmark-publisher">Yash Kiran Patil</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://linuxhandbook.com/content/images/thumbnail/Docker-Level-Up.png" alt="" onerror="this.style.display = 'none'"></div></a></figure><p>Next week, we will publish a few DIY lab scenarios. Doing it on your own is the best form of learning. Stay tuned 😄</p>
<div class="kg-card kg-cta-card kg-cta-bg-grey kg-cta-minimal    " data-layout="minimal">
            
            <div class="kg-cta-content">
                
                
                    <div class="kg-cta-content-inner">
                    
                        <div class="kg-cta-text">
                            <p><span style="white-space: pre-wrap;">This is the </span><a href="https://linuxhandbook.com/courses/" rel="noreferrer" class="cta-link-color"><span style="white-space: pre-wrap;">19 courses</span></a><span style="white-space: pre-wrap;"> so far and we’re not stopping. Three new courses have already been released in 2026, and our goal is to reach </span><b><strong style="white-space: pre-wrap;">at least 25 courses by the end of the year</strong></b><span style="white-space: pre-wrap;"> 💪</span><br><br><span style="white-space: pre-wrap;">That’s also why this is a great time to consider the </span><b><strong style="white-space: pre-wrap;">Pro membership</strong></b><span style="white-space: pre-wrap;">. It gives you access to all current and future courses. You can choose the annual Pro plan at </span><b><strong style="white-space: pre-wrap;">$69 per year</strong></b><span style="white-space: pre-wrap;">, or skip recurring payments altogether with a </span><b><strong style="white-space: pre-wrap;">lifetime membership for $199,</strong></b><span style="white-space: pre-wrap;"> a special price reserved for newsletter subscribers.</span></p><p><span style="white-space: pre-wrap;">If you’ve been thinking about upgrading, this is a good moment to jump in.</span></p>
                        </div>
                    
                    
                        <a href="https://buy.stripe.com/eVq6oH9nSaPg58teR60Jq04?prefilled_promo_code=LHB22&ref=linuxhandbook.com" class="kg-cta-button " style="background-color: #000000; color: #ffffff;">
                            Lifetime membership at $20 OFF
                        </a>
                        
                    </div>
                
            </div>
        </div>


<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">
        <div data-sx-content-cta-blur class="absolute w-full start-0 -top-0.5 -translate-y-full bg-linear-to-b to-70% from-black/0 to-background dark:to-background-dark pointer-events-none">
            &nbsp; <br> &nbsp; <br> &nbsp;
        </div>

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                        <span class="hidden first:inline">
                        This post is for subscribers only
                    </span>                

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Module 5 Practice Lab]]></title>
                    <description><![CDATA[Let&#x27;s put learning into practice with this lab, for the final time.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/m5-practice-lab/</link>
                    <guid isPermaLink="false">6974985db8e74a00019b2cac</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 17:08:14 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Service Discovery &amp; Internal DNS]]></title>
                    <description><![CDATA[Learn how containers find and communicate with each other using service discovery mechanisms.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/internal-dns/</link>
                    <guid isPermaLink="false">697487a0b8e74a00019b2c34</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 17:05:23 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Macvlan &amp; IPvlan]]></title>
                    <description><![CDATA[Understand advanced Docker networking options like Macvlan and IPvlan that allow containers to appear as devices on the physical network.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/macvlan-ipvlan/</link>
                    <guid isPermaLink="false">69745dd8b8e74a00019b2ba8</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:58:18 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Multi-Host Networking]]></title>
                    <description><![CDATA[This chapter introduces networking models used in distributed container environments.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/multi-host-networking/</link>
                    <guid isPermaLink="false">697377e4b8e74a00019b2901</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:57:04 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Module 4 Practice Lab]]></title>
                    <description><![CDATA[Let&#x27;s put learning into practice with this lab.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/m4-practice-lab/</link>
                    <guid isPermaLink="false">6970e764d52ee80001f7701a</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:54:14 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Container Security Tools]]></title>
                    <description><![CDATA[Explore some tools used for container security scanning, runtime protection, and vulnerability detection.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/container-security-tools/</link>
                    <guid isPermaLink="false">6970c833d52ee80001f76f70</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:52:30 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Best Practices to Secure Containers]]></title>
                    <description><![CDATA[Learn practical strategies for securing container environments.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/best-practices-secure-containers/</link>
                    <guid isPermaLink="false">6970b8cfd52ee80001f76efe</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:50:28 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Container Security]]></title>
                    <description><![CDATA[Understand the fundamental security model of containers.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/container-security/</link>
                    <guid isPermaLink="false">696f8b18d52ee80001f76c9a</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:48:22 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Module 3 Practice Lab]]></title>
                    <description><![CDATA[Let&#x27;s put learning into practice with this lab.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/m3-practice-lab/</link>
                    <guid isPermaLink="false">696df367d52ee80001f766af</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:44:32 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Debugging Container Networking]]></title>
                    <description><![CDATA[Container networking issues can be difficult to trace. Here are some ppractical methods for troubleshooting networking problems between containers and host.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/debug-container-networking/</link>
                    <guid isPermaLink="false">696debb7d52ee80001f76648</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:42:19 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Internal Observability]]></title>
                    <description><![CDATA[Understand how to inspect and debug containers from within.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/internal-observability/</link>
                    <guid isPermaLink="false">696c9887d52ee80001f7623d</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:30:17 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[External Observability]]></title>
                    <description><![CDATA[This chapter explores logging, metrics, and system-level monitoring approaches for understanding container behavior.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/external-observability/</link>
                    <guid isPermaLink="false">696b6136d52ee80001f75d89</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:28:08 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Module 2 Practice Lab]]></title>
                    <description><![CDATA[Let&#x27;s put learning into practice with this lab.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/m2-practice-lab/</link>
                    <guid isPermaLink="false">6969d425d52ee80001f6e620</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:23:25 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Image Optimization Techniques]]></title>
                    <description><![CDATA[Learn techniques for creating smaller and more efficient Docker images.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/image-optimization/</link>
                    <guid isPermaLink="false">6969d1ddd52ee80001f6e60b</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:21:29 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Using Multi-Stage Builds]]></title>
                    <description><![CDATA[Discover how multi-stage builds help reduce image size and improve efficiency.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/multi-stage-builds/</link>
                    <guid isPermaLink="false">6969cfc9d52ee80001f6e5f1</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:18:33 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Why Docker Images Become Bulky]]></title>
                    <description><![CDATA[Learn how Docker images are built and why they often become unnecessarily large.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/why-docker-images-become-bulky/</link>
                    <guid isPermaLink="false">6969ce8ed52ee80001f6e5e2</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 16:13:21 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Module 1 Practice Lab]]></title>
                    <description><![CDATA[Let&#x27;s put learning into practice with this lab.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/m1-practice-lab/</link>
                    <guid isPermaLink="false">696917bcd52ee80001f6e4e5</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 15:59:02 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Network and Device Controllers]]></title>
                    <description><![CDATA[Now we will see how the networking and the device resource limits are made possible using the network and device controllers. ]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/network-device-controllers/</link>
                    <guid isPermaLink="false">6969cc30d52ee80001f6e5d0</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 15:56:08 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Cgroups and Resource Control]]></title>
                    <description><![CDATA[Containers share the same kernel, so controlling resource usage is critical. This chapter shows how cgroups manage CPU, memory, and other system resources to prevent containers from affecting the entire system.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/cgroups-resource-control-2/</link>
                    <guid isPermaLink="false">6969160ed52ee80001f6e4cf</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 15:54:31 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Hostnames, IPC &amp; User Isolation]]></title>
                    <description><![CDATA[Learn hostname separation, inter-process communication (IPC) namespaces, and user namespaces for improved isolation and security.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/user-isolation/</link>
                    <guid isPermaLink="false">6969138dd52ee80001f6e4af</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 15:51:52 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Introduction to Namespaces]]></title>
                    <description><![CDATA[Understand what containers really are and how Linux namespaces isolate processes which is the fundamental mechanism that allows containers to run independently on the same host.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/namespaces-intro/</link>
                    <guid isPermaLink="false">6969115cd52ee80001f6e4a0</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 15:43:10 +0530</pubDate>


                    <content:encoded><![CDATA[

<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                                <span class="hidden first:inline">
                                This lesson is for paying subscribers only
                            </span>                           
                    <span class="hidden first:inline">
                        This post is for paying subscribers only
                    </span>  

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[Docker Level Up]]></title>
                    <description><![CDATA[Level up your Docker skills. Learn container internals, networking, image optimization, observability, and security in this practical course.]]></description>
                    <link>https://linuxhandbook.com/courses/docker-level-up/</link>
                    <guid isPermaLink="false">69b7c729df009b000197439f</guid>

                        <category><![CDATA[Docker Level Up]]></category>

                        <dc:creator><![CDATA[Yash Kiran Patil]]></dc:creator>

                    <pubDate>Mon, 16 Mar 2026 15:23:56 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/03/Docker-Level-Up.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/03/Docker-Level-Up.png" alt="Docker Level Up"/> <p>I gather you are familiar with Docker basics by now. You can deploy simple applications through Docker, create compose files for a mult-container app and even create your own custom image.</p><p>But real-world Docker usage goes much deeper.</p><ul><li>Why are containers isolated?</li><li>How do containers communicate across hosts?</li><li>Why do some images become huge? </li><li>How do you debug networking issues inside containers? </li><li>How do you secure containers properly?</li></ul><p>This <strong>Docker Level Up course</strong> is designed to answer these questions.</p><p>This course helps you understand the <strong>internal mechanisms that make containers work:</strong> namespaces, cgroups, networking layers, security controls, observability tools, and image optimization techniques.</p><p>By the end of the course, Docker will no longer feel like a black box. You’ll understand <strong>how containers actually function under the hood</strong> and how to use Docker more effectively in real environments.</p><div class="kg-card kg-callout-card kg-callout-card-red"><div class="kg-callout-emoji">🚧</div><div class="kg-callout-text">This course presumes that you are familiar with Docker already, well, at least the basics like running containers, building images, docker compose etc. If you are unsure, please revisit our <a href="https://linuxhandbook.com/courses/docker/">Docker for Beginners course</a>.</div></div><h2 id="%F0%9F%91%80-who-this-course-is-for">👀 Who this course is for?</h2><p>This course is ideal for:</p><p><strong>Linux users who already know basic Docker commands: </strong>If you’ve used Docker before but want to understand what happens behind the scenes.</p><p><strong>Developers deploying containerized applications: </strong>Learn how to build smaller images, debug networking issues, and run containers efficiently.</p><p><strong>DevOps engineers and SREs: </strong>Understand observability, container networking, and security best practices.</p><p><strong>Homelab enthusiasts and self-hosters: </strong>If you run services with Docker and want deeper control over networking and isolation.</p><p><strong>Students learning container technologies: </strong>This course builds strong fundamentals for Kubernetes and cloud-native systems.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">💡</div><div class="kg-callout-text">Understanding <b><strong style="white-space: pre-wrap;">how Docker works beneath the surface</strong></b> gives you a huge advantage. You’ll be able to troubleshoot container issues faster, build optimized images and secure container environments.</div></div><h2 id="%F0%9F%A7%A0-what-you%E2%80%99ll-learn">🧠 What you’ll learn</h2><p>The course is structured in <strong>five modules</strong>, each focusing on a key aspect of how Docker actually works under the hood.</p><p>Instead of jumping randomly between concepts, the modules follow a logical progression: <strong>container fundamentals → image building → observability → security → advanced networking.</strong></p><h3 id="module-1-container-internals">Module 1: Container Internals</h3><p>Before mastering Docker, you need to understand <strong>what a container actually is</strong>.</p><p>Containers are not virtual machines. They rely on Linux kernel features like <strong>namespaces and cgroups</strong> to isolate processes and resources.</p><p>In this module, you’ll explore the Linux technologies that make containers possible.</p><p>Topics covered:</p><ul><li>Introduction to containers and namespaces</li><li>Hostname, IPC and user isolation</li><li>cgroups and resource control</li><li>Network and device controllers</li><li>Practice lab</li></ul><p>By the end of this module, you’ll clearly understand <strong>why containers behave the way they do</strong>.</p><h3 id="module-2-docker-images-and-optimization">Module 2: Docker Images and Optimization</h3><p>Docker images often become unnecessarily large and inefficient.</p><p>In this module, you’ll learn how Docker images are built and how to optimize them properly.</p><p>Topics covered:</p><ul><li>How Docker images work internally</li><li>Why Docker images become bulky</li><li>Build tools vs production environments</li><li>Multi-stage builds</li><li>Image optimization techniques</li><li>Practice lab</li></ul><p>This module will help you build <strong>smaller, cleaner, production-ready images</strong>.</p><h3 id="module-3-container-observability-debugging">Module 3: Container Observability &amp; Debugging</h3><p>Containers sometimes fail in ways that are difficult to diagnose.</p><p>Understanding how to observe container behavior is critical when troubleshooting production issues.</p><p>Topics covered:</p><ul><li>External observability tools</li><li>Internal observability inside containers</li><li>Debugging container networking</li><li>Practice lab</li></ul><p>You’ll learn practical techniques to <strong>inspect, monitor, and debug containers effectively</strong>.</p><h3 id="module-4-container-security">Module 4: Container Security</h3><p>Security is often overlooked when running containers.</p><p>But containers share the host kernel, so understanding security boundaries is essential.</p><p>Topics covered:</p><ul><li>Core container security concepts</li><li>Security best practices</li><li>Important container security tools</li><li>Practice lab</li></ul><p>This module helps you run containers <strong>more safely and responsibly</strong>.</p><h3 id="module-5-advanced-container-networking">Module 5: Advanced Container Networking</h3><p>Networking is one of the most confusing areas in Docker.</p><p>This module explains how container networking works both <strong>within a host and across multiple hosts</strong>.</p><p>Topics covered:</p><ul><li>Multi-host container networking</li><li>Macvlan and IPvlan networks</li><li>Service discovery and internal DNS</li><li>Practice lab</li></ul><p>After this module, Docker networking will finally make <strong>practical sense instead of feeling magical</strong>.</p><div class="kg-card kg-callout-card kg-callout-card-green"><div class="kg-callout-emoji">💡</div><div class="kg-callout-text">Each module includes <b><strong style="white-space: pre-wrap;">hands-on practice labs</strong></b> to reinforce the concepts.</div></div>
<div class="kg-card kg-cta-card kg-cta-bg-grey kg-cta-minimal    " data-layout="minimal">
            
            <div class="kg-cta-content">
                
                
                    <div class="kg-cta-content-inner">
                    
                        <div class="kg-cta-text">
                            <p><span style="white-space: pre-wrap;">This course is available to Pro members of Linux Handbook only. Get Pro membership today and</span></p><p><span style="white-space: pre-wrap;">✅ Get access to Linux for DevOps, Docker, Ansible and other text courses</span><br><span style="white-space: pre-wrap;">✅ Get access to Kubernetes Operator and SSH video course</span><br><span style="white-space: pre-wrap;">✅ 17+ courses in total (more incoming)</span><br><span style="white-space: pre-wrap;">✅ Get 6 premium books on Bash, Linux and Ansible for free</span><br><span style="white-space: pre-wrap;">✅ No ads on the website</span></p>
                        </div>
                    
                    
                        <a href="https://linuxhandbook.com/#/portal/signup" class="kg-cta-button kg-style-accent" style="color: #FFFFFF;">
                            Get Pro Membership
                        </a>
                        
                    </div>
                
            </div>
        </div>
]]></content:encoded>
                </item>
                <item>
                    <title><![CDATA[LHB Linux Digest #26.04: git chaneglog, hard links and inodes, self-hosting tools and more]]></title>
                    <description><![CDATA[Self-hosting is the way to go.]]></description>
                    <link>https://linuxhandbook.com/newsletter/26-04/</link>
                    <guid isPermaLink="false">698e9b76f7d3c300011c40ab</guid>

                        <category><![CDATA[Newsletter]]></category>

                        <dc:creator><![CDATA[Abhishek Prakash]]></dc:creator>

                    <pubDate>Tue, 24 Feb 2026 19:26:52 +0530</pubDate>

                        <media:content url="https://linuxhandbook.com/content/images/2026/02/lhb-newsletter-1.png" medium="image"/>

                    <content:encoded><![CDATA[<img src="https://linuxhandbook.com/content/images/2026/02/lhb-newsletter-1.png" alt="LHB Linux Digest #26.04: git chaneglog, hard links and inodes, self-hosting tools and more"/> <p>This month, we released the <a href="https://linuxhandbook.com/courses/golang/">Go for DevOps course</a>. Next is GitOps video course. The work is in progress, and we are on track to release it early next month.</p><figure class="kg-card kg-image-card"><img src="https://linuxhandbook.com/content/images/2026/02/git-for-devops.webp" class="kg-image" alt="GitOps video course in progress" loading="lazy" width="800" height="375" srcset="https://linuxhandbook.com/content/images/size/w600/2026/02/git-for-devops.webp 600w, https://linuxhandbook.com/content/images/2026/02/git-for-devops.webp 800w" sizes="(min-width: 720px) 720px"></figure><p>After that, the plan is to release Docker Advanced level course and add videos to existing Docker beginner course. Plenty of exciting content in the pipeline. Hope you are as excited about them as I am 💪</p>
<div class="kg-card kg-cta-card kg-cta-bg-grey kg-cta-minimal    " data-layout="minimal">
            
            <div class="kg-cta-content">
                
                
                    <div class="kg-cta-content-inner">
                    
                        <div class="kg-cta-text">
                            <p><a href="https://linuxhandbook.com/courses/" rel="noreferrer" class="cta-link-color"><span style="white-space: pre-wrap;">18 courses</span></a><span style="white-space: pre-wrap;"> so far and we’re just getting started. Two new courses have already been released in 2026, and our goal is to reach </span><b><strong style="white-space: pre-wrap;">at least 25 courses by the end of the year</strong></b><span style="white-space: pre-wrap;"> 💪</span><br><br><span style="white-space: pre-wrap;">That’s also why this is a great time to consider the </span><b><strong style="white-space: pre-wrap;">Pro membership</strong></b><span style="white-space: pre-wrap;">. It gives you access to all current and future courses. You can choose the annual Pro plan at </span><b><strong style="white-space: pre-wrap;">$69 per year</strong></b><span style="white-space: pre-wrap;">, or skip recurring payments altogether with a </span><b><strong style="white-space: pre-wrap;">lifetime membership for $199,</strong></b><span style="white-space: pre-wrap;"> a special price reserved for newsletter subscribers.</span></p><p><span style="white-space: pre-wrap;">If you’ve been thinking about upgrading, this is a good moment to jump in.</span></p>
                        </div>
                    
                    
                        <a href="https://buy.stripe.com/eVq6oH9nSaPg58teR60Jq04?prefilled_promo_code=LHB22&ref=linuxhandbook.com" class="kg-cta-button " style="background-color: #000000; color: #ffffff;">
                            Lifetime membership at $20 OFF
                        </a>
                        
                    </div>
                
            </div>
        </div>


<aside data-sx-content-cta class="relative p-0.5 js-toc-ignore">
        <div data-sx-content-cta-blur class="absolute w-full start-0 -top-0.5 -translate-y-full bg-linear-to-b to-70% from-black/0 to-background dark:to-background-dark pointer-events-none">
            &nbsp; <br> &nbsp; <br> &nbsp;
        </div>

    <div class="relative flex flex-col items-center text-center w-full px-4 py-10 lg:px-10 text-base rounded-xl sm:rounded-2xl">
        <div class="dark:hidden absolute -inset-px -z-10 rounded-xl bg-white shadow-pretty-sm transition-shadow duration-200"></div>
        <span class="hidden dark:block absolute -z-10 -inset-px rounded-inherit bg-radial-[50%_100%_at_50%_0%] from-white/10"></span>        
        <div class="hidden dark:block absolute -inset-px -z-10 rounded-xl bg-white/1 transition-colors duration-500 inset-shadow-md inset-shadow-white/2"></div>
        
        <div class="hidden dark:block absolute -z-10 -inset-0.5 mask-to-b mask-position-to-70% mask-opacity-to-50%">
            <div class="hidden dark:block absolute -z-10 inset-px rounded-xl border border-gray-50/10"></div>
        </div>                                                
        <div class="hidden dark:block absolute -z-10 -inset-px rounded-xl border border-gray-50/5 opacity-0"></div>

        <div class="hidden dark:block absolute -top-px start-1/2 -translate-x-1/2 w-1/2 h-px bg-linear-to-r from-white/0 to-white/0 via-gray-400/50"></div>

        <h2 class="text-gray-900 dark:text-gray-100 text-pretty text-xl sm:text-2xl leading-snug tracking-tight">




                                        <span class="hidden first:inline">
                        This post is for subscribers only
                    </span>                

        </h2>

            <button data-portal="signup" class="mt-7 px-4 py-2.5 font-semibold text-sm text-center text-accent-contrast bg-primary rounded-full shadow-primary dark:shadow-none dark:drop-shadow-primary-sm hover:opacity-90 transition-opacity duration-200">
                Subscribe now
            </button>
            <p class="mt-5 text-sm">
                Already have an account? <button data-portal="signin" class="block sm:inline mx-auto font-medium underline decoration-primary decoration-2 underline-offset-2 hover:text-primary transition-colors duration-200">Sign in</button>
            </p>
    </div>
</aside>
]]></content:encoded>
                </item>
    </channel>
</rss>