{"id":5392,"date":"2026-08-30T17:50:35","date_gmt":"2026-08-30T08:50:35","guid":{"rendered":"https:\/\/donguri3.net\/server-tech\/wsl2-podman-localllm-setup-2\/"},"modified":"2026-08-30T17:50:37","modified_gmt":"2026-08-30T08:50:37","slug":"wsl2-podman-localllm-setup","status":"publish","type":"post","link":"https:\/\/donguri3.net\/en\/server-tech\/ai-local-llm\/wsl2-podman-localllm-setup\/","title":{"rendered":"No Docker Required: Building a Lightweight Local LLM Environment with WSL2 and Podman"},"content":{"rendered":"<p>Currently, I am experimenting with building a &#8220;multi-agent&#8221; system that coordinates multiple AIs.<br \/>Rather than letting SaaS (such as ChatGPT or Gemini) handle all processing, I decided to go with a hybrid architecture combined with a local LLM running on my own machine.<\/p>\n<p>To build the local LLM environment, I use containers that keep the Windows side clean. While standard Docker is an option, Docker leaves a daemon (management process) running in the background even when idle and not using AI, needlessly consuming PC resources. For future multi-agent development, I want to keep my local environment as streamlined and lightweight as possible.<\/p>\n<p>Therefore, this time I built a clean local LLM environment (Ollama + Open WebUI) on WSL2 using &#8220;Podman,&#8221; which has low resource consumption and runs completely daemonless.<\/p>\n<h2>Keeping Two Local LLMs in Standby<\/h2>\n<p>The specific goals are as follows:<\/p>\n<ol>\n<li>Environment cleanup: Avoid installing Docker Desktop on Windows, and reduce background processes completely to &#8220;zero&#8221; when containers are stopped.<\/li>\n<li>Multi-model standby: Taking advantage of the RTX 3060 (12GB VRAM) headroom, launch two lightweight models strong in Japanese (qwen3:4b and gemma3:4b) simultaneously.<\/li>\n<\/ol>\n<h2>[Personal Experience] The &#8220;5 Traps&#8221; I Fell Into When Migrating to Podman<\/h2>\n<p>When switching from Docker to Podman, I neatly fell into several traps. Knowing the following countermeasures should save you from wasting time.<\/p>\n<ol>\n<li>Trap where the GPU is not recognized<br \/>GPU does not work with Docker syntax. Instead, use &#8220;CDI,&#8221; an official mechanism provided by NVIDIA to connect GPUs directly to containers.<\/li>\n<li>Trap where images cannot be downloaded<br \/>Podman is strict about security and rejects shorthand names. Always specify the full path (fully qualified name) like docker.io\/ollama\/ollama.<\/li>\n<li>Trap where chat history disappears<br \/>Directly specifying a Windows-side folder causes database corruption due to permission errors. Use &#8220;named volumes,&#8221; where Podman automatically creates a safe storage area.<\/li>\n<li>Trap where loading takes longer after 5 minutes of inactivity<br \/>By default, models are evicted from VRAM if there is no chat activity for 5 minutes. Set the environment variable OLLAMA_KEEP_ALIVE=-1 to disable timeout and keep them resident in VRAM at all times.<\/li>\n<li>Trap where models are not loaded simultaneously<br \/>Even if you try to switch and use two models assuming a multi-agent setup, the default specification is that &#8220;only one model can be loaded into VRAM at a time.&#8221; Explicitly specify the environment variable OLLAMA_MAX_LOADED_MODELS=2 to allow simultaneous standby of two models.<\/li>\n<\/ol>\n<h2>[Shortest Build Procedure] docker-compose.yml<\/h2>\n<p>As a prerequisite, it is assumed that a WSL2 (Ubuntu 22.04 or later) environment is prepared.<\/p>\n<h3>Step 1: Installing Podman and GPU Integration Tools<\/h3>\n<p>Open the Ubuntu terminal and install the required packages.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\"># Podman core and Compose tools introduction\nsudo apt update\nsudo apt install -y podman podman-compose podman-docker\n\n# Introduce NVIDIA-provided GPU passthrough tool\nsudo apt-get install -y nvidia-container-toolkit\n\n# Automatically generate configuration file for CDI (direct GPU connection mechanism)\nsudo nvidia-ctk cdi generate --output=\/etc\/cdi\/nvidia.yaml<\/pre>\n<h3>Step 2: Creating docker-compose.yml<\/h3>\n<p>Create the following docker-compose.yml in an appropriate working folder. This is the definitive edition incorporating all countermeasures against the &#8220;5 traps based on personal experience&#8221; mentioned above.<\/p>\n<pre class=\"brush: yaml; title: ; notranslate\" title=\"\">services:\n  ollama:\n    image: docker.io\/ollama\/ollama\n    container_name: ollama\n    ports:\n      - &quot;0.0.0.0:11434:11434&quot;\n    environment:\n      - &quot;OLLAMA_KEEP_ALIVE=-1&quot;          # Countermeasure for Trap 4: Disable timeout\n      - &quot;OLLAMA_MAX_LOADED_MODELS=2&quot;    # Countermeasure for Trap 5: Simultaneous standby of 2 models\n    volumes:\n      - ollama_data:\/root\/.ollama       # Countermeasure for Trap 3: Named volume\n    devices:\n      - nvidia.com\/gpu=all              # Countermeasure for Trap 1: GPU passthrough via CDI\n\n  open-webui:\n    image: ghcr.io\/open-webui\/open-webui:main\n    container_name: open-webui\n    ports:\n      - &quot;0.0.0.0:3000:8080&quot;\n    environment:\n      - OLLAMA_BASE_URL=http:\/\/ollama:11434\n    volumes:\n      - open-webui_data:\/app\/backend\/data\n    depends_on:\n      - ollama\n\nvolumes:\n  ollama_data:\n  open-webui_data:<\/pre>\n<h3>Step 3: Startup and Fetching AI Models<\/h3>\n<p>Do not use sudo under any circumstances; run the startup command as a regular user.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">podman-compose up -d<\/pre>\n<p>Once started, download the models you want to use within the Ollama container.<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">podman exec -it ollama ollama run qwen3:4b\npodman exec -it ollama ollama run gemma3:4b<\/pre>\n<p>You can also add models via settings on the browser.<\/p>\n<p><a href=\"https:\/\/donguri3.net\/wp-content\/uploads\/2026\/03\/68736b887d7eef46240becfe5d523cb2.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-2904\" src=\"https:\/\/donguri3.net\/wp-content\/uploads\/2026\/03\/68736b887d7eef46240becfe5d523cb2.png\" alt=\"Acquiring AI Models\" width=\"490\" height=\"616\" srcset=\"https:\/\/donguri3.net\/wp-content\/uploads\/2026\/03\/68736b887d7eef46240becfe5d523cb2.png 490w, https:\/\/donguri3.net\/wp-content\/uploads\/2026\/03\/68736b887d7eef46240becfe5d523cb2-239x300.png 239w, https:\/\/donguri3.net\/wp-content\/uploads\/2026\/03\/68736b887d7eef46240becfe5d523cb2-422x530.png 422w, https:\/\/donguri3.net\/wp-content\/uploads\/2026\/03\/68736b887d7eef46240becfe5d523cb2-449x565.png 449w\" sizes=\"(max-width: 490px) 100vw, 490px\" \/><\/a><\/p>\n<h3>Step 4: Disabling Timeout on the WebUI Side<\/h3>\n<p>Access http:\/\/localhost:3000 from your Windows browser and log in to Open WebUI. Navigate to &#8220;Admin Panel&#8221; &gt; &#8220;Settings&#8221; &gt; &#8220;General&#8221; &gt; &#8220;Advanced Parameters&#8221; at the bottom left of the screen, change the &#8220;Keep Alive (Ollama)&#8221; item to -1, and save.<\/p>\n<h2>[Summary] A Clean Foundation to Leverage Local Resources is Complete<\/h2>\n<p>When no longer needed, simply shut it down with podman-compose down, and background processes and VRAM consumption will drop completely to &#8220;zero.&#8221;<\/p>\n<p>By moving away from standard Docker Desktop and implementing Podman with a little ingenuity, I obtained an extremely clean environment that makes efficient use of limited resources (RTX 3060) without waste.<\/p>\n<p>Using this agile local LLM environment as a foundation, next time I will proceed with building a &#8220;multi-agent&#8221; system that actually integrates with SaaS (such as Gemini).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Currently, I am experimenting with building a &#8220;multi-agent&#8221; system that coordinates multiple AIs.R [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":2906,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_locale":"en_US","_original_post":"https:\/\/donguri3.net\/?p=2903","footnotes":""},"categories":[1169],"tags":[18,19,1006,1125,100,1000,365,291,931,310],"class_list":["post-5392","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ai-local-llm","tag-docker","tag-docker-compose","tag-gemini","tag-podman","tag-ubuntu-22-04","tag-wsl","tag-wsl2","tag-yaml","tag-931","tag-310","en-US"],"_links":{"self":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/5392","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/comments?post=5392"}],"version-history":[{"count":1,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/5392\/revisions"}],"predecessor-version":[{"id":5395,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/posts\/5392\/revisions\/5395"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/media\/2906"}],"wp:attachment":[{"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/media?parent=5392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/categories?post=5392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/donguri3.net\/wp-json\/wp\/v2\/tags?post=5392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}