用 Docker 自建私有云相册:Immich 完整部署指南(2026 版)

admin 开源软件 2026-06-19 17 0

手机里存了三年的照片,最后都去哪儿了?

大多数人的答案是云盘。但云盘这条路,走到后面总会撞上三堵墙:容量要续费、会员涨价、还有就是——你永远不确定那些私密照片被拿去做了什么。去年某网盘"AI 审核误删用户私人照片"的新闻闹了好几天,评论区一片哀嚎,删了就是删了,连个回滚按钮都没有。

所以这两年,"把照片搬回自己家"成了一股不小的潮流。而在这条路上,目前公认做得最完整的一套自建相册方案,叫 Immich。它不是网盘的替代品,而是冲着"自建版 Google Photos"去的:一样的时间线、一样的人脸聚类、一样的按内容搜索,唯一不同的是——数据躺在你自己的硬盘里,服务器关掉就谁也拿不走。

一、它到底能干什么

先别急着敲命令,先看清楚它能给你什么,值不值得你折腾一晚上。

能力实际体验
手机相册自动备份iOS / Android 官方客户端,连上 Wi-Fi 后台自动传,支持"只备份新照片"和按相册选择
时间线浏览按拍摄时间倒序排列,滚动加载,和手机相册几乎一样,10 万张也不卡
人脸识别自动聚类出"这是谁",可以手动命名,之后按人筛选
语义搜索输入"海边 日落""猫"这类自然语言就能搜到图,靠 CLIP 模型,不需要手动打标签
视频转码把 iPhone 的 HEVC 视频转成浏览器能直接播的格式,支持显卡硬件加速
多用户 / 共享可以给家人各开一个账号,互相隔离,也能建共享相册
外部库不导入也行,直接挂载已有的照片目录,只读索引,原文件不动
RAW 与实况照片CR2/NEF/ARW 等常见 RAW 格式可预览,iPhone 实况照片按视频+静态双份处理
回收站删除先进回收站,30 天后才真删,手滑也有救

最新版本是 v3.3.5(2026 年 10 月),采用 AGPL-3.0 协议开源,服务端是 TypeScript,客户端是 Flutter,社区里已经有超过 11 万星标——这个量级说明一件事:它不是玩具。

二、部署前先想清楚三件事

1. 硬件

  • 内存:4GB 是底线,8GB 会比较舒服。机器学习容器在跑人脸识别时很吃内存,2GB 的小鸡基本会 OOM。
  • 硬盘:照片本体放机械盘没问题,但数据库一定要放 SSD。数据库里存的是缩略图的索引和向量,随机读写极多,放机械盘会让整个界面卡成 PPT。
  • CPU:没有显卡也能跑。有人脸识别需求的话,第一次全量扫描会比较慢,十万张照片大概需要几个小时,之后就是增量的。
  • 带宽:这是最容易被忽略的。手机在外面备份时,上传速度取决于你家宽带的上行。100M 下行 / 20M 上行的家庭宽带,传 2GB 视频大概要十几分钟。

2. 系统

Ubuntu 22.04 / 24.04、Debian 12 都行,其他发行版只要 Docker 版本够新也可以。下面以 Ubuntu 24.04 为例。

3. 域名与端口

手机客户端必须通过 HTTPS 访问,否则 iOS 会直接拒绝后台备份。所以你需要一个域名,并且能给它签发证书。纯 IP + HTTP 的玩法在手机上走不通,这一点先记住。

三、安装 Docker

apt update
apt install -y docker.io docker-compose-plugin
systemctl enable --now docker

docker --version
docker compose version

如果 `docker compose version` 报错,说明装的是旧版 compose,需要单独装 v2 插件。国内机器拉取镜像慢的话,配置一下镜像加速器,否则后面几个 GB 的镜像能让你等到天亮。

四、目录规划

建议单独划一个目录出来,把"程序"和"数据"分开。很多人图省事直接在家目录跑 compose,结果重装系统时把照片一起格了。

mkdir -p /opt/immich && cd /opt/immich
mkdir -p /data/immich/library /data/immich/postgres

这里的 /data/immich 建议挂一块独立的大盘。假如你打算存 10 年照片,按每年 100GB 算,准备 1TB 起步不会错。

五、写配置文件

先进目录,创建 .env:

cd /opt/immich
cat > .env <<'EOF'
# 照片实际存放位置
UPLOAD_LOCATION=/data/immich/library

# 数据库数据位置(务必放在 SSD 上)
DB_DATA_LOCATION=/data/immich/postgres

