<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: NACAMURA Mitsuhiro</title>
    <description>The latest articles on Forem by NACAMURA Mitsuhiro (@m15a).</description>
    <link>https://forem.com/m15a</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3602284%2F75930e9b-c334-4ce0-aaa2-a76f65e74154.jpeg</url>
      <title>Forem: NACAMURA Mitsuhiro</title>
      <link>https://forem.com/m15a</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/m15a"/>
    <language>en</language>
    <item>
      <title>Housekeeping My Neovim Configuration</title>
      <dc:creator>NACAMURA Mitsuhiro</dc:creator>
      <pubDate>Sun, 07 Dec 2025 14:39:48 +0000</pubDate>
      <link>https://forem.com/m15a/housekeeping-my-neovim-configuration-4kim</link>
      <guid>https://forem.com/m15a/housekeeping-my-neovim-configuration-4kim</guid>
      <description>&lt;h2&gt;
  
  
  The End of Stagnation
&lt;/h2&gt;

&lt;p&gt;I used to be a passionate tinkerer when it came to Vim/Neovim configuration. Lately, however, that passion has cooled. The last time I significantly touched my config was back in January of this year. Since then, I've been using Neovim daily without making any fixes or updates.&lt;/p&gt;

&lt;p&gt;After nearly a year of stagnation, I happened to update the lock file of my configuration, which is managed using &lt;a href="https://nixos.org/" rel="noopener noreferrer"&gt;Nix&lt;/a&gt;. This triggered a realization: it was time to clear out the accumulating deprecation warnings and modernize my setup to keep up with the evolving Neovim scene. Here is a log of my "Spring Cleaning" in December.&lt;/p&gt;




&lt;h2&gt;
  
  
  Updates &amp;amp; Migrations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Addressing &lt;code&gt;:checkhealth&lt;/code&gt; Warnings
&lt;/h3&gt;

&lt;p&gt;For a while (before updating the lock file), I had been ignoring a persistent warning in my &lt;code&gt;:messages&lt;/code&gt; regarding the usage of the obsolete &lt;code&gt;vim.fn.sign_define&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- ⚠️ WARNING Defining diagnostic signs with :sign-define or sign_define() is deprecated. Feature will be removed in Nvim 0.12
  - ADVICE:
    - use vim.diagnostic.config() instead.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I finally decided to stop ignoring it. After reading &lt;code&gt;:h diagnostic-signs&lt;/code&gt;, I refactored the code to use the modern &lt;code&gt;vim.diagnostic.config&lt;/code&gt; API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gh"&gt;diff --git a/lua/m15a/plugins/lspconfig/init.lua b/lua/m15a/plugins/lspconfig/init.lua
index 3cfbd2124d..8644fedc68 100644
&lt;/span&gt;&lt;span class="gd"&gt;--- a/lua/m15a/plugins/lspconfig/init.lua
&lt;/span&gt;&lt;span class="gi"&gt;+++ b/lua/m15a/plugins/lspconfig/init.lua
&lt;/span&gt;&lt;span class="p"&gt;@@ -97,12 +97,19 @@&lt;/span&gt;
 end
&lt;span class="err"&gt;
&lt;/span&gt; local function setup_diagnostic_signs()
&lt;span class="gd"&gt;-   -- Change diagnostic signs in the gutter:
-   -- https://github.com/neovim/nvim-lspconfig/wiki/UI-Customization#change-diagnostic-symbols-in-the-sign-column-gutter
&lt;/span&gt;&lt;span class="gi"&gt;+   local signs = {
+      text = {},
+      texthl = {},
+      numhl = {},
+   }
&lt;/span&gt;    for type, text in pairs(assets.fonts.diagnostic) do
&lt;span class="gi"&gt;+      local severity = vim.diagnostic.severity[type:gsub('^%l+', string.upper)]
&lt;/span&gt;       local hl = 'DiagnosticSign' .. type:gsub('^%l', string.upper)
&lt;span class="gd"&gt;-      vim.fn.sign_define(hl, { text = text, texthl = hl, numhl = hl })
&lt;/span&gt;&lt;span class="gi"&gt;+      signs.text[severity] = text
+      signs.texthl[severity] = hl
+      signs.numhl[severity] = hl
&lt;/span&gt;    end
&lt;span class="gi"&gt;+   vim.diagnostic.config { signs = signs }
&lt;/span&gt; end
&lt;span class="err"&gt;
&lt;/span&gt; function M.setup()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Modernizing &lt;a href="https://github.com/neovim/nvim-lspconfig" rel="noopener noreferrer"&gt;nvim-lspconfig&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The "framework" API of &lt;a href="https://github.com/neovim/nvim-lspconfig" rel="noopener noreferrer"&gt;nvim-lspconfig&lt;/a&gt; was &lt;a href="https://github.com/neovim/nvim-lspconfig/pull/4077" rel="noopener noreferrer"&gt;deprecated (Sep 18, 2025)&lt;/a&gt;, now that Neovim supports &lt;a href="https://github.com/neovim/neovim/pull/31031" rel="noopener noreferrer"&gt;&lt;code&gt;vim.lsp.config&lt;/code&gt; (as of Dec 11, 2024)&lt;/a&gt;. To align with this shift, I updated the legacy API calls in my config:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Replaced &lt;code&gt;require("lspconfig")&lt;/code&gt; with &lt;code&gt;vim.lsp.config&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Updated the server setup logic.&lt;/li&gt;
&lt;li&gt;Ensured servers are explicitly enabled.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gh"&gt;diff --git a/lua/m15a/plugins/lspconfig/init.lua b/lua/m15a/plugins/lspconfig/init.lua
index a6f8dbbfce..d99c110643 100644
&lt;/span&gt;&lt;span class="gd"&gt;--- a/lua/m15a/plugins/lspconfig/init.lua
&lt;/span&gt;&lt;span class="gi"&gt;+++ b/lua/m15a/plugins/lspconfig/init.lua
&lt;/span&gt;&lt;span class="p"&gt;@@ -1,6 +1,5 @@&lt;/span&gt;
 local namespace = ...
