使用 Docker Compose 部署 Immich 并配置域名与 HTTPS

本文记录一次在 Linux 服务器上部署 Immich 的过程:使用 Docker Compose 运行 Immich,把照片与数据库数据持久化到 /storage/photo_backup,再通过 Cloudflare DNS、Nginx 反向代理和 Let’s Encrypt 证书对外提供 HTTPS 访问。

安全说明:本文已移除所有敏感信息,例如 Cloudflare API Key、数据库密码、Token、服务器后台令牌等。示例里的域名、路径和端口可按需替换。

目标架构

  • 应用:Immich
  • 运行方式:Docker Compose
  • 对外域名:photo.example.com
  • 本机监听:127.0.0.1:2283
  • 反向代理:Nginx / Tengine
  • HTTPS:Let’s Encrypt + Certbot
  • 数据目录:/storage/photo_backup

目录规划:

1
2
3
4
/storage/photo_backup/
├── library # Immich 上传与媒体文件
├── postgres # PostgreSQL 数据
└── model-cache # 机器学习模型缓存

1. 创建数据目录

1
2
3
mkdir -p /storage/photo_backup/library \
/storage/photo_backup/postgres \
/storage/photo_backup/model-cache

2. 准备 Docker Compose

创建项目目录:

1
2
mkdir -p /opt/immich
cd /opt/immich

创建 .env

1
2
3
4
5
6
7
UPLOAD_LOCATION=/storage/photo_backup/library
DB_DATA_LOCATION=/storage/photo_backup/postgres
IMMICH_VERSION=release
DB_PASSWORD=请替换为强随机密码
DB_USERNAME=postgres
DB_DATABASE_NAME=immich
TZ=Etc/UTC

创建 docker-compose.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
name: immich

services:
immich-server:
container_name: immich_server
image: ghcr.io/immich-app/immich-server:${IMMICH_VERSION:-release}
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- /etc/localtime:/etc/localtime:ro
env_file:
- .env
ports:
- "127.0.0.1:2283:2283"
depends_on:
- redis
- database
restart: always
healthcheck:
disable: false

immich-machine-learning:
container_name: immich_machine_learning
image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release}
volumes:
- ${UPLOAD_LOCATION}:/usr/src/app/upload
- ${DB_DATA_LOCATION}/../model-cache:/cache
env_file:
- .env
restart: always
healthcheck:
disable: false

redis:
container_name: immich_redis
image: docker.io/valkey/valkey:8-bookworm
healthcheck:
test: redis-cli ping || exit 1
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_INIT_ARGS: "--data-checksums"
volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
restart: always

说明:Immich 官方示例有时会固定镜像 digest。如果遇到 digest 拉取失败,可以临时改用同版本 tag,但生产环境建议定期确认官方最新推荐 compose 文件。

校验配置:

1
docker compose config --quiet

3. 配置 DNS

在 Cloudflare DNS 中添加 A 记录:

1
2
3
4
5
类型:A
名称:photo
内容:服务器公网 IPv4
代理状态:DNS only
TTL:Auto 或 120

如果要使用 HTTP-01 方式申请 Let’s Encrypt 证书,建议先关闭 Cloudflare 代理,确认公网能直连服务器的 80 端口。

4. Nginx HTTP 临时配置

先配置 HTTP,用于 Let’s Encrypt 的验证路径:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server {
listen 80;
server_name photo.example.com;

location ^~ /.well-known/acme-challenge/ {
root /www/wwwroot/photo.example.com;
default_type text/plain;
}

location / {
proxy_pass http://127.0.0.1:2283;
proxy_http_version 1.1;
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 600s;
proxy_send_timeout 600s;
client_max_body_size 0;
}
}

加载前检查:

1
2
nginx -t
nginx -s reload

5. 申请 SSL 证书

安装 Certbot 后使用 webroot 模式:

1
2
3
4
5
6
7
8
certbot certonly \
--webroot \
-w /www/wwwroot/photo.example.com \
-d photo.example.com \
--email admin@example.com \
--agree-tos \
--no-eff-email \
--non-interactive

证书签发后路径通常为:

1
2
/etc/letsencrypt/live/photo.example.com/fullchain.pem
/etc/letsencrypt/live/photo.example.com/privkey.pem

6. 启用 HTTPS 反向代理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
server {
listen 80;
server_name photo.example.com;

location ^~ /.well-known/acme-challenge/ {
root /www/wwwroot/photo.example.com;
default_type text/plain;
}

location / {
return 301 https://$host$request_uri;
}
}

server {
listen 443 ssl http2;
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;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;

client_max_body_size 0;

location / {
proxy_pass http://127.0.0.1:2283;
proxy_http_version 1.1;
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 https;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 600s;
proxy_send_timeout 600s;
proxy_buffering off;
}
}

重新加载:

1
2
nginx -t
nginx -s reload

7. 启动 Immich

1
2
3
cd /opt/immich
docker compose pull
docker compose up -d

查看状态:

1
2
docker compose ps
docker compose logs -f immich-server

immich_serverimmich_postgresimmich_redis 变为 healthy,且日志显示 Immich Server 正常监听后,即可访问:

1
https://photo.example.com/

8. 证书续期后自动重载 Nginx

Certbot 会创建自动续期任务。为了让证书更新后 Nginx 自动加载新证书,可以添加 deploy hook:

1
2
3
4
5
6
mkdir -p /etc/letsencrypt/renewal-hooks/deploy
cat > /etc/letsencrypt/renewal-hooks/deploy/nginx-reload.sh <<'SCRIPT'
#!/bin/sh
nginx -t && nginx -s reload
SCRIPT
chmod 755 /etc/letsencrypt/renewal-hooks/deploy/nginx-reload.sh

常用维护命令

1
2
3
4
5
6
7
8
9
10
11
cd /opt/immich

# 查看容器状态
docker compose ps

# 查看日志
docker compose logs -f immich-server

# 更新 Immich
docker compose pull
docker compose up -d

总结

这套部署方式的重点是:

  1. Immich 只绑定到本机地址,减少暴露面;
  2. 所有公网访问统一走 Nginx HTTPS;
  3. 数据目录明确放在 /storage/photo_backup,便于备份;
  4. DNS、证书、反代、容器状态分别验证,减少排错成本。

部署完成后,首次访问 Web UI 创建管理员账号即可开始使用。