Immich Dev Containers 开发环境指南:用 Docker 容器一键搭建后端、前端与 ML 联调环境
2026/9/7 5:03:03 网站建设 项目流程

Immich Dev Containers 开发环境指南:用 Docker 容器一键搭建后端、前端与 ML 联调环境

【免费下载链接】immichHigh performance self-hosted photo and video management solution.项目地址: https://gitcode.com/GitHub_Trending/im/immich

Dev Containers 让 Immich 的开发者在 Mac、Linux、Windows 或云端环境中获得完全一致、可复现的开发环境。本文基于仓库中的 devcontainers.md 展开,并结合.devcontainer/、docker/docker-compose.dev.yml 与 server/Dockerfile.dev 的实际实现,讲解容器服务的组成、环境变量注入机制、启动脚本的自动初始化流程,以及测试、调试与排障的完整操作路径。读完后你可以独立搭建 Immich 容器化开发环境,理解端口转发、UPLOAD_LOCATION卷挂载与调试端口的底层配置,并在容器内直接运行测试与调试器。

一、前置条件与备选工具链

在开始之前,文档要求确认以下环境已就绪:

  • Docker Desktop(最新版):支持 Mac、Windows(推荐 WSL2 后端)与 Linux;
  • VS Code+ Dev Containers 扩展;
  • Git用于克隆仓库;
  • 内存:至少 8GB(推荐 16GB);
  • 磁盘:至少 20GB 空闲空间。

文档同时列出了除 VS Code 之外的可选工具链,可按团队习惯选择:

类别工具
本地编辑器IntelliJ IDEA、neovim(nvim-remote-containers)、Emacs(lsp-docker)、DevContainer CLI
云端方案GitHub Codespaces、GitPod
可自托管Coder、DevPod(对 devcontainer.json 支持良好,见下文快速上手)

这些工具的共性是都遵循 devcontainer 规范,因此 Immich 仓库中同一份.devcontainer配置在它们之间基本通用。

二、容器服务组成

Immich 的 Dev Container 由一组 Docker Compose 服务构成,进入的"主容器"是immich-server。文档给出的服务表如下:

服务容器名说明端口
Server & Webimmich-server开发模式下同时运行 API 服务与 Web 前端2283 (API)、3000 (Web)、9230 (Workers 调试)、9231 (API 调试)
数据库databasePostgreSQL5432
缓存redisValkey 缓存服务6379
机器学习immich-machine-learningImmich ML 模型推理服务3003

仓库中的.devcontainer/devcontainer.json证实了这一结构:runServices声明为immich-initimmich-serverredisdatabaseimmich-machine-learning五个服务,且 Compose 文件是两层叠加的——基础层 docker/docker-compose.dev.yml 加覆盖层.devcontainer/server/container-compose-overrides.yml(见该文件第 11-14 行的dockerComposeFile字段)。

从基础 Compose 文件可以看到各服务的真实形态:

  • immich-init(第 36-59 行):一个"初始化门卫"容器,命令是mise install(安装各语言工具链),完成后touch /tmp/init-complete并挂起;其余服务通过depends_on: condition: service_healthy等它健康检查通过后才启动,健康检查就是探测/tmp/init-complete文件是否存在。
  • database(第 161-177 行):使用ghcr.io/immich-app/postgres:14-vectorchord...-pgvectors...定制镜像(PostgreSQL 14 + vectorchord + pgvectors 扩展,用于向量检索),shm_size: 128mb,初始化参数带--data-checksums
  • redis(第 155-159 行):实际是 Valkey 9 镜像,健康检查为redis-cli ping
  • immich-machine-learning(第 131-153 行):构建自 machine-learning/Dockerfile,默认DEVICE=cpu,把 Python 源码目录挂载进容器便于热改。

三、快速上手

3.1 克隆仓库

克隆 Immich 仓库后进入目录(克隆地址以仓库页面的 Clone 地址为准):

git clone <immich 仓库克隆地址> cd immich

3.2 配置环境变量(先于启动容器)

关键机制:Immich 的 Dev Container 从你的 shell 环境读取环境变量,而不是从.env文件。文档明确强调:本地运行时若希望使用自定义的数据/照片存储目录,必须在启动 Dev Container之前在 shell 环境中设置UPLOAD_LOCATION