&lt;span class="err"&gt;
&lt;/span&gt;&lt;span class="gd"&gt;-local lspconfig = require 'lspconfig'
&lt;/span&gt; local tbuiltin = require 'telescope.builtin'
 local assets = require 'm15a.assets'
 local keymap = require 'm15a.keymap'
&lt;span class="p"&gt;@@ -27,7 +26,8 @@&lt;/span&gt;
 local function setup_servers()
    for server, cmd in pairs(servers) do
       if vim.fn.executable(cmd) &amp;gt; 0 then
&lt;span class="gd"&gt;-         lspconfig[server].setup(require_server_config(server))
&lt;/span&gt;&lt;span class="gi"&gt;+         vim.lsp.config(server, require_server_config(server))
+         vim.lsp.enable(server)
&lt;/span&gt;       end
    end
 end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Optimizing &lt;a href="https://github.com/nvim-telescope/telescope.nvim" rel="noopener noreferrer"&gt;telescope.nvim&lt;/a&gt; Keybindings
&lt;/h3&gt;

&lt;p&gt;I reconsidered my historical Telescope key mappings to improve ergonomics. Previously, opening a picker required three keystrokes (e.g., &lt;code&gt;&amp;lt;Leader&amp;gt;ef&lt;/code&gt;, &lt;code&gt;&amp;lt;Leader&amp;gt;eg&lt;/code&gt;, etc.), as configured below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nvim_set_keymap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"[telescope]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;Nop&amp;gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;noremap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nvim_set_keymap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&amp;lt;Leader&amp;gt;e"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"[telescope]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt;
&lt;span class="n"&gt;vim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;keymap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"[telescope]f"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"telescope.builtin"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;find_files&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have now reduced this to just two keystrokes: &lt;code&gt;&amp;lt;Leader&amp;gt;f&lt;/code&gt;, &lt;code&gt;&amp;lt;Leader&amp;gt;g&lt;/code&gt;, etc. It feels much faster and more direct.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pruning &lt;a href="https://github.com/nvim-treesitter/nvim-treesitter-textobjects" rel="noopener noreferrer"&gt;nvim-treesitter-textobjects&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;This plugin offers a massive number of syntax textobjects. In the past, I blindly mapped almost all of them. However, in practice, I only use a handful. I decided to keep only the essentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;         &lt;span class="n"&gt;keymaps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ik"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"@class.inner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ak"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"@class.outer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ic"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"@comment.inner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ac"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"@comment.outer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"im"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"@function.inner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"am"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"@function.outer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"ia"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"@parameter.inner"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"aa"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"@parameter.outer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Replacing &lt;a href="https://github.com/famiu/feline.nvim" rel="noopener noreferrer"&gt;feline.nvim&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The repository &lt;a href="https://github.com/freddiehaddad/feline.nvim" rel="noopener noreferrer"&gt;freddiehaddad/feline.nvim&lt;/a&gt;—a previously maintained fork of the original &lt;a href="https://github.com/famiu/feline.nvim" rel="noopener noreferrer"&gt;feline.nvim&lt;/a&gt;—was deleted. I was a fan of this&lt;br&gt;
minimalist statusline framework, but with the repo gone, migration was necessary. I decided to switch to &lt;a href="https://github.com/nvim-lualine/lualine.nvim" rel="noopener noreferrer"&gt;lualine.nvim&lt;/a&gt;, which is another minimal (and widely-adopted) statusline plugin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sticking with &lt;a href="https://github.com/stevearc/dressing.nvim" rel="noopener noreferrer"&gt;dressing.nvim&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://github.com/stevearc/dressing.nvim" rel="noopener noreferrer"&gt;dressing.nvim&lt;/a&gt; repository has been archived. I read &lt;a href="https://github.com/stevearc/dressing.nvim/issues/190" rel="noopener noreferrer"&gt;the issue&lt;/a&gt; where the author explains the decision:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;[F]olke came out with snacks.nvim and it contains both a fuzzy&lt;br&gt;
vim.ui.select implementation and a good vim.ui.input. Now, at long&lt;br&gt;
last, I can say that this plugin has outlived its usefulness and&lt;br&gt;
retire it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I looked at the suggested successor, &lt;a href="https://github.com/folke/snacks.nvim" rel="noopener noreferrer"&gt;snacks.nvim&lt;/a&gt;. However, it comes with far more features than I need. I prefer a simpler plugin for this functionality. For now, I have decided to keep using the archived &lt;a href="https://github.com/stevearc/dressing.nvim" rel="noopener noreferrer"&gt;dressing.nvim&lt;/a&gt; until a more focused alternative appears.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrating to &lt;a href="https://github.com/nxhung2304/lastplace.nvim" rel="noopener noreferrer"&gt;lastplace.nvim&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I migrated from &lt;a href="https://github.com/ethanholz/nvim-lastplace" rel="noopener noreferrer"&gt;nvim-lastplace&lt;/a&gt; to &lt;a href="https://github.com/nxhung2304/lastplace.nvim" rel="noopener noreferrer"&gt;lastplace.nvim&lt;/a&gt;. Although I knew the &lt;a href="https://github.com/ethanholz/nvim-lastplace" rel="noopener noreferrer"&gt;nvim-lastplace&lt;/a&gt; repository had been archived for a while, I kept using it simply because it worked. This update brings me back to a maintained version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Removals
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/OXY2DEV/markview.nvim" rel="noopener noreferrer"&gt;markview.nvim&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I decided to remove &lt;a href="https://github.com/OXY2DEV/markview.nvim" rel="noopener noreferrer"&gt;markview.nvim&lt;/a&gt;. I realized that I dislike heavily concealed text. The dynamic width changes that occur when switching between normal and insert modes were becoming visually distracting.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/lewis6991/gitsigns.nvim" rel="noopener noreferrer"&gt;gitsigns.nvim&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I removed &lt;a href="https://github.com/lewis6991/gitsigns.nvim" rel="noopener noreferrer"&gt;gitsigns.nvim&lt;/a&gt; in favor of &lt;a href="https://github.com/jj-vcs/jj" rel="noopener noreferrer"&gt;Jujutsu&lt;/a&gt;, which I have recently started using as my Git frontend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/windwp/nvim-ts-autotag" rel="noopener noreferrer"&gt;nvim-ts-autotag&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I had overlooked it previously, but it is incredibly helpful when editing HTML.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/chrisgrieser/nvim-origami" rel="noopener noreferrer"&gt;nvim-origami&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;I have seldom used folding and its plugins. My preference has been that code should be split into small enough files so that folding becomes unnecessary.&lt;/p&gt;

