<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Docker-Compose on K-Life Hack | Seoul Gastronomy &amp; Travel Guide</title><link>https://klifehack.com/en/tags/docker-compose/</link><description>Recent content in Docker-Compose on K-Life Hack | Seoul Gastronomy &amp; Travel Guide</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Thu, 21 May 2026 17:43:23 +0900</lastBuildDate><atom:link href="https://klifehack.com/en/tags/docker-compose/index.xml" rel="self" type="application/rss+xml"/><item><title>Deploying Immich on Windows 11 with Tailscale and Upload Optimization</title><link>https://klifehack.com/en/p/immich-windows-tailscale-upload-optimization/</link><pubDate>Thu, 21 May 2026 17:43:23 +0900</pubDate><guid>https://klifehack.com/en/p/immich-windows-tailscale-upload-optimization/</guid><description>&lt;h2 id="initializing-wsl2-and-docker-desktop-backend-for-immich"&gt;Initializing WSL2 and Docker Desktop Backend for Immich
&lt;/h2&gt;&lt;p&gt;The deployment of Immich within a Windows 11 environment necessitates a sophisticated virtualization strategy to bridge the gap between Windows-native operations and Linux-centric containerized binaries. The Windows Subsystem for Linux (WSL2) serves as this critical infrastructure, providing a genuine Linux kernel interface that allows Docker containers to achieve near-native execution speeds. Unlike traditional Hyper-V implementations that incur significant overhead, WSL2 utilizes a lightweight utility virtual machine that dynamically shares hardware resources with the host operating system. This architecture is particularly advantageous for resource-constrained hardware such as the Intel N100-based Mini PC, where efficient CPU scheduling and memory management are paramount for maintaining system responsiveness.&lt;/p&gt;
&lt;p&gt;Furthermore, the integration of Docker Desktop with the WSL2 backend requires precise configuration to ensure the Docker daemon operates within a specialized Linux distribution. This setup optimizes file system performance, which is often a bottleneck in cross-platform virtualization. Verification of the environment is conducted via the command line interface using &lt;code&gt;wsl --list --verbose&lt;/code&gt;. If the distribution is not utilizing version 2, immediate remediation is required through the &lt;code&gt;wsl --update&lt;/code&gt; command. This process ensures the latest kernel patches from Microsoft are applied, followed by a &lt;code&gt;wsl --shutdown&lt;/code&gt; to force a clean initialization of the virtualized environment.&lt;/p&gt;
&lt;p&gt;Quantitatively speaking, memory management represents one of the most significant challenges when running WSL2 on a host with limited RAM. By default, WSL2 can consume a substantial portion of the host&amp;rsquo;s physical memory due to its dynamic allocation logic, potentially leading to &amp;ldquo;Out of Memory&amp;rdquo; (OOM) errors in the Windows host environment. To mitigate this, a &lt;code&gt;.wslconfig&lt;/code&gt; file must be implemented in the user&amp;rsquo;s home directory. For a system equipped with 16GB of RAM, restricting the WSL2 instance to 8GB provides a balanced allocation, ensuring that Immich’s machine learning models and transcoding tasks have sufficient resources without starving the host OS. This proactive resource capping is essential for maintaining 24/7 uptime in a production-grade self-hosted environment.&lt;/p&gt;
&lt;h2 id="implementing-tailscale-mesh-vpn-for-secure-remote-access"&gt;Implementing Tailscale Mesh VPN for Secure Remote Access
&lt;/h2&gt;&lt;p&gt;Establishing secure remote access for Immich without the inherent risks of public port forwarding is achieved through the implementation of Tailscale. This mesh VPN solution leverages the WireGuard protocol to construct an encrypted overlay network, known as a tailnet, which connects disparate devices regardless of their physical location. Each node within the tailnet is assigned a stable, private IP address, typically within the 100.64.0.0/10 range. Consequently, the need for complex Dynamic DNS (DDNS) configurations or vulnerable firewall exceptions is eliminated, as Tailscale facilitates NAT traversal through its coordination server and global DERP (Detour Entrusting Reliable Proxy) relay network.&lt;/p&gt;
&lt;p&gt;In addition to simplified connectivity, Tailscale provides a robust security layer by ensuring the Immich API and web interface are only reachable by authenticated devices. The Windows 11 host, acting as the server node, is assigned a static internal address such as &lt;b&gt;&lt;mark&gt;100.XX.XX.XX&lt;/mark&gt;&lt;/b&gt;. This address serves as the primary endpoint for mobile clients globally. By utilizing Tailscale’s Access Control Lists (ACLs), administrators can further restrict traffic to the specific Immich service port, effectively minimizing the attack surface and providing a granular security posture that traditional VPNs often lack. This architecture ensures that family members can synchronize media from any cellular or Wi-Fi network without compromising the integrity of the home network.&lt;/p&gt;
&lt;h2 id="orchestrating-immich-services-via-docker-compose"&gt;Orchestrating Immich Services via Docker Compose
&lt;/h2&gt;&lt;p&gt;The orchestration of Immich’s microservices architecture is managed through a comprehensive Docker Compose configuration. This stack includes the core server, a microservices worker for background processing, a machine learning engine for image analysis, and a high-performance PostgreSQL database equipped with the &lt;code&gt;pgvecto-rs&lt;/code&gt; extension. A critical aspect of this deployment on Windows is the translation of file paths. To ensure compatibility with the WSL2 Docker engine, the &lt;code&gt;.env&lt;/code&gt; file must utilize forward slashes for all directory mappings, such as &lt;code&gt;C:/immich-server/library&lt;/code&gt;. Failure to adhere to this syntax will result in volume mounting errors and container initialization failures within the Docker daemon.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;version&lt;/span&gt;: &lt;span style="color:#e6db74"&gt;&amp;#34;3.8&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;services&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;immich-server&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;container_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;immich_server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ghcr.io/immich-app/immich-server:v1.105.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;${UPLOAD_LOCATION}:/usr/src/app/upload&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;/etc/localtime:/etc/localtime:ro&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;env_file&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;.env&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;2283:2283&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;depends_on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;redis&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;database&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;database&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;container_name&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;immich_postgres&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;tensorchord/pgvecto-rs:pg16-v0.2.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;POSTGRES_PASSWORD&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${DB_PASSWORD}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;POSTGRES_USER&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${DB_USERNAME}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;POSTGRES_DB&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;${DB_DATABASE_NAME}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;volumes&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;${DB_DATA_LOCATION}:/var/lib/postgresql/data&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The inclusion of the &lt;code&gt;pgvecto-rs&lt;/code&gt; image is vital for the semantic search and facial recognition features that define the Immich experience. During the initial execution of &lt;code&gt;docker compose up -d&lt;/code&gt;, the system pulls the necessary images and executes database migrations. Monitoring these logs via &lt;code&gt;docker compose logs -f&lt;/code&gt; is a mandatory verification step. Any interruption during the database schema initialization will prevent the server from binding to port &lt;b&gt;&lt;mark&gt;2283&lt;/mark&gt;&lt;/b&gt;, leading to service unavailability. Furthermore, the Intel N100’s hardware acceleration can be utilized by the machine learning and transcoding services by passing the &lt;code&gt;/dev/dri&lt;/code&gt; device into the relevant containers, significantly reducing CPU load during heavy processing tasks.&lt;/p&gt;
&lt;h2 id="integrating-upload-optimizer-for-storage-constraint-management"&gt;Integrating Upload Optimizer for Storage Constraint Management
&lt;/h2&gt;&lt;p&gt;Managing storage constraints on a 1TB SSD requires the integration of an upload optimizer to prevent rapid volume saturation. The &lt;code&gt;immich-upload-optimizer&lt;/code&gt; functions as a specialized reverse proxy that intercepts incoming media uploads. By analyzing the metadata and file size of incoming multipart/form-data requests, the optimizer can transcode high-bitrate 4K videos or massive RAW images into more efficient formats before they reach the Immich server. This process is handled transparently, ensuring that the mobile user experience remains seamless while significantly extending the longevity of the server&amp;rsquo;s storage hardware.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#f92672"&gt;immich-upload-optimizer&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;image&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;ghcr.io/miguelangel-nubla/immich-upload-optimizer:latest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;ports&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#e6db74"&gt;&amp;#34;2283:2283&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;environment&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;IUO_UPSTREAM=http://immich-server:2283&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;IUO_TASKS_IMAGE_MAX_SIZE=4MB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;IUO_TASKS_VIDEO_MAX_SIZE=40MB&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;depends_on&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; - &lt;span style="color:#ae81ff"&gt;immich-server&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#f92672"&gt;restart&lt;/span&gt;: &lt;span style="color:#ae81ff"&gt;always&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In this optimized configuration, the direct port mapping for the &lt;code&gt;immich-server&lt;/code&gt; is removed, and the optimizer assumes control of port 2283. The &lt;code&gt;IUO_UPSTREAM&lt;/code&gt; variable facilitates internal communication within the Docker network. By leveraging the Intel N100’s QuickSync capabilities, the optimizer can perform hardware-accelerated transcoding using FFmpeg, which minimizes the latency introduced during the upload phase. This architectural choice is particularly effective for multi-user environments where simultaneous uploads from modern smartphones could otherwise overwhelm the server&amp;rsquo;s processing and storage capacity.&lt;/p&gt;
&lt;h2 id="resolving-environment-variable-syntax-and-image-pull-failures"&gt;Resolving Environment Variable Syntax and Image Pull Failures
&lt;/h2&gt;&lt;p&gt;Operational stability in a Windows-based Docker environment often hinges on the precise syntax of environment variables. Docker Compose V2 is notoriously sensitive to formatting within the &lt;code&gt;.env&lt;/code&gt; file; common errors such as &amp;ldquo;key cannot contain a space&amp;rdquo; usually stem from trailing spaces or inline comments. To ensure a successful deployment, the &lt;code&gt;.env&lt;/code&gt; file must be strictly sanitized to follow the &lt;code&gt;KEY=VALUE&lt;/code&gt; format. Additionally, network timeouts during the image pull phase can occur due to DNS resolution issues within WSL2. This can be resolved by manually configuring DNS servers in &lt;code&gt;/etc/wsl.conf&lt;/code&gt; or restarting the Docker Desktop service to refresh the virtual network bridge.&lt;/p&gt;
&lt;p&gt;Finally, the portability of the Immich stack is one of its primary advantages. Since all persistent data, including the database and the library, is stored within the &lt;code&gt;C:\immich-server&lt;/code&gt; directory, disaster recovery is straightforward. Regular backups of this directory allow for rapid migration to new hardware. By simply transferring the folder and executing the Docker Compose commands on a new host, the entire service can be restored with minimal downtime, ensuring that the personal media archive remains secure and accessible over the long term. Verification of the final stack is performed by accessing the Tailscale IP from a remote device, confirming that the network routing and backend services are correctly aligned.&lt;/p&gt;</description></item></channel></rss>