# 仅对当前会话临时生效 export UPLOAD_LOCATION=/opt/dev_upload_folder # 或写入 shell 配置以实现持久化(~/.bashrc、~/.zshrc 等) echo 'export UPLOAD_LOCATION=/opt/dev_upload_folder' >> ~/.bashrc source ~/.bashrc

3.3 启动方式

文档提示了一个重要限制:由于 Immich 开发深度依赖其定制的 base 镜像,无法使用 VS Code 的 "Clone Repository in a Container Volume" 命令,必须先在宿主机克隆仓库再重开进容器。三种启动方式:

方式一:VS Code 命令面板

  1. 在 VS Code 中打开已克隆的仓库;
  2. F1(或Ctrl/Cmd+Shift+P)打开命令面板;
  3. 执行 "Dev Containers: Rebuild and Reopen in Container";
  4. 选择 "Immich - Backend, Frontend and ML";
  5. 等待构建完成(首次运行可能需要数分钟)。

方式二:VS Code 快捷弹窗打开仓库后点击弹出的 "Reopen in Container"。

方式三:命令行

# 使用 DevContainer CLI devcontainer up --workspace-folder .

方式四:DevPod + Docker(文档中的快速上手小节)

# Step 1: 克隆仓库 git clone <immich 仓库克隆地址> cd immich # Step 2: 配置 DevPod provider(如尚未配置) devpod provider add docker devpod provider use docker # Step 3: 先手动构建 'immich-server-dev' 镜像 docker build -f server/Dockerfile.dev -t immich-server-dev . # Step 4: 启动 devcontainer devpod up .

注意 Step 3 是必要的:DevContainer 的service指向immich-server,其镜像immich-server-dev:latest由 server/Dockerfile.dev 的dev-container-server目标构建而来。

四、环境变量机制:remoteEnv${localEnv:...}语法

与基于 Docker Compose +.env的传统开发者设置不同,Dev Container 通过 devcontainer 规范把宿主机 shell 变量"搬运"进容器。.devcontainer/devcontainer.json中的实际配置为:

"remoteEnv": { "UPLOAD_LOCATION": "${localEnv:UPLOAD_LOCATION:./library}", "DB_PASSWORD": "${localEnv:DB_PASSWORD:postgres}", "DB_USERNAME": "${localEnv:DB_USERNAME:postgres}", "DB_DATABASE_NAME": "${localEnv:DB_DATABASE_NAME:immich}" }

其中${localEnv:VARIABLE:default}的含义是"读取本地 shell 中的VARIABLE,未设置时回退到默认值"。各变量的默认值与说明:

变量默认值说明
UPLOAD_LOCATION./library上传文件与数据库数据的存放位置(可设为绝对路径)
DB_PASSWORDpostgresPostgreSQL 密码(建议仅使用A-Za-z0-9字符)
DB_USERNAMEpostgresPostgreSQL 用户名
DB_DATABASE_NAMEimmich数据库名

4.1UPLOAD_LOCATION的路径解析(源码级印证)

文档描述的默认解析结果为<immich-root>/docker/Library。从仓库当前源码看,实际的覆盖层.devcontainer/server/container-compose-overrides.yml采用了比文档更完善的双模式设计:

# immich-server 的挂载(第 16 行) - ${UPLOAD_LOCATION:-upload-devcontainer-volume}${UPLOAD_LOCATION:+/photos}:/data # database 的挂载(第 33 行) - ${UPLOAD_LOCATION:-postgres-devcontainer-volume}${UPLOAD_LOCATION:+/postgres}:/var/lib/postgresql/data

这段 Compose 表达式可以拆解为两个分支:

  • 未设置UPLOAD_LOCATION:挂载名为upload-devcontainer-volume/postgres-devcontainer-volume命名 Docker 卷(文件末尾volumes:段落声明了它们)。容器照常工作,只是数据落在 Docker 管理的卷里,适合云端等无需持久化到宿主目录的场景——这正是文档所说"在云环境中无需预配置也能运行"的实现基础;
  • 设置了UPLOAD_LOCATION:挂载宿主机的${UPLOAD_LOCATION}/photos到容器/data${UPLOAD_LOCATION}/postgres/var/lib/postgresql/data,照片与数据库数据均可直接在宿主机上访问和备份。