&lt;p&gt;However, I realized that for certain tasks—specifically scripts for deploying to pipeline orchestrators that prohibit external packaging—I am often forced to put many modules into a single script file. In these cases, folding helps me. I decided to introduce &lt;a href="https://github.com/chrisgrieser/nvim-origami" rel="noopener noreferrer"&gt;nvim-origami&lt;/a&gt; to handle this.&lt;/p&gt;




&lt;h2&gt;
  
  
  Next Time?
&lt;/h2&gt;

&lt;p&gt;It took about a week of spare time to finish this configuration overhaul. My next major update will likely happen after &lt;a href="https://github.com/nvim-treesitter/nvim-treesitter" rel="noopener noreferrer"&gt;nvim-treesitter&lt;/a&gt; releases its &lt;code&gt;main&lt;/code&gt; branch, as that is expected to bring several breaking changes.&lt;/p&gt;

</description>
      <category>neovim</category>
      <category>productivity</category>
    </item>
    <item>
      <title>"As Cloud-like as Possible" Data Science: Local MLOps with Docker Compose</title>
      <dc:creator>NACAMURA Mitsuhiro</dc:creator>
      <pubDate>Mon, 24 Nov 2025 08:50:06 +0000</pubDate>
      <link>https://forem.com/m15a/as-cloud-like-as-possible-data-science-local-mlops-with-docker-compose-4lgd</link>
      <guid>https://forem.com/m15a/as-cloud-like-as-possible-data-science-local-mlops-with-docker-compose-4lgd</guid>
      <description>&lt;h2&gt;
  
  
  Emulates cloud-native MLOps locally
