Immich 自托管需要多少内存?如何安全升级
了解 Immich 的真实内存需求、HTTPS 反向代理端口 2283、exit 137 内存终止错误,以及 Immich v3 无法启动 pgvecto.rs 数据库的原因和恢复步骤。
您要构建的内容
Immich 是一款自托管的照片和视频备份服务,可以真正替代 Google Photos。它提供手机应用,可在后台上传相机胶卷;还提供时间线、相册、人脸识别和机器学习搜索。无需手动添加标签,它就能找到“海滩”照片或某个人的照片。您可以将它运行在自己拥有的 VPS 上,原始文件保留在自己的磁盘中,也不会有人扫描这些文件来向您投放商品广告。如果您仍在考虑另一个明显的候选方案,我们的 PhotoPrism 与 Immich 对比将两者的最低内存要求、手机应用和备份命令并列展示。
安装过程需要使用项目自带的 Docker Compose 文件启动 4 个容器。这部分只需 10 分钟。真正麻烦的是本指南的其他内容:在配置较小的机器上,机器学习容器非常耗费内存;原始文件会快速占满磁盘;移动应用拒绝连接纯 HTTP 服务器;而 Immich 发布破坏性变更的频率很高,粗心的 docker compose pull 可能导致数据库无法启动。认真处理这 4 个问题,Immich 就会非常稳定。忽略它们,您可能会损失一个周末。
前置条件和需要正视的问题
- RAM:官方文档要求至少 6 GB,建议 8 GB;请将 4 GB 加 swap 视为绝对下限。
immich-server和 Postgres 容器的内存占用不高。immich-machine-learning容器的占用量最大,因为它会将 CLIP 和人脸识别模型加载到 RAM 中以构建搜索索引。在 2 GB 的服务器上,内核会将其终止。即使有 4 GB RAM,也应配置 swap。 - 磁盘:应按整个图库的大小规划,并预留额外空间。 原始文件会被完整复制,Immich 还会生成缩略图和预览图,额外占用通常约为 10–20%。一个 200 GB 的照片库需要 300 GB 的卷。相比之下,Postgres 的占用量较小。
- CPU:任何较新的 KVM VPS 都可以,但在 CPU 上运行 ML 速度较慢。 大规模导入的智能搜索索引可能会在后台运行数小时。这是正常现象,不需要 GPU。
- 一个指向 VPS 的域名。 移动应用强烈建议使用 HTTPS 端点,并且应在前面配置反向代理。这与 使用 Docker、TLS 和备份自托管 Nextcloud 实例的架构相同;Immich 相当于该文件服务器的照片服务。
- 已安装 Docker 和 Compose 插件。 应从 Docker 官方 apt 仓库安装 Docker Engine 和 Compose v2 插件,具体步骤参见我们的 Docker Compose 基础指南。
第 1 步:先添加 swap
在小型 VPS 上,Immich 最常见的故障是 ML 容器因内存不足(OOM)被终止。先为内核提供可用的 swap 空间。
sudo fallocate -l 4G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
free -h现在,free -h 应显示一行 Swap:,其值为 4.0Gi。这不会提升 ML 的运行速度,但可以避免容器在 4 GB 机器上建立索引时中途退出。
第 2 步:获取官方 compose 文件和环境文件,使用官方文件,不要使用副本
Immich 会在其发布的文件中固定服务版本,尤其是数据库镜像版本。不要将博客中的 compose 文件(包括本文中的文件)作为唯一依据。下载发布资产:
sudo mkdir -p /opt/immich && cd /opt/immich
sudo wget -O docker-compose.yml https://github.com/immich-app/immich/releases/latest/download/docker-compose.yml
sudo wget -O .env https://github.com/immich-app/immich/releases/latest/download/example.env这些文件来自带标签的发布版本,因此其中的镜像引用相互匹配。compose 文件定义了 4 个服务。在进行任何修改前,先了解每个服务的作用:
immich-server(ghcr.io/immich-app/immich-server,容器immich_server)负责 API 和 Web UI,监听端口2283。它将您的上传目录挂载到/data。immich-machine-learning(ghcr.io/immich-app/immich-machine-learning,容器immich_machine_learning)负责 CLIP 搜索和人脸识别。它会将下载的模型缓存到model-cache卷中。这是最占用内存的服务。database(容器immich_postgres)运行带有 VectorChord 向量扩展的 Postgres,为相似度搜索提供支持。镜像标签会直接在 compose 文件中通过摘要固定,例如ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0@sha256:...。较旧的部署使用pgvecto.rs;Immich v3.0 已移除对它的支持,因此现在安装的版本都会使用 VectorChord。绝不要手动编辑此标签。redis(容器immich_redis)运行 Valkey/Redis 实例,为作业队列提供支持。
步骤 3:配置 .env,照片和数据库存储在这里
打开 .env 并设置以下 4 项。标记行之后的所有内容保持不变。
# Where original uploads are stored on the host
UPLOAD_LOCATION=/opt/immich/library
# Where the Postgres data lives. NEVER put this on an NFS/network share.
DB_DATA_LOCATION=/opt/immich/postgres
# "v3" is a floating tag that tracks the latest v3.x. Pin a full tag like
# v3.0.2 instead — then you upgrade on purpose, not by surprise.
IMMICH_VERSION=v3.0.2
# Change this to a long random string. Letters and digits only.
DB_PASSWORD=REPLACE_WITH_A_LONG_RANDOM_STRING
# Set your timezone so timestamps and "on this day" line up
TZ=Europe/London
###################################################################################
DB_USERNAME=postgres
DB_DATABASE_NAME=immich两条规则可以避免后续问题。UPLOAD_LOCATION 应指向大容量磁盘;如果之后要挂载数据卷,请从一开始就将其设置为该卷的挂载路径,因为事后迁移意味着需要移动缩略图并更新资源路径。DB_DATA_LOCATION 必须位于本地磁盘上:Postgres 在 NFS 或 SMB 共享上运行会导致数据损坏,文档对此已有明确说明。在 DB_PASSWORD 中仅使用字母和数字,可以避免一类连接字符串转义错误。
第 4 步:首次运行并创建 admin 用户
cd /opt/immich
sudo docker compose up -d
sudo docker compose ps正确结果应为 4 个容器,全部处于 running 状态,并最终变为 healthy:
NAME STATUS
immich_machine_learning Up (healthy)
immich_postgres Up (healthy)
immich_redis Up (healthy)
immich_server Up (healthy)首次执行 up 时会拉取数 GB 的镜像,请耐心等待。使用 sudo docker compose logs -f immich-server 监控进度;服务器就绪后,会在日志中记录其正在监听端口 2283。现在在浏览器中打开 http://YOUR_SERVER_IP:2283。首次访问时会显示 入门向导,您创建的第一个账户就是 admin。请设置强密码;该账户拥有服务器设置、用户管理权限,以及稍后需要配置的 ML 配置。
第 5 步:移动应用和后台备份
从 App Store 或 Play Store 安装 “Immich”。在登录界面中,应用会要求填写 Server Endpoint URL。输入包含 scheme 的完整 URL,例如 https://photos.example.com(应用会自动追加 /api)。使用刚创建的账户登录,然后打开应用的 Backup 页面,选择要保护的相册(通常是 Camera 和 Screenshots),并启用 Background backup。iOS 会限制后台备份的运行频率;前台上传始终会运行,后台上传则在操作系统允许时执行。
这正是许多用户遇到问题的地方,因此在排查应用之前先阅读第 6 步。
第 6 步:通过反向代理启用 HTTPS,以及完整 URL 规则
移动应用确实需要 HTTPS。请在端口 2283 前配置反向代理,并在那里终止 TLS。如果您已经运行多个容器,为多个 Docker 应用配置带自动 TLS 的 Traefik 是最整洁的方案:一个标签块就能将 photos.example.com 路由到 immich-server 容器,并自动为您获取证书。如果您更喜欢 nginx,使用 Certbot 和 nginx 配置 Let's Encrypt 指南会为您获取证书并生成一个 proxy_pass http://127.0.0.1:2283; 块。代理配置完成后,添加下一个服务通常只需新增一个子域名。因此,像 Halcyon:Jellyfin 的 90 年代录像店界面 这样的媒体前端,也能与 Immich 并列运行在同一台主机上。自行托管 HarnessRouter,通过一个 API 提供 Codex 和 Claude Code 的情况也一样。它会特意绑定到 loopback,只有在前置代理终止 TLS 后才能访问。因此,在将子域名指向它之前,请先修改默认登录凭据。并非每个容器都需要公网主机名。例如,自行托管的 open-kritt 安全扫描器 仅供管理员使用,最好完全不接入代理;只有在少数需要打开其 UI 的情况下,再通过 SSH 隧道访问。其他服务则完全不使用代理,因为它们根本不使用 HTTP。自行托管的 RustDesk 中继服务器 就是最典型的例子:它监听少量原始 TCP 和 UDP 端口,需要配置防火墙规则,而不是设置子域名。Immich 有一个代理设置需要特别注意:请提高上传大小限制,因为手机视频文件通常很大。在 nginx 中,应在 server 块内设置 client_max_body_size 50000M;;默认的 1 MB 会导致视频上传因 413 Request Entity Too Large 被拒绝。
应用强制执行的规则是:端点必须可访问,实际使用时还必须是 HTTPS。http:// 端点,或省略端口的直接 IP 地址,都会导致“应用无法连接到服务器”。下面将此问题作为一个单独的故障类型介绍。
第 7 步:外部库与上传内容:导入现有照片目录
照片进入 Immich 有两种方式,两者并不相同。
- 上传内容是由 Immich 管理的资源。应用或 Web 上传器会将文件复制到
UPLOAD_LOCATION。Immich 可以重命名、移动和删除这些文件。 - 外部库是对服务器目录中现有文件的只读导入,例如旧的
Pictures目录树或 NAS 导出目录。Immich 会在原位置为这些文件建立索引,并在时间线中显示,但不会修改或删除原始文件。
要导入现有目录树,请将其以只读方式挂载到服务器容器中。编辑 docker-compose.yml 下的 immich-server:,并添加一个卷:
immich-server:
volumes:
- ${UPLOAD_LOCATION}:/data
- /etc/localtime:/etc/localtime:ro
- /srv/photos:/mnt/media/photos:ro:ro 可确保 Immich 永远无法修改原始文件。使用 sudo docker compose up -d 重新创建容器,然后在 Web UI 中依次打开您的头像 → 管理 → 外部库 → 创建库,选择所属用户,点击“文件夹”下的 添加,并输入容器路径 /mnt/media/photos,而不是主机路径 /srv/photos。点击扫描。使用主机路径而不是容器路径,是配置外部库时最常见的错误;扫描不会找到任何内容,并显示资源数为 0。
步骤 8:Immich 要求的升级纪律
这是决定 Immich 能否正常运行的关键。Immich 发布速度很快,不会回移植修复,也不支持降级。盲目跟踪浮动的 v3 标签,最终会导致数据库损坏。对于服务器上所有长期运行的容器,都应采用“固定版本后阅读更新说明”的做法。因此,自托管的 KiroCrew 代理会固定到一个已知正常的标签,而不是任由它在下一次重启时自动切换版本。具体要求如下:
- 固定版本。 将
IMMICH_VERSION设置为具体标签,例如v3.0.2,不要使用总是拉取最新 v3.x 的浮动标签v3。 - 每次升级前都要阅读更新说明。 其中会说明不兼容变更,尤其是数据库或向量扩展的变更。v3.0 版本就是一个典型例子:该版本直接移除了 pgvecto.rs,因此仍在使用旧扩展的用户,必须先完成 VectorChord 迁移(该迁移早在 v1.133 中引入),才能升级到更高版本。
- 先备份数据库(步骤 9)。任何时候都应备份;当更新说明提到数据库时,更要如此。
- 同时获取新的 compose 文件。
IMMICH_VERSION只固定 server 和 ML 镜像。Postgres 镜像的固定摘要位于docker-compose.yml中,因此需要新版数据库扩展的版本会随附新的 compose 文件。重新下载两个发布资源,重新应用您的.env值,然后再升级。 - 大致同时更新移动客户端。 server 只支持与其匹配的主版本,应用支持当前主版本和前一个主版本。如果 server 已升级到高于应用的版本,手机上会显示
Your app major version is not compatible with the server!,直到您更新应用。因此,最好先更新应用。
准备好新文件后,实际执行以下命令:
cd /opt/immich
sudo docker compose pull
sudo docker compose up -d
sudo docker image prune步骤 9:备份、数据库转储和原始文件,并测试备份
Immich 的备份包含两部分,缺少任何一部分都没有用。数据库保存相册结构、人脸数据、搜索索引,以及资源与文件之间的映射。原始文件目录保存实际照片。只恢复其中一部分,要么得到没有组织结构的照片,要么得到指向缺失文件的空壳。这个两部分结构并非 Immich 特有:自托管 Chatwoot 支持台同样需要 Postgres 转储和上传目录的组合,否则恢复后的收件箱会丢失所有附件。将 Postgres 数据目录作为文件树复制,看似可以跳过转储步骤,但这不是可用的备份。这是一个常见陷阱,完整的 Immich 备份与恢复教程会同时说明这一点,以及会让时间线变为空的恢复错误。
在 Postgres 容器内使用 pg_dump 转储数据库,目标是 immich 数据库,而不是整个集群:
sudo docker exec -t immich_postgres pg_dump --clean --if-exists \
--dbname=immich --username=postgres | gzip > /opt/immich/immich-db-$(date +%F).sql.gz然后备份 UPLOAD_LOCATION,即完整的 /opt/immich/library 目录树,尤其是其中的 library/、upload/ 和 profile/ 子目录。使用 restic、rsync 或 borg 将其备份到另一台机器或对象存储。无论使用 cron 条目还是 systemd timer 调度任务,都必须有失败告警渠道。使用指向您自己的 ntfy 推送服务器的 systemd OnFailure= 单元,可以在转储失败的当晚将消息发送到手机,而不是等到恢复时才发现问题。先备份数据库,再备份文件。这样,转储就不会引用尚未复制到文件备份中的照片。外部图库应在其实际源位置单独备份;Immich 不负责管理这些图库。
现在处理所有人都会跳过的部分:测试恢复。 恢复必须在一个全新的栈上执行。该栈的 server 不能启动过,并且必须使用与转储兼容的 Postgres 镜像。这正是不能临时决定数据库镜像标签的原因。在使用相同 compose 和 .env 的临时主机上,删除所有旧状态,只启动数据库,然后加载转储:
cd /opt/immich
sudo docker compose down -v
sudo docker compose pull
sudo docker compose create
sudo docker start immich_postgres
sleep 10
gunzip --stdout immich-db-2026-07-15.sql.gz |
sed "s/SELECT pg_catalog.set_config('search_path', '', false);/SELECT pg_catalog.set_config('search_path', 'public, pg_catalog', true);/g" |
sudo docker exec -i immich_postgres psql --dbname=immich --username=postgres --single-transaction --set ON_ERROR_STOP=on
sudo docker compose up -d在 VectorChord 数据库中,sed 对 search_path 的重写不可省略。省略后,恢复会在中途中止。将原始文件放回原位并重新启动栈后,打开 Web UI。如果照片和相册都存在,说明备份有效。如果从未执行过这项测试,您就没有备份,只有希望。
故障模式及您将看到的字符串
ML 容器因 OOM 被终止。 sudo docker compose logs immich-machine-learning 会突然结束,docker compose ps 显示为 Restarting,退出代码为 137。sudo dmesg | grep -i oom 可确认这一点:Out of memory: Killed process ... (python3)。随后,搜索和人脸任务会停滞。原因是模型所需的 RAM 不足。按以下顺序修复:添加 swap(步骤 1);为 VPS 增加 RAM;如果确实无法增加,则在 管理 → 设置 → 机器学习设置 中关闭 智能搜索 和 人脸识别,这样可以保留备份和相册,但会失去按内容搜索功能。从 compose 文件中移除 immich-machine-learning 服务也会产生相同效果。
升级后 Postgres 拒绝启动。 服务器日志会循环输出类似 The database currently has VectorChord 0.5.3 activated, but the Postgres instance only has 0.4.2 available. This most likely means the extension was downgraded. 的行;在较旧的堆栈中,则可能显示 The pgvecto.rs extension is not available in this Postgres instance.。原因是数据库镜像的扩展版本低于数据升级后的版本。这几乎总是因为手动编辑镜像标签,或将较新的转储恢复到较旧的镜像中。修复方法是使用匹配的 Postgres 镜像,使用与数据库匹配的 release 中的 compose 文件,不要降级,并且只将数据恢复到兼容的镜像中。
移动应用无法连接服务器。 输入 URL 后,登录屏幕会显示连接错误或 服务器不可访问。有 3 种原因:您输入了 http://,但代理只提供 https://;您直接连接到后端却省略了端口,因此应用尝试使用 example.com(端口 443),而不是 example.com:2283;或者反向代理没有转发 /api。请输入完整的 https://photos.example.com URL,并先确认它能在手机浏览器中加载。如果浏览器可以访问而应用无法访问,可能是代理删除了路径,或者证书是自签名证书;应用会拒绝不受信任的证书。
导入过程中磁盘空间耗尽。 上传开始失败,缩略图变为空白,日志显示 ENOSPC: no space left on device,或者 Postgres 显示 could not extend file ... No space left on device。df -h 显示 UPLOAD_LOCATION 卷已达到 100%。因此,在导入大型媒体库前应先规划磁盘容量。恢复方法是挂载更大的卷,停止堆栈,将 UPLOAD_LOCATION 移动到该卷,更新 .env,然后重新启动;如果服务商支持,也可以扩展现有磁盘。磁盘空间耗尽可能导致 Postgres 卡住,因此请先释放空间并重启数据库容器,再判断是否发生数据损坏。
FAQ
Immich 需要多少 RAM 和磁盘空间?
Immich 的官方要求是最低 6 GB RAM,建议 8 GB;对于小型图库,配合 swap 使用 4 GB RAM 是实际可行的下限。无论如何都应配置 swap,因为机器学习容器最容易出现资源峰值。磁盘空间应按完整图库大小预留,并额外增加约 10–20% 用于生成缩略图和预览图。数据应存储在本地,绝不要将 Postgres 数据目录放在网络共享上。如果您还在决定运行哪些服务,2026 年适合自行托管的服务指南会将 Immich 的资源占用与其他服务进行比较。
可以在没有 GPU 的情况下运行 Immich 吗?
可以。机器学习容器可以稳定地使用 CPU 运行。GPU 只会加快智能搜索索引,并且在使用正确的镜像变体时加快视频转码。在 CPU 上,大型图库的初始索引可能需要在后台运行数小时,但不会阻塞备份或浏览。如果设备性能太低,完全无法运行机器学习,您可以在管理设置中禁用 Smart Search 和 Facial Recognition,同时保留其他功能。
如何安全升级 Immich?
将 IMMICH_VERSION 固定为具体标签,例如 v3.0.2。每次升级前都要阅读发行说明,并先备份数据库。由于 Postgres 镜像固定在 docker-compose.yml 中,而不是通过 IMMICH_VERSION 固定,因此应从目标发行版重新下载 compose 文件和 example.env,重新应用您的配置值,然后运行 docker compose pull && docker compose up -d。不要让版本在无人管理的情况下自动浮动。Immich 会发布不兼容变更,并且不支持降级。
具体需要备份哪些内容?
需要同时备份两项:immich 数据库的 pg_dump,以及完整的 UPLOAD_LOCATION originals 目录。数据库保存相册、人脸和资源到文件的映射关系;目录保存实际照片。恢复时需要这两项,以及一个带有兼容 vector 扩展的数据库镜像。先执行数据库转储,再复制文件。至少应在测试设备上测试一次恢复;未经测试的备份不能视为有效备份。
如何导入现有的照片目录?
将该目录以只读方式作为额外卷挂载到 immich-server 容器中,例如 - /srv/photos:/mnt/media/photos:ro,然后重新创建容器。接着在 Administration → External Libraries 中创建图库,并添加 container 路径 /mnt/media/photos。Immich 会原地为文件建立索引,不会修改或删除文件。最常见的错误是输入主机路径而不是容器路径,这会导致扫描不到任何内容。