<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Docker | 个人主页</title><link>https://page.syscall.cn/tags/docker/</link><atom:link href="https://page.syscall.cn/tags/docker/index.xml" rel="self" type="application/rss+xml"/><description>Docker</description><generator>Hugo Blox Builder (https://hugoblox.com)</generator><language>zh-Hans</language><lastBuildDate>Wed, 16 Sep 2026 00:00:00 +0000</lastBuildDate><image><url>https://page.syscall.cn/media/icon_hu7729264130191091259.png</url><title>Docker</title><link>https://page.syscall.cn/tags/docker/</link></image><item><title>🖼 自建照片库 Immich：从手机相册到私有 AI 图库</title><link>https://page.syscall.cn/post/selfhosted-immich/</link><pubDate>Wed, 16 Sep 2026 00:00:00 +0000</pubDate><guid>https://page.syscall.cn/post/selfhosted-immich/</guid><description>&lt;blockquote>
&lt;p>把照片交给云厂商，本质是用隐私换便利。这篇记录我用 Immich 把这个交换关系反过来：&lt;strong>便利我全要，隐私我自己留。&lt;/strong>&lt;/p>
&lt;/blockquote>
&lt;h2 id="一为什么不用网盘--相册-app">一、为什么不用网盘 + 相册 App&lt;/h2>
&lt;p>传统方案是&amp;quot;网盘存文件 + 手机相册 App 看&amp;quot;。问题是：&lt;/p>
&lt;ul>
&lt;li>网盘不懂照片，没有时间线、没有地图、没有&amp;quot;找那只猫&amp;quot;&lt;/li>
&lt;li>相册 App 不懂备份，换手机要手动导&lt;/li>
&lt;li>两边的元数据（时间、地点、人物）永远对不齐&lt;/li>
&lt;/ul>
&lt;p>Immich 的价值在于&lt;strong>它同时是备份工具和相册应用&lt;/strong>，元数据从上传那一刻就统一。&lt;/p>
&lt;h2 id="二部署形态">二、部署形态&lt;/h2>
&lt;p>标准 Immich 是四容器结构：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">immich-server ← API + Web UI + 任务调度
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">immich-machine-learning ← CLIP 模型推理 / 人脸检测
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">immich-postgres ← 元数据库
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">immich-redis ← 队列与缓存
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>关键设计点：&lt;/p>
&lt;p>&lt;strong>1. 数据与容器分离。&lt;/strong> 上传目录（&lt;code>UPLOAD_LOCATION&lt;/code>）和 PostgreSQL 数据目录必须是宿主机绑定挂载，而不是匿名卷 —— 否则容器一重建，照片就没了。&lt;/p>
&lt;p>&lt;strong>2. 对外只走 TLS 反代。&lt;/strong> Immich 本身监听 2283（HTTP），我用 nginx 在 2284 上做了 HTTPS 反代。手机 App 填的是 &lt;code>https://&amp;lt;域名&amp;gt;:2284&lt;/code>，不是裸端口。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-nginx" data-lang="nginx">&lt;span class="line">&lt;span class="cl">&lt;span class="k">server&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">listen&lt;/span> &lt;span class="mi">2284&lt;/span> &lt;span class="s">ssl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">server_name&lt;/span> &lt;span class="s">home.***.cn&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">client_max_body_size&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1"># 相册上传不限体积
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">location&lt;/span> &lt;span class="s">/&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">proxy_pass&lt;/span> &lt;span class="s">http://127.0.0.1:2283&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">proxy_set_header&lt;/span> &lt;span class="s">Host&lt;/span> &lt;span class="nv">$host&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">proxy_set_header&lt;/span> &lt;span class="s">X-Forwarded-Proto&lt;/span> &lt;span class="s">https&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">proxy_http_version&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="s">.1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">proxy_set_header&lt;/span> &lt;span class="s">Upgrade&lt;/span> &lt;span class="nv">$http_upgrade&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kn">proxy_set_header&lt;/span> &lt;span class="s">Connection&lt;/span> &lt;span class="s">&amp;#34;upgrade&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>client_max_body_size 0&lt;/code> 是必须的 —— 默认 1MB 会让上传静默失败。&lt;code>Upgrade&lt;/code>/&lt;code>Connection&lt;/code> 两个头是为了 WebSocket（移动端上传进度实时回传）。&lt;/p>
&lt;p>&lt;strong>3. 高位端口 + SNI。&lt;/strong> 在 80/443 受限的网络环境里，HTTPS 挪到 2284 端口仍然能正常握手 —— TLS 不关心端口号，只关心 SNI。&lt;/p>
&lt;h2 id="三智能搜索的真实边界">三、智能搜索的真实边界&lt;/h2>
&lt;p>Immich 的智能搜索基于 CLIP 模型（默认 &lt;code>ViT-B-32__openai&lt;/code>）。这里有一个&lt;strong>必须知道的坑&lt;/strong>：&lt;/p>
&lt;blockquote>
&lt;p>默认模型的文本编码器是&lt;strong>纯英文&lt;/strong>的。搜 &lt;code>cat&lt;/code> 能出结果，搜 &lt;code>猫&lt;/code> 静默返回空。&lt;/p>
&lt;/blockquote>
&lt;p>不是 bug，是模型的词表限制。三条应对路径：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>换多语言模型&lt;/strong>：需要重新跑一遍索引，代价大且显存要求更高。&lt;/li>
&lt;li>&lt;strong>用英文检索 + 内部约定&lt;/strong>：把常搜的类别固定成英文词（&lt;code>cat&lt;/code>/&lt;code>sunset&lt;/code>/&lt;code>food&lt;/code>/&lt;code>document&lt;/code>），写进自己的使用习惯。&lt;/li>
&lt;li>&lt;strong>依赖人脸与地点这类非文本维度&lt;/strong> —— 它们不经过文本编码器，中文环境完全可用。&lt;/li>
&lt;/ol>
&lt;p>我选了 2 + 3 的组合。人脸识别用的是 InsightFace 的 &lt;code>buffalo_l&lt;/code> 模型包，识别与聚类都在本地完成，人名只存在你自己的数据库里。&lt;/p>
&lt;h2 id="四按人检索的-api">四、按人检索的 API&lt;/h2>
&lt;p>除了 Web UI，Immich 的 REST API 允许按人物 ID 直接检索：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">POST /api/search/metadata
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;personIds&amp;#34;&lt;/span>: &lt;span class="o">[&lt;/span>&lt;span class="s2">&amp;#34;&amp;lt;person-uuid&amp;gt;&amp;#34;&lt;/span>&lt;span class="o">]&lt;/span>,
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s2">&amp;#34;size&amp;#34;&lt;/span>: &lt;span class="m">100&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>配合 &lt;code>/api/people&lt;/code> 列出已聚类的所有人物，就能做出&amp;quot;某个人的全部照片&amp;quot;这种自定义视图 —— 比如生成家庭相册、或者做年度回顾。&lt;/p>
&lt;h2 id="五资源占用别被瞬时峰值骗了">五、资源占用：别被瞬时峰值骗了&lt;/h2>
&lt;p>一个真实教训：监控告警说 Immich 峰值吃了 1GB 内存，接近宿主上限。第一反应是&amp;quot;要加内存了&amp;quot;，但拉时间线一看：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">峰值时间：每天 00:00 前后
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">持续时间：数分钟
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">原因：后台扫描任务（缩略图生成 / 人脸检测 / 智能索引）
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>这是周期性批处理，不是常驻开销。&lt;/strong> 稳态内存远低于峰值。结论是：&lt;/p>
&lt;ul>
&lt;li>判断是否需要扩容，要看&lt;strong>稳态 + P95&lt;/strong>，不是看单点峰值&lt;/li>
&lt;li>批处理任务可以限流（&lt;code>IMMICH_...&lt;/code> 并发参数），避开高峰期&lt;/li>
&lt;li>如果宿主真的很小，把 ML 推理拆到另一台机器上（远程 ML 后端）&lt;/li>
&lt;/ul>
&lt;h2 id="六远程-ml-后端把小主机的活外包出去">六、远程 ML 后端：把小主机的活外包出去&lt;/h2>
&lt;p>当宿主的 CPU 实在扛不住 CLIP 推理时，Immich 支持把机器学习服务拆出去：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-yaml" data-lang="yaml">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># immich-server 侧&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="nt">environment&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nt">IMMICH_MACHINE_LEARNING_URL&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="l">http://&amp;lt;remote-host&amp;gt;:3003&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>远程那边只要跑 &lt;code>immich-machine-learning&lt;/code> 一个容器，通过 SSH 隧道或内网直连暴露 3003 端口即可。这样&lt;strong>照片库留在本地，算力借用别处&lt;/strong> —— 数据不动，计算下沉。&lt;/p>
&lt;h2 id="七复盘">七、复盘&lt;/h2>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>维度&lt;/th>
&lt;th>结论&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>存储&lt;/td>
&lt;td>照片目录必须挂宿主机，容器要能随便删&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>访问&lt;/td>
&lt;td>对外只给 TLS 反代，端口用高位&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>搜索&lt;/td>
&lt;td>默认 CLIP 是英文的，中文搜索要么换模型要么改用英文词&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>人脸&lt;/td>
&lt;td>本地模型，人名不上云，中文环境无影响&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>容量&lt;/td>
&lt;td>看稳态不看峰值；峰值多是后台扫描&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>扩展&lt;/td>
&lt;td>算力不够就拆 ML 后端，别动数据&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>一句话：&lt;strong>自建照片库最难的不是装，而是想清楚哪些数据必须留在自己手里。&lt;/strong>&lt;/p></description></item><item><title>Immich 私人照片库</title><link>https://page.syscall.cn/project/immich/</link><pubDate>Sun, 27 Oct 2024 00:00:00 +0000</pubDate><guid>https://page.syscall.cn/project/immich/</guid><description>&lt;p>自建的私人照片管理与 AI 图库，支持手机备份、智能搜索、人脸识别和地理定位。&lt;/p>
&lt;p>当前地址：&lt;a href="https://home.syscall.cn:2284/" target="_blank" rel="noopener">https://home.syscall.cn:2284/&lt;/a>&lt;/p></description></item></channel></rss>