&lt;/h2&gt;

&lt;p&gt;I have built a data science environment that allows me to construct data pipelines and manage machine learning experiments on a local PC, while providing a user experience that is as cloud-like as possible.&lt;/p&gt;

&lt;p&gt;According to Gemini:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This environment functions as a sandbox for learning a "cloud-native development style" by replacing major components used in cloud environments—such as S3, orchestrators, and ML tracking services—with local Docker containers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Alright. If you say so, this serves as educational content.&lt;/p&gt;

&lt;p&gt;The source code (&lt;code&gt;docker-compose.yaml&lt;/code&gt;, etc.) is available on &lt;a href="https://github.com/m15a/acap-datasci-env" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  System components
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Data store: &lt;a href="https://www.versity.com/products/versitygw/" rel="noopener noreferrer"&gt;Versity S3 Gateway&lt;/a&gt; emulates S3 storage.&lt;/li&gt;
&lt;li&gt;Source code repository: Just a Git daemon.&lt;/li&gt;
&lt;li&gt;Pipeline: &lt;a href="https://www.prefect.io/" rel="noopener noreferrer"&gt;Prefect&lt;/a&gt; orchestrates pipelines.&lt;/li&gt;
&lt;li&gt;Experiment management: &lt;a href="https://mlflow.org/" rel="noopener noreferrer"&gt;MLflow&lt;/a&gt; tracks models, parameters, and results.&lt;/li&gt;
&lt;li&gt;Notebook: &lt;a href="https://marimo.io/" rel="noopener noreferrer"&gt;Marimo&lt;/a&gt; for interactive development.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I initially used &lt;a href="https://www.min.io/" rel="noopener noreferrer"&gt;MinIO&lt;/a&gt; as the S3 alternative, but since they have &lt;a href="https://github.com/minio/minio/blob/master/README.md#source-only-distribution" rel="noopener noreferrer"&gt;stopped distributing binaries and Docker images&lt;/a&gt;, I switched to the Versity S3 gateway to access the file system via the S3 protocol.&lt;/p&gt;

&lt;p&gt;The system components collaborate as shown in the following diagram:&lt;/p&gt;

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

&lt;p&gt;(Marimo is omitted for clarity as it is loosely coupled with the&lt;br&gt;
rest of the system.)&lt;/p&gt;
&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;The steps for running experiments are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;(If necessary) Upload the data to S3 (&lt;code&gt;http://localhost:7070&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Implement the Prefect workflow (&lt;code&gt;experiments/*.py&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git push&lt;/code&gt; the code to the Git repo (&lt;code&gt;http:localhost:9010/repo&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Deploy the workflow to Prefect (&lt;code&gt;prefect deploy&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Run the workflow via Prefect (&lt;code&gt;prefect deployment run&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Check the experiment results in MLflow (&lt;code&gt;http://localhost:5001&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Detailed prerequisite steps, such as setting environment variables, are written in the &lt;a href="https://github.com/m15a/acap-datasci-env" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; README.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementing Prefect workflows
&lt;/h3&gt;

&lt;p&gt;Define your experiment workflows and tasks using Prefect decorators (&lt;code&gt;@flow&lt;/code&gt;, &lt;code&gt;@task&lt;/code&gt;). Insert MLflow functions such as&lt;br&gt;
&lt;code&gt;mlflow.log_params()&lt;/code&gt; to track everything in MLflow!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@flow&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;example&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_tests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;An example experiment as a Prefect flow with MLflow tracking.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;mlflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_tracking_uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MLFLOW_TRACKING_URI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mlflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_experiment&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example-experiment-&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;s3://data/iris.csv&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;drop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;columns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;target&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;species&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;target&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;x_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x_test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_test&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;train_test_split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;test_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;test_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x_test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;test_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;target&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y_test&lt;/span&gt;
    &lt;span class="n"&gt;test_dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mlflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pandas&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;test_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;target&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@task&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_estimators&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;criterion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;A run in the experiment.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;mlflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;start_run&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;n_estimators&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;n_estimators&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;criterion&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;criterion&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;mlflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log_params&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RandomForestClassifier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_train&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;model_info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mlflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sklearn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log_model&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;input_example&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x_train&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;mlflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model_info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;model_uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;test_dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;model_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;classifier&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n_estimators&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)]:&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;criterion&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gini&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;entropy&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;log_loss&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_tests&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n_estimators&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;criterion&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploying and running Prefect workflows
&lt;/h3&gt;