# 时区,影响时间线分组和日志时间
TZ=Asia/Shanghai

# 版本号,后续升级只需改这里
IMMICH_VERSION=v3

# 数据库密码,只能使用大小写字母和数字,不要用特殊符号
DB_PASSWORD=ChangeMeToSomethingLong2026

DB_USERNAME=postgres
DB_DATABASE_NAME=immich
EOF

那个密码别偷懒,长度至少 20 位。它只在容器内部使用,不需要你记住,但泄露了就等于数据库裸奔。

然后是 docker-compose.yml:

cat > docker-compose.yml <<'EOF'
name: immich

services:
  immich-server:
    container_name: immich_server
    image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
    volumes:
      - ${UPLOAD_LOCATION}:/data
      - /etc/localtime:/etc/localtime:ro
    env_file:
      - .env
    ports:
      - '2283:2283'
    depends_on:
      - redis
      - database
    restart: always

  immich-machine-learning:
    container_name: immich_machine_learning
    image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
    volumes:
      - model-cache:/cache
    env_file:
      - .env
    restart: always

  redis:
    container_name: immich_redis
    image: docker.io/valkey/valkey:9
    restart: always

  database:
    container_name: immich_postgres
    image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0
    environment:
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_USER: ${DB_USERNAME}
      POSTGRES_DB: ${DB_DATABASE_NAME}
      POSTGRES_INITDB_ARGS: '--data-checksums'
    volumes:
      - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
    restart: always

volumes:
  model-cache:
EOF

四个容器,各司其职:

  • immich-server:主程序,Web 界面和 API 都在这里,对外暴露 2283 端口。
  • immich-machine-learning:跑人脸识别和语义搜索模型的,最吃内存的一个。
  • redis:任务队列。上传后生成缩略图、转码、识别,都是异步任务,靠它调度。
  • database:PostgreSQL,注意这里用的是带 VectorChord 和 pgvector 扩展的专用镜像,普通 postgres 镜像跑不起来,别自作聪明换掉。

六、启动

docker compose up -d

# 看日志,等 immich_server 打出 "Immich Server is listening"
docker compose logs -f immich-server

第一次启动要下载镜像,加起来两三个 GB,慢是正常的。等四个容器都变成 Up 状态:

docker compose ps

然后浏览器打开 http://服务器IP:2283,会看到注册页面。第一个注册的账号自动成为管理员。

注册完先别急着传照片,进"管理"里把这两项配一下:

  • 外部域名:填上你最终的 HTTPS 域名,生成分享链接时会用到。
  • 机器学习:确认开关是打开的,否则人脸和语义搜索都不会工作。

七、上 HTTPS(这一步别省)

手机客户端强制要求 HTTPS,所以必须要有反向代理。用 Nginx 的话,配置大概长这样:

server {
    listen 443 ssl;
    http2 on;
    server_name photo.example.com;

    ssl_certificate     /etc/letsencrypt/live/photo.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/photo.example.com/privkey.pem;

    # 关键:视频上传动辄几个 G,默认 1M 会直接 413
    client_max_body_size 0;

    location / {
        proxy_pass http://127.0.0.1:2283;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # 关键:websocket,进度条和实时通知靠它
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # 关键:不要缓冲请求体,否则大文件上传会先落盘再转发,白占一倍空间
        proxy_request_buffering off;
        proxy_buffering off;
        proxy_read_timeout 3600s;
    }
}

证书用 Let's Encrypt 免费签就行,自动续期脚本配好,别三个月后忘了续导致手机备份集体停摆——这个坑我见过不止一次。

八、手机端接入

iOS 在 App Store 搜 Immich,Android 可以装官方 APK 或从 F-Droid 获取。装好后:

  1. 服务器地址填 https://photo.example.com,注意别漏协议头。
  2. 登录你在网页上注册的账号。
  3. 进入"备份"设置,打开"前台备份"和"后台备份"。
  4. 选择要备份的相册——建议只选"相机胶卷",别把微信缓存的图片也一起备份进去,不然几万张垃圾图会把时间线淹没。
  5. 打开"仅在使用 Wi-Fi 时备份",除非你的流量不要钱。

第一次备份是最难熬的,几万张照片可能要跑一整夜。建议插上充电器,让手机保持亮屏或者干脆放一晚上。后台任务被系统杀掉是正常现象,重新打开 App 会自动续传。

九、日常运维

升级

作者更新很勤,几乎每周都有版本。升级前务必先看更新日志有没有数据库迁移,然后:

cd /opt/immich
docker compose pull
docker compose up -d

跨大版本(比如 v2 到 v3)时,官方通常会要求先升到某个中间版本,不能一步到位,这点别犟。

备份

照片文件本身是直接躺在磁盘上的,按 年月/日期 分目录存放,随便用 rsync 同步走就行。真正麻烦的是数据库,它记录着人脸、相册、标签、分享链接这些元数据。

# 停库再备份,热备份可能拿到不一致的数据
cd /opt/immich
docker compose stop database
docker run --rm -v /data/immich/postgres:/var/lib/postgresql/data \
  -v /backup:/backup alpine tar czf /backup/pg-$(date +%F).tar.gz -C /var/lib/postgresql/data .
docker compose start database

数据库通常只有几百 MB 到几个 GB,建议每周一次,和照片目录一起同步到另一台机器或者离线硬盘上。不要只备份照片不备份数据库——那样恢复出来会是一堆没有名字、没有人脸、没有相册归类的裸图。

恢复

反过来,把 tar 包解回 /data/immich/postgres,确保目录属主是 postgres,再启动即可。版本必须和备份时一致,跨版本恢复会失败。

十、性能调优

显卡转码

有独立显卡(N 卡)或者带核显的 Intel CPU,可以开硬件转码,转码速度能快 5 到 10 倍。做法是在 compose 里给 server 挂载设备并加一段 extends,常见选项是 nvenc(N 卡)、quicksync(Intel 核显)、vaapi(通用 Linux)和 rkmpp(瑞芯微 ARM 板子)。

需要注意的是,Intel 核显直通要装 intel-media-va-driver,并且容器里要能看到 /dev/dri/renderD128,看不到就是没直通成功。

机器学习加速

同理,机器学习容器也有 cuda、rocm、openvino 等变体。如果你有显卡,换对应 tag 后,十万张照片的人脸扫描能从几小时压到几十分钟。

缩略图缓存

缩略图存放在上传目录下的 thumbs 子目录里,数量会比原图多得多(一张图可能生成 3 种尺寸)。所以实际占用空间通常是原图的 1.2 到 1.5 倍,规划容量时记得算进去。

十一、几个我踩过的坑

  1. 上传到一半报 413:Nginx 的 client_max_body_size 没改。设成 0 表示不限制。
  2. 手机备份一直"等待中":九成是反向代理没开 websocket,进度推送收不到。
  3. 时间线全部显示成同一天:容器时区没设,或者照片本身没有 EXIF 时间。可以在后台开"根据文件名推断日期"。
  4. 人脸识别一直转圈:机器学习容器内存不够被 OOM 杀了,docker ps -a 看退出码 137 就是它。
  5. 数据库放机械盘后界面卡死:前面说过,这是硬伤,没法优化,只能换盘。
  6. 升级后打不开:多半是跨版本升级没走中间版本,数据库迁移卡住了。这种情况只能回滚到旧镜像,再按官方路径一步步升。
  7. 外部库照片重复:既导入了又挂了外部库,同一张图会出现两次。二选一。
  8. 磁盘满了导致数据库崩溃:Postgres 在磁盘写满时会直接拒绝服务,甚至损坏数据页。建议挂个磁盘监控,超过 85% 就报警。

十二、和商业方案比,值不值

对比项自建 Immich商业云相册
成本服务器年费 + 电费,一次性买盘后边际成本接近 0按容量订阅,越用越贵
隐私数据在自家硬盘,服务商看不到依赖服务商政策,存在审核和误删风险
稳定性硬盘坏了就是坏了,取决于你有没有备份多副本容灾,基本不会丢
上手难度要会敲命令,要懂点 Docker注册即用
维护成本升级、备份、监控都得自己来零

说句实在话:自建不是给所有人准备的。如果你一年拍不到两千张照片,商业云盘那点钱花得值。但如果你有几十万张照片、几个 T 的视频、又对隐私有要求,那这套方案的天花板明显更高——尤其是它支持"外部库",可以直接挂载你已有的照片目录,不导入、不改动原文件,只做索引,试错成本几乎为零。

先挂个外部库试试水,觉得顺手了再考虑全量导入。这是最稳妥的姿势。

至于硬件怎么选、备份怎么做、要不要上显卡——如果你也在折腾自建服务,本站后面还会陆续写几篇同样方向的实战记录,包括文件同步、内网穿透和证书自动化,都是从零踩坑踩出来的东西。