因此,如果你希望"数据落在自己指定的宿主目录",就必须按第 3.2 节所述在 shell 中导出UPLOAD_LOCATION;不设置也能启动,但数据会进入 Docker 命名卷。

数据库变量则通过覆盖层注入(container-compose-overrides.yml第 26-31 行):POSTGRES_PASSWORD/POSTGRES_USER/POSTGRES_DB分别映射${DB_PASSWORD-postgres}${DB_USERNAME-postgres}${DB_DATABASE_NAME-immich},并显式设置POSTGRES_HOST_AUTH_METHOD: md5

五、镜像构建与自动启动流程

5.1 开发镜像:server/Dockerfile.dev

Dev Container 的容器基于该 Dockerfile 构建,关键目标:

  • dev(第 2-26 行):基于 Immich 官方定制基础镜像ghcr.io/immich-app/base-server-dev,预装 mise 工具管理器;把 pnpm store、node-gyp 与 mise 数据目录全部指向/buildcache,该目录与 Compose 中的build_cache卷对应,跨容器复用依赖缓存以加速重复安装;
  • dev-container-server(第 28-40 行):后端/前端 Dev Container 使用的最终目标,安装 OpenJDK 21、vim 等工具,把.devcontainer/server/*.sh脚本复制进/immich-devcontainer/,工作目录设为/workspaces/immich(符号链接指向/usr/src/app);
  • dev-container-mobile(第 42-81 行):在 server 目标之上加装指定版本的 Flutter SDK 与 dcm 构建缓存工具,供 .devcontainer/mobile/devcontainer.json 定义的移动端 Dev Container 使用(remoteUsernode,并预装 Dart/Flutter/dcm 扩展)。

5.2 VS Code Tasks 驱动的常驻服务

.devcontainer/devcontainer.json通过customizations.vscode.settings.tasks注入了三个任务,其中两个标记了runOptions.runOn: "folderOpen",即打开容器时自动启动,并且都是isBackground常驻任务:

  1. Immich API Server (Nest)→ 执行/immich-devcontainer/container-start-backend.sh
  2. Immich Web Server (Vite)→ 执行/immich-devcontainer/container-start-frontend.sh
  3. Build Immich CLIpnpm --filter @immich/cli build:dev(按需手动运行)。

对照文档"自动设置"小节的描述,从源码看当前仓库的实际初始化分工是:依赖安装与启动全部收敛在这两个启动脚本里(文档提到的container-server-post-create.sh脚本在当前仓库中已不存在,其职责被下述脚本与immich-init容器取代)。

5.3 启动脚本的实现细节

container-common.sh 提供公共逻辑:IMMICH_WORKSPACE=/usr/src/app、API 端口IMMICH_PORT(默认 2283)、Web 端口DEV_PORT(默认 3000),并把所有命令输出带时间戳写入$HOME/immich-devcontainer.log便于事后排障。

container-start-backend.sh 的核心循环:

run_cmd pnpm --filter immich install # 安装后端依赖 cd "${IMMICH_WORKSPACE}/server" while true; do run_cmd pnpm --filter immich exec nest start --debug "0.0.0.0:9230" --watch # 崩溃后 3 秒自动重启 sleep 3 done

即 Nest API 以--watch热重载模式启动,进程异常退出会被自动拉起重启。

container-start-frontend.sh 则体现了一条有依赖顺序的启动链:先pnpm --filter @immich/sdk install/build(TypeScript SDK)、@immich/plugin-sdk install/build(插件 SDK),再pnpm --filter immich-web install;随后轮询等待 API 就绪——反复请求http://127.0.0.1:2283/api/server/config直到成功,最后以vite dev --host 0.0.0.0 --port 3000循环拉起 Web 前端。这也解释了为什么 Web 任务不担心与 API 竞争启动顺序。

5.4 端口转发

devcontainer.jsonforwardPorts: [3000, 9231, 9230, 2283]portsAttributes标注了各端口语义(第 91-110 行):3000 为前端 HTTP(配置了onAutoForward: "openBrowserOnce",首次转发时自动打开浏览器),2283 为 API,9231 为 API 调试,9230 为 Workers 调试。

六、开发工作流与服务访问

6.1 运行中服务的访问地址

服务地址说明
Web UIhttp://localhost:3000主界面;其/api路径反向代理到后端
APIhttp://localhost:2283REST API(通常不直接访问)
PostgreSQLlocalhost:5432默认用户postgres

6.2 代码变更的反馈方式

  • 服务端代码server/):nest start --watch触发自动重编译;进程崩溃由启动脚本 3 秒后自动重启;
  • Web 代码web/):Vite 提供热模块替换(HMR);
  • 数据库迁移:运行mise //server:sql同步 schema;
  • API 变更后:用mise //:open-api重新生成 OpenAPI 规范与 SDK。

文档特别指出:Dev Container 方案取代了传统设置中的mise dev命令——所有服务在打开容器时自动启动。

6.3 连接移动 App 联调

把手机/模拟器连到 Dev Container:

  1. 查宿主机局域网 IP:macOS 用ipconfig getifaddr en0,Linux 用hostname -I,Windows(WSL2) 用ip addr show eth0
  2. 在移动 App 中配置服务器地址http://YOUR_IP:2283/api(文档中另一处写作http://YOUR_IP:3000/api,两者最终都可达后端:3000 由 Web 层代理/api,2283 直连 Nest API;实际防火墙需放行的端口与所用地址一致);
  3. 移动端更完整的开发流程(Flutter 环境、模拟器运行、移动端调试)参见 setup.md;仓库还单独提供了移动端专用 Dev Container 配置 .devcontainer/mobile/devcontainer.json,其镜像目标dev-container-mobile已内置 Flutter SDK 与 dcm。

七、测试与常用命令

Dev Container 内的终端可直接使用 mise 任务(容器内已预装 mise 与工具链):

# Server mise //server:test # 单元测试 mise //server:test-medium # 中等/集成测试 # Web mise //web:test # 单元测试 # E2E mise //e2e:test # API 测试 mise //e2e:test-web # Web UI 测试(Playwright) # 对某组件执行完整检查清单 mise //server:checklist mise //web:checklist # API 生成 mise //:open-api # 生成 OpenAPI 规范 mise //:open-api-typescript # 生成 TypeScript SDK mise //:open-api-dart # 生成 Dart SDK # 数据库 mise //server:sql # 同步数据库 schema

对应的测试代码可在 server/test/medium/(中型集成测试)、e2e/src/specs/(API 与 Web 的端到端测试)中找到,与上述命令一一对应。

八、调试(Debugging)

Dev Container 预配置了 Node.js 远程调试端口,与devcontainer.jsonportsAttributes的标注一致:

  1. API 服务调试:在 VS Code 中设置断点,按F5打开 "Run and Debug",选择 "Attach to Server" 配置;调试端口9231。对照 container-start-backend.sh,Nest 以--debug "0.0.0.0:9230"参数启动,端口参数在 Compose 中同时映射了 9230 与 9231 两个调试入口;
  2. Workers 调试:使用 "Attach to Workers" 配置,调试端口9230
  3. Web 调试:使用浏览器 DevTools;VS Code 也支持对 Chrome/Edge 扩展进行调试。

九、Git 认证与提交签名

SSH 密钥转发:在宿主机启动 ssh-agent 并加载密钥:

eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_rsa # 或你的密钥路径

VS Code 会自动把宿主机 SSH agent 转发进容器,容器内的git push/fetch即可复用你的 GitHub 凭据。

提交签名(Commit Signing):如需在容器内用 SSH 密钥签名提交,按 GitHub 官方文档配置user.signingkeycommit.gpgsign即可;签名相关配置同样来自你 shell 中的 git 全局配置或GIT_CONFIG_*环境变量。

十、排障指南

文档整理了五类常见问题,结合仓库实现给出验证路径:

权限错误(EACCES)

后端 Dev Container 以root身份进入(devcontainer.jsonremoteUser: "root"),而工作区挂载卷的属主可能不同,导致node用户写文件失败。解决:确认宿主目录属主,或执行 "Dev Containers: Rebuild Container" 重建容器;检查日志文件$HOME/immich-devcontainer.log(由container-common.sh写入)定位具体失败命令。

容器无法启动
  1. docker ps确认 Docker 在运行;
  2. docker system prune -a清理资源;
  3. 检查磁盘空间(至少 20GB);
  4. 检查 Docker Desktop 资源上限(内存/CPU)。首次构建immich-server-dev镜像体积较大,资源不足时最容易卡死在构建阶段。
端口被占用("Port 3000/2283 is already in use")
  1. lsof -i :3000(macOS/Linux)查冲突进程;
  2. 停掉冲突服务或修改端口映射(同时改docker-compose.dev.ymlportsdevcontainer.jsonforwardPorts);
  3. 重启 Docker Desktop。
UPLOAD_LOCATION未设置

容器可以启动(数据落入命名卷),但若报缺失/写入错误:

  1. export UPLOAD_LOCATION=./Library(或绝对路径);
  2. 写入 shell 配置持久化;
  3. 重启终端与 VS Code,然后 Rebuild 容器。
数据库连接失败
  1. docker ps确认immich_postgres在运行;
  2. 查看 "Dev Containers: Show Container Log";
  3. 核对DB_PASSWORD/DB_USERNAME/DB_DATABASE_NAMEPOSTGRES_*注入值一致(见container-compose-overrides.yml第 26-31 行)。

求助路径:View → Output → "Dev Containers" 查看日志;"Rebuild Container Without Cache" 强制无缓存重建;仍无法解决可在 Immich 官方 Discord 的#contributing频道提问。

十一、进阶配置

11.1 自定义 VS Code 扩展

在 .devcontainer/devcontainer.json 的customizations.vscode.extensions数组中追加扩展 ID。当前仓库已预装 ESLint、Prettier、Svelte、Playwright、Docker 等 12 个扩展,可直接照葫芦画瓢。

11.2 添加额外服务

若要在 Dev Container 中新增服务(例如 Redis 可视化工具),需要同时改两处:

  1. docker/docker-compose.dev.yml —— 添加服务定义;
  2. .devcontainer/server/container-compose-overrides.yml—— 按需添加覆盖(例如重置env_file、调整volumes),并把服务名加入devcontainer.jsonrunServices

11.3 资源限制

macOS/Windows 在 Docker Desktop → Settings → Resources 调整;Linux 修改 Docker daemon 配置。文档给出的最低建议:4 核 CPU、8GB 内存、20GB 磁盘。

十二、延伸阅读与关键文件索引

  • 架构总览:architecture.mdx
  • 数据库迁移:database-migrations.md
  • 传统 Compose 开发环境:setup.md
  • 开发者排障:troubleshooting.md

本文涉及的关键仓库文件:

文件作用
docs/docs/developer/devcontainers.md本文依据的官方 Dev Container 指南
.devcontainer/devcontainer.json主 Dev Container 配置(服务、端口、remoteEnv、tasks)
.devcontainer/server/container-compose-overrides.yml覆盖层:挂载解析与 Postgres 变量注入
docker/docker-compose.dev.yml开发 Compose 基础定义(init/server/web/ML/redis/db)
server/Dockerfile.dev开发镜像:dev / dev-container-server / dev-container-mobile 三目标
.devcontainer/server/container-start-backend.shAPI 服务安装与常驻启动脚本
.devcontainer/server/container-start-frontend.shSDK 构建、API 就绪等待与 Vite 启动脚本
.devcontainer/mobile/devcontainer.json移动端 Dev Container 配置

适用前提提示:本文描述基于当前仓库快照中的.devcontainer与 Compose 配置;Dev Container 方案要求 Docker 可用且能拉取 Immich 定制基础镜像(PostgreSQL 定制镜像、ML 镜像构建较重),首次构建耗时明显长于普通项目,建议按前置条件一节预留内存与磁盘。

【免费下载链接】immichHigh performance self-hosted photo and video management solution.项目地址: https://gitcode.com/GitHub_Trending/im/immich

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询