&lt;p&gt;Register the workflow with the Prefect server by declaring the deployment configuration in &lt;code&gt;prefect.yaml&lt;/code&gt; and running &lt;code&gt;prefect deploy&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;deployments&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;experiment&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;n_tests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
    &lt;span class="na"&gt;entrypoint&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;experiments/example.py:example&lt;/span&gt;
    &lt;span class="na"&gt;work_pool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sandbox&lt;/span&gt;
      &lt;span class="na"&gt;job_variables&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After deploying, run it with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;prefect deployment run example/experiment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can view the execution status in real-time by accessing the&lt;br&gt;
Prefect Web UI (&lt;a href="http://localhost:4200/runs" rel="noopener noreferrer"&gt;http://localhost:4200/runs&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking and analyzing results in MLflow
&lt;/h3&gt;

&lt;p&gt;Access the MLflow Web UI (&lt;a href="http://localhost:5001" rel="noopener noreferrer"&gt;http://localhost:5001&lt;/a&gt;) to review the&lt;br&gt;
tracked experiment results and perform comparative analysis based on parameters.&lt;/p&gt;

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

&lt;p&gt;I have created a local environment that feels "as cloud-like as&lt;br&gt;
possible." Adding something like a data lake (e.g., &lt;a href="https://ducklake.select/" rel="noopener noreferrer"&gt;DuckLake&lt;/a&gt;) would likely make it feel even more like the cloud.&lt;/p&gt;




&lt;p&gt;Translated from the original post at &lt;a href="https://m15a.dev/ja/posts/acap-datasci-env/" rel="noopener noreferrer"&gt;https://m15a.dev/ja/posts/acap-datasci-env/&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>docker</category>
      <category>mlops</category>
      <category>mlflow</category>
    </item>
    <item>
      <title>How Much Smaller Are NixNG Container Images Compared to NixOS, Really?</title>
      <dc:creator>NACAMURA Mitsuhiro</dc:creator>
      <pubDate>Sat, 08 Nov 2025 09:48:27 +0000</pubDate>
      <link>https://forem.com/m15a/how-much-smaller-are-nixng-container-images-compared-to-nixos-really-57k9</link>
      <guid>https://forem.com/m15a/how-much-smaller-are-nixng-container-images-compared-to-nixos-really-57k9</guid>
      <description>&lt;h2&gt;
  
  
  NixNG
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/nix-community/NixNG" rel="noopener noreferrer"&gt;NixNG&lt;/a&gt; is a Linux distribution currently under development, derived&lt;br&gt;
from &lt;a href="https://nixos.org/" rel="noopener noreferrer"&gt;NixOS&lt;/a&gt;. It is being positioned as a lightweight alternative to&lt;br&gt;
NixOS, specifically targeting container environments.&lt;/p&gt;

&lt;p&gt;The project achieves its reduced size by omitting systemd from&lt;br&gt;
NixOS and minimizing the default package set. Since NixOS container&lt;br&gt;
images are a bit heavy, a lighter alternative is definitely welcome.&lt;br&gt;
Dropping systemd also opens up possibilities for using&lt;br&gt;
lighter-weight init systems like runit, which I find to be an exciting&lt;br&gt;
prospect.&lt;/p&gt;

&lt;p&gt;But just how much smaller is NixNG in practice, compared to an image&lt;br&gt;
based on the original NixOS? I created both images to compare their&lt;br&gt;
sizes.&lt;/p&gt;
&lt;h2&gt;
  
  
  The experiment
&lt;/h2&gt;

&lt;p&gt;The official Nix image is &lt;a href="https://hub.docker.com/r/nixos/nix/" rel="noopener noreferrer"&gt;available on DockerHub&lt;/a&gt;. I built&lt;br&gt;
a comparable NixNG image that includes only the Nix package manager and&lt;br&gt;
then compared the sizes of the two.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Distro&lt;/th&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Base image/Build&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Official Nix&lt;/td&gt;
&lt;td&gt;Nix 2.32.2&lt;/td&gt;
&lt;td&gt;DockerHub &lt;code&gt;nixos/nix:2.32.2&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NixNG&lt;/td&gt;
&lt;td&gt;Nix 2.32.2&lt;/td&gt;
&lt;td&gt;Built using the method below&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I ensured that the platform was consistent: &lt;code&gt;x86_64-linux&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  NixNG build flake setup
&lt;/h3&gt;

&lt;p&gt;I set up a minimal flake project for the test.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;flake.nix&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;nixng&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github:nix-community/NixNG"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"github:NixOS/nixpkgs/nixpkgs-unstable"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nv"&gt;outputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nv"&gt;nixng&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="o"&gt;...&lt;/span&gt;
    &lt;span class="p"&gt;}:&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;examples&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;nixng-nix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;import&lt;/span&gt; &lt;span class="sx"&gt;./examples/nixng-nix.nix&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;inherit&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;nixng&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;nglib&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;inherit&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;system&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"x86_64-linux"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The system of interest for comparison is defined in&lt;br&gt;
&lt;code&gt;examples.nixng-nix&lt;/code&gt;, based on&lt;br&gt;
&lt;a href="https://github.com/nix-community/NixNG/tree/master/examples/nix" rel="noopener noreferrer"&gt;an example from the NixNG repository&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;examples/nixng-nix.nix&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nix"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;nglib&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt;

&lt;span class="nv"&gt;nglib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;makeSystem&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kn"&gt;inherit&lt;/span&gt; &lt;span class="nv"&gt;nixpkgs&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kn"&gt;inherit&lt;/span&gt; &lt;span class="nv"&gt;system&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"nixng-nix"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nv"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nv"&gt;dumb-init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;type&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;shell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="nv"&gt;nix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;enable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;package&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;pkgs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;nixVersions&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;nix_2_32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nv"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nv"&gt;experimental-features&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;"nix-command"&lt;/span&gt;
            &lt;span class="s2"&gt;"flakes"&lt;/span&gt;
          &lt;span class="p"&gt;];&lt;/span&gt;
          &lt;span class="nv"&gt;sandbox&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Build and load the OCI image
&lt;/h3&gt;

&lt;p&gt;I generated and loaded the Docker image tar file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/amd64 &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/work &lt;span class="nt"&gt;-w&lt;/span&gt; /work &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="go"&gt;    nixos/nix:2.32.2 bash -c '
    {
        echo "filter-syscalls = false"
        echo "experimental-features = nix-command flakes"
&lt;/span&gt;&lt;span class="gp"&gt;    } &amp;gt;&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /etc/nix/nix.conf
&lt;span class="gp"&gt;    nix build .#&lt;/span&gt;examples.nixng-nix.config.system.build.ociImage.stream
&lt;span class="gp"&gt;    ./result &amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nixng-nix-image.tar
&lt;span class="go"&gt;    '

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker image load &lt;span class="nt"&gt;-i&lt;/span&gt; nixng-nix-image.tar 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: Since I use Docker Desktop on an ARM Mac, I&lt;br&gt;
&lt;a href="https://github.com/DeterminateSystems/nix-installer/issues/324" rel="noopener noreferrer"&gt;had to add &lt;code&gt;filter-syscalls = false&lt;/code&gt; to the Nix configuration&lt;/a&gt;&lt;br&gt;
to avoid an error during the build.&lt;/p&gt;
&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Image sizes
&lt;/h3&gt;

&lt;p&gt;With the official Nix image already available, I checked the sizes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker image &lt;span class="nb"&gt;ls&lt;/span&gt;
&lt;span class="go"&gt;REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
nixos/nix    2.32.2    f9b3c7811e27   55 years ago   436MB
nixos/nix    latest    f9b3c7811e27   55 years ago   436MB
nixng-nix    latest    26361447b07f   55 years ago   356MB
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official image was &lt;strong&gt;436MB&lt;/strong&gt;, while the NixNG image came in&lt;br&gt;
at &lt;strong&gt;356MB&lt;/strong&gt;. That's a size reduction of &lt;strong&gt;80MB&lt;/strong&gt; (approximately &lt;strong&gt;18%&lt;/strong&gt;).&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;/nix/store/&lt;/code&gt; contents
&lt;/h3&gt;

&lt;p&gt;I was curious to see exactly which packages were omitted.&lt;br&gt;
First, I looked at the package count in the &lt;code&gt;/nix/store/&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker run &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/amd64 nixos/nix:2.32.2 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="gp"&gt;    sh -c 'ls /nix/store' 2&amp;gt;&lt;/span&gt;/dev/null | rg &lt;span class="s1"&gt;'^[a-z0-9]+-'&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;span class="go"&gt;     121
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker run &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/amd64 nixng-nix &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="gp"&gt;    sh -c 'ls /nix/store' 2&amp;gt;&lt;/span&gt;/dev/null | rg &lt;span class="s1"&gt;'^[a-z0-9]+-'&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;span class="go"&gt;      81
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official Nix image contains &lt;strong&gt;121&lt;/strong&gt; packages, compared to &lt;strong&gt;81&lt;/strong&gt;&lt;br&gt;
in NixNG—a reduction of &lt;strong&gt;40&lt;/strong&gt; packages.&lt;/p&gt;

&lt;p&gt;Next, I looked at the detailed differences. After preprocessing the&lt;br&gt;
package names to normalize version and date differences:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker run &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/amd64 nixos/nix:2.32.2 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="gp"&gt;    sh -c 'ls /nix/store' 2&amp;gt;&lt;/span&gt;/dev/null | rg &lt;span class="s1"&gt;'^[a-z0-9]+-'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="go"&gt;    | cut -d'-' -f2- \
&lt;/span&gt;&lt;span class="gp"&gt;    | sed -Ee 's#&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;0-9]&lt;span class="o"&gt;{&lt;/span&gt;4&lt;span class="o"&gt;}(&lt;/span&gt;-?[0-9]&lt;span class="o"&gt;{&lt;/span&gt;2&lt;span class="o"&gt;}(&lt;/span&gt;-?[0-9]&lt;span class="o"&gt;{&lt;/span&gt;2&lt;span class="o"&gt;})&lt;/span&gt;?&lt;span class="o"&gt;)&lt;/span&gt;?[a-z]?#DATE#&lt;span class="s1"&gt;' \
&lt;/span&gt;&lt;span class="gp"&gt;        -e 's#&lt;/span&gt;&lt;span class="s1"&gt;[0-9]+\.[0-9]+([.p-][0-9]+)?#VERSION#'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="go"&gt;    | sort \
    | uniq \
&lt;/span&gt;&lt;span class="gp"&gt;    &amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nixos-nix-nix-store.txt
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker run &lt;span class="nt"&gt;--platform&lt;/span&gt; linux/amd64 nixng-nix &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="gp"&gt;    sh -c 'ls /nix/store' 2&amp;gt;&lt;/span&gt;/dev/null | rg &lt;span class="s1"&gt;'^[a-z0-9]+-'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="go"&gt;    | cut -d'-' -f2- \
&lt;/span&gt;&lt;span class="gp"&gt;    | sed -Ee 's#&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;0-9]&lt;span class="o"&gt;{&lt;/span&gt;4&lt;span class="o"&gt;}(&lt;/span&gt;-?[0-9]&lt;span class="o"&gt;{&lt;/span&gt;2&lt;span class="o"&gt;}(&lt;/span&gt;-?[0-9]&lt;span class="o"&gt;{&lt;/span&gt;2&lt;span class="o"&gt;})&lt;/span&gt;?&lt;span class="o"&gt;)&lt;/span&gt;?[a-z]?#DATE#&lt;span class="s1"&gt;' \
&lt;/span&gt;&lt;span class="gp"&gt;        -e 's#&lt;/span&gt;&lt;span class="s1"&gt;[0-9]+\.[0-9]+([.p-][0-9]+)?#VERSION#'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="go"&gt;    | sort \
    | uniq \
&lt;/span&gt;&lt;span class="gp"&gt;    &amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;nixng-nix-nix-store.txt
&lt;span class="go"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Comparing the diff reveals the omitted components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="gd"&gt;--- nixos-nix-nix-store.txt 2025-11-08 21:45:41
&lt;/span&gt;&lt;span class="gi"&gt;+++ nixng-nix-nix-store.txt 2025-11-08 21:45:48
&lt;/span&gt;&lt;span class="p"&gt;@@ -1,6 +1,5 @@&lt;/span&gt;
 acl-VERSION
 attr-VERSION
&lt;span class="gd"&gt;-audit-VERSION-lib
&lt;/span&gt; aws-c-auth-VERSION
 aws-c-cal-VERSION
 aws-c-common-VERSION
&lt;span class="p"&gt;@@ -14,73 +13,45 @@&lt;/span&gt;
 aws-checksums-VERSION
 aws-crt-cpp-VERSION
 aws-sdk-cpp-VERSION
&lt;span class="gd"&gt;-base-system
&lt;/span&gt; bash-interactive-VERSION
&lt;span class="gd"&gt;-bash-interactive-VERSION-man
&lt;/span&gt; bash-VERSION
 boehm-gc-VERSION
 boost-VERSION
 brotli-VERSION-lib
 busybox-VERSION
 bzip2-VERSION
&lt;span class="gd"&gt;-channel-nixos
-coreutils-full-VERSION
-coreutils-VERSION
&lt;/span&gt;&lt;span class="gi"&gt;+ca-certificates.crt
&lt;/span&gt; curl-VERSION
&lt;span class="gd"&gt;-curl-VERSION-bin
-curl-VERSION-man
-db-VERSION
-dns-root-data-DATE
-editline-VERSION
-expat-VERSION
-findutils-VERSION
&lt;/span&gt;&lt;span class="gi"&gt;+dumb-init-VERSION
+editline-VERSION-unstable-DATE
&lt;/span&gt; gcc-VERSION-lib
 gcc-VERSION-libgcc
&lt;span class="gd"&gt;-gdbm-VERSION-lib
-gettext-VERSION
-git-minimal-VERSION
&lt;/span&gt;&lt;span class="gi"&gt;+generate-shadow
&lt;/span&gt; glibc-VERSION
&lt;span class="gd"&gt;-glibc-VERSION-bin
-gmp-with-cxx-VERSION
-gnugrep-VERSION
-gnused-VERSION
-gnutar-VERSION
-groff-VERSION
-gzip-VERSION
-gzip-VERSION-man
&lt;/span&gt;&lt;span class="gi"&gt;+group
+hwloc-VERSION-lib
&lt;/span&gt; iana-etc-DATE
&lt;span class="gi"&gt;+icu4c-VERSION
&lt;/span&gt; keyutils-VERSION-lib
 krb5-VERSION-lib
&lt;span class="gd"&gt;-ldns-VERSION
-less-668
-less-668-man
&lt;/span&gt; libarchive-VERSION-lib
 libblake3-VERSION
&lt;span class="gd"&gt;-libbsd-VERSION
-libcap-ng-VERSION
-libcap-VERSION-lib
-libcbor-VERSION
&lt;/span&gt; libcpuid-VERSION
&lt;span class="gd"&gt;-libedit-DATE-VERSION
-libfido2-VERSION
&lt;/span&gt; libgit2-VERSION-lib
 libidn2-VERSION
&lt;span class="gd"&gt;-libmd-VERSION
-libpipeline-VERSION
&lt;/span&gt; libpsl-VERSION
 libseccomp-VERSION-lib
 libsodium-VERSION
 libssh2-VERSION
 libunistring-VERSION
&lt;span class="gd"&gt;-libxcrypt-VERSION
&lt;/span&gt; libxml2-VERSION
&lt;span class="gd"&gt;-linux-pam-VERSION
&lt;/span&gt; llhttp-VERSION
 lowdown-VERSION-lib
&lt;span class="gd"&gt;-man-db-VERSION
-manifest.nix
&lt;/span&gt; ncurses-VERSION
&lt;span class="gi"&gt;+ndig4f4dx8bmrmyr5vfm19g02r9l9ggm-source
&lt;/span&gt; nghttp2-VERSION-lib
&lt;span class="gi"&gt;+nghttp3-VERSION
+ngtcp2-VERSION
&lt;/span&gt; nix-cmd-VERSION
 nix-expr-VERSION
 nix-fetchers-VERSION
&lt;span class="p"&gt;@@ -89,32 +60,20 @@&lt;/span&gt;
 nix-store-VERSION
 nix-util-VERSION
 nix-VERSION
&lt;span class="gd"&gt;-nss-cacert-VERSION
-openssh-VERSION
&lt;/span&gt;&lt;span class="gi"&gt;+nix.conf
+nixng-nixng-nix
+onetbb-DATE.VERSION
&lt;/span&gt; openssl-VERSION
&lt;span class="gi"&gt;+passwd
&lt;/span&gt; pcre2-VERSION
&lt;span class="gd"&gt;-pcsclite-VERSION-lib
&lt;/span&gt;&lt;span class="gi"&gt;+profile
&lt;/span&gt; publicsuffix-list-0-unstable-DATE
 readline-VERSION
&lt;span class="gd"&gt;-root-profile-env
&lt;/span&gt; s2n-tls-VERSION
&lt;span class="gd"&gt;-shadow-VERSION
-source
&lt;/span&gt;&lt;span class="gi"&gt;+service-dir
&lt;/span&gt; sqlite-VERSION
&lt;span class="gd"&gt;-systemd-minimal-libs-VERSION
-tbb-DATE.VERSION
-tbb-DATE.VERSION-dev
-tcb-VERSION
-util-linux-minimal-VERSION-bin
-util-linux-minimal-VERSION-lib
-util-linux-minimal-VERSION-login
-util-linux-minimal-VERSION-mount
-util-linux-minimal-VERSION-swap
-wget-VERSION
-which-VERSION
&lt;/span&gt;&lt;span class="gi"&gt;+tzdata-DATE
&lt;/span&gt; xgcc-VERSION-libgcc
 xz-VERSION
&lt;span class="gd"&gt;-zlib-ng-VERSION
&lt;/span&gt; zlib-VERSION
 zstd-VERSION
&lt;span class="gd"&gt;-zstd-VERSION-bin
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition to the removal of systemd (&lt;code&gt;systemd-minimal-libs&lt;/code&gt;),&lt;br&gt;
in NixNG, many other packages have also been omitted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;To be blunt, the default advice for minimizing container size is&lt;br&gt;
often: &lt;strong&gt;"Use Alpine or Distroless!"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;However, if committed to using Nix in a project and want to&lt;br&gt;
save a bit on cloud storage or bandwidth costs, NixNG should be&lt;br&gt;
a viable option.&lt;/p&gt;




&lt;p&gt;Translated from the original post&lt;br&gt;
at &lt;a href="https://m15a.dev/ja/posts/nixng-image-size/" rel="noopener noreferrer"&gt;https://m15a.dev/ja/posts/nixng-image-size/&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>nix</category>
      <category>nixos</category>
      <category>nixng</category>
      <category>containers</category>
    </item>
  </channel>
</rss>
