lobehub/docs/self-hosting/server-database/docker-compose.zh-CN.mdx
2024-10-13 12:09:16 +08:00

553 lines
21 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 通过 Docker Compose 部署 LobeChat
description: 学习如何使用 Docker Compose 部署 LobeChat 服务,包括各种服务的配置教程。
tags:
- Docker Compose
- LobeChat
- Docker 容器
- 部署指引
---
# 使用 Docker Compose 部署 LobeChat 服务端数据库版本
<div style={{display:"flex", gap: 4}}>
[![][docker-release-shield]][docker-release-link]
[![][docker-size-shield]][docker-size-link]
[![][docker-pulls-shield]][docker-pulls-link]
</div>
<Callout type="info">
本文已经假定你了解了 LobeChat 服务端数据库版本(下简称 DB
版)的部署基本原理和流程,因此只包含核心环境变量配置的内容。如果你还不了解 LobeChat DB
版的部署原理,请先查阅 [使用服务端数据库部署](/zh/docs/self-hosting/server-database) 。
</Callout>
<Callout type="warning">
由于无法使用 Docker 环境变量暴露 `NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY`,使用 Docker / Docker Compose
部署 LobeChat 时,你不能使用 Clerk 作为登录鉴权服务。
如果你确实需要 Clerk 作为登录鉴权服务,你可以考虑使用 Vercel 部署或者自行构建镜像。
</Callout>
一般来讲,想要完整的运行 LobeChat 数据库版本,你需要至少拥有如下四个服务
- LobeChat 数据库版本自身
- 带有 PGVector 插件的 PostgreSQL 数据库
- 支持 S3 协议的对象存储服务
- 受 LobeChat 支持的 SSO 登录鉴权服务
这些服务可以通过自建或者在线云服务组合搭配,以满足不同层次的部署需求。
本文中,我们提供了完全基于开源自建服务的 Docker Compose 配置,你可以直接使用这份配置文件来启动 LobeChat 数据库版本,也可以对之进行修改以适应你的需求。
我们默认使用 [MinIO](https://github.com/minio/minio) 作为本地 S3 对象存储服务,使用 [Casdoor](https://github.com/casdoor/casdoor) 作为本地鉴权服务。
## 快速启动
为方便快速上手,这一章使用 `docker-compose/local` 目录中的 `docker-compose.yml` 配置文件,启动后的 LobeChat 应用运行在 `http://localhost:3210`,可在本地运行。
<Callout type="warning">
为了快速上手,此 `docker-compose.yml` 内置了大量的 Secret/Password
的敏感字段配置,仅适用于快速演示或个人本地使用。请勿直接用于线上生产环境!否则遇到安全问题请自行负责!
</Callout>
<Steps>
### 一键启动脚本
新建一个 `lobe-chat-db` 目录,用于存放你的配置文件和后续的数据库文件。
```sh
mkdir lobe-chat-db
cd lobe-chat-db
```
我们提供了一个一键启动脚本 `setup.sh`,可以自动使用默认配置并启动服务:
```sh
bash <(curl -fsSL https://raw.githubusercontent.com/lobehub/lobe-chat/HEAD/docker-compose/local/setup.sh) -f -l zh_CN
```
### 启动 Docker
```sh
docker compose up -d
```
默认登录账号即 Casdoor 的默认账号,账号名 `admin`,密码 `123`
### 检查日志
```sh
docker logs -f lobe-chat
```
如果你在容器中看到了以下日志,则说明已经启动成功:
```log
[Database] Start to migration...
✅ database migration pass.
-------------------------------------
▲ Next.js 14.x.x
- Local: http://localhost:3210
- Network: http://0.0.0.0:3210
✓ Starting...
✓ Ready in 95ms
```
</Steps>
至此,你已经成功部署了 LobeChat 数据库版本,你可以通过 `http://localhost:3210` 访问你的 LobeChat 服务。
如果你遇到问题,请尝试查看 Docker 日志和控制台日志进行排查。
## 发布到生产IP 模式)
下文假设局域网 / 公网需要运行 LobeChat 服务的机器 IP 为 `your_server_ip`。
想要通过局域网 IP 访问,你需要首先按照本地启动运行:
```sh
bash <(curl -fsSL https://raw.githubusercontent.com/lobehub/lobe-chat/HEAD/docker-compose/local/setup.sh) -f -l zh_CN
docker compose up -d
```
接着,你需要修改下载下来的 `docker-compose.yml` 文件,执行一次全文替换,将 `localhost` 替换为 `your_server_ip`,随后重新启动:
```sh
sed -i 's/localhost/your_server_ip/g' docker-compose.yml
docker compose up -d
```
### 配置 Casdoor
1. 使用 `setup.sh` 脚本启动后Casdoor WebUI 默认端口为 `8000`,你可以通过 `http://your_server_ip:8000` 访问,默认用户名 `admin`,密码 `123`
2. 在 `身份认证 -> 应用` 中添加一行
```
http://your_server_ip:3210/api/auth/callback/casdoor
```
3. 其他配置大多保持默认即可,你也可以在 `身份认证 -> 应用` 中修改默认配置
### 配置 MinIO S3
1. 使用 `setup.sh` 脚本启动后MinIO WebUI 默认端口为 `9001`,你可以通过 `http://your_server_ip:9001` 访问,默认用户名 `YOUR_MINIO_USER`,密码 `YOUR_MINIO_PASSWORD`
2. 大多数配置保持默认即可,如果你希望能允许用户更换头像功能,你需要首先在 `buckets` 中创建一个名为 `casdoor` 的桶,选择自定义策略,复制并粘贴如下内容(如果你修改了桶名,请自行查找替换)
```json
{
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": ["*"]
},
"Action": ["s3:GetBucketLocation"],
"Resource": ["arn:aws:s3:::casdoor"]
},
{
"Effect": "Allow",
"Principal": {
"AWS": ["*"]
},
"Action": ["s3:ListBucket"],
"Resource": ["arn:aws:s3:::casdoor"],
"Condition": {
"StringEquals": {
"s3:prefix": ["files/*"]
}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": ["*"]
},
"Action": ["s3:PutObject", "s3:DeleteObject", "s3:GetObject"],
"Resource": ["arn:aws:s3:::casdoor/**"]
}
],
"Version": "2012-10-17"
}
```
3. 创建一个新的访问密钥,将生成的 `Access Key` 和 `Secret Key` 存储之
4. 在 Casdoor 的 `身份认证 -> 提供商` 中关联 MinIO S3 服务,以下是一个示例配置:
![casdoor](https://github.com/user-attachments/assets/71035610-0706-434e-9488-ab5819b55330)
其中,客户端 ID、客户端密钥为上一步创建的访问密钥中的 `Access Key` 和 `Secret Key``192.168.31.251` 应当被替换为 `your_server_ip`。
5. 在 Casdoor 的 `身份认证 -> 应用` 中,对 `app-built-in` 应用添加提供商,选择 `minio`,保存并退出
6. 你可以在 Casdoor 的 `身份认证 -> 资源` 中,尝试上传文件以测试配置是否正确
## 发布到生产(域名模式)
<Callout type="info">
对于拥有域名的部署,我们推荐使用 [Logto](https://logto.io/)
作为登录鉴权服务。本文剩余部分也将以其为例进行说明。如果你使用其他诸如 Casdoor
等其他登录鉴权服务,流程应当相近,但请注意不同的登录鉴权服务的端口配置可能有所差异。
</Callout>
在下文中,我们假设在上述服务之外,你还运行了一层 Nginx 来进行反向代理、配置 SSL。
域名和配套服务端口说明如下:
- `lobe.example.com`:为你的 LobeChat 服务端域名,需要反向代理到 LobeChat 服务端口,默认为 `3210`
- `lobe-auth-api.example.com`:为你的 Logto 服务端域名,需要反向代理到 Logto API 服务端口,默认为 `3001`
- `lobe-auth-ui.example.com`:为你的 Logto UI 域名,需要反向代理到 Logto WebUI 服务端口,默认为 `3002`
- `lobe-s3-api.example.com`:为你的 MinIO API 域名,需要反向代理到 MinIO API 服务端口,默认为 `9000`
- `lobe-s3-ui.example.com`:可选,为你的 MinIO UI 域名,需要反向代理到 MinIO WebUI 服务端口,默认为 `9001`
以及不进行反向代理的服务端口:
- `postgresql`:你的 PostgreSQL 数据库服务端口,默认为 `5432`
<Callout type="warning">
请务必注意CORS 跨域是在 MinIO / Logto 服务端内部配置的,请勿在你的反向代理中额外配置 CORS这会导致错误。
对于 minio 非 443 端口时Host 必须是 `$http_host`(带端口号),否则会 403 错误:`proxy_set_header Host $http_host`。
如果你需要配置 SSL 证书,请统一在外层的 Nginx 反向代理中配置,而不是在 MinIO 中配置。
</Callout>
### 配置文件
```sh
curl -fsSL https://raw.githubusercontent.com/lobehub/lobe-chat/HEAD/docker-compose/production/logto/docker-compose.yml > docker-compose.yml
curl -fsSL https://raw.githubusercontent.com/lobehub/lobe-chat/HEAD/docker-compose/production/logto/.env.zh-CN.example > .env
```
配置文件包括 `.env` 和 `docker-compose.yml` 两个文件,其中 `.env` 文件用于配置 LobeChat 的环境变量,`docker-compose.yml` 文件用于配置 Postgres、MinIO 和 Logto 服务。
一般情况下,你只应修改其中的域名和账号密码等敏感信息,其他配置项请按照默认值进行配置。
它们的示例配置请参见本文附录。
### Postgres 数据库配置
你可以使用下述指令检查日志:
```sh
docker logs -f lobe-chat
```
<Callout type="tip">
在我们官方的 Docker 镜像中,会在启动镜像前自动执行数据库 schema 的 migration
,我们的官方镜像承诺「空数据库 ->
完整表」这一段自动建表的稳定性。因此我们建议你的数据库实例使用一个空表实例,进而省去手动维护表结构或者
migration 的麻烦。
</Callout>
如果你在建表的时候出现了问题,你可以尝试使用如下命令强制移除数据库容器并重新启动:
```sh
docker compose down # 停止服务
sudo rm -rf ./data # 移除挂载的数据库数据
docker compose up -d # 重新启动
```
### 登录鉴权服务配置
本文以 Logto 为例,解释配置过程,如果你使用的是其他登录鉴权服务商,请参照其文档进行配置。
<Callout type="warning">
请记得注意配置对应登录鉴权服务提供商的 CORS 跨域配置,以确保 LobeChat 能够正常访问登录鉴权服务。
在本文中,你需要允许 `https://lobe.example.com` 的跨域请求。
</Callout>
你需要首先访问 WebUI 来进行配置:
- 如果你按照前文配置了反向代理,打开 `https://lobe-auth-ui.example.com`
- 否则,请在进行端口映射后,打开 `http://localhost:3002`
1. 注册一个新账户,首个注册的账户将自动成为管理员
2. 在 `Applications` 里创建一个 `Next.js (App Router)` 应用,名称随意
3. 配置 `Redirect URI` 为 `https://lobe.example.com/api/auth/callback/logto``Post sign-out redirect URI` 为 `https://lobe.example.com/`
4. 配置 `CORS allowed origins` 为 `https://lobe.example.com`
<Image
alt="配置 Logto"
src="https://github.com/user-attachments/assets/5b816379-c07b-40ea-bde4-df16e2e4e523"
/>
5. 获取 `App ID` 和 `App secrets`,填入你的 `.env` 文件中的 `AUTH_LOGTO_ID` 和 `AUTH_LOGTO_SECRET` 中
6. 配置你的 `.env` 文件中 `AUTH_LOGTO_ISSUER` 为 `https://lobe-auth-api.example.com/oidc`
<Image
alt="配置 Logto 环境变量"
src="https://github.com/user-attachments/assets/15af6d94-af4f-4aa9-bbab-7a46e9f9e837"
/>
7. 可选,在左侧 `Sign-in experience` 面板的 `Sign-up and sign-in - Advanced Options` 中关闭 `Enable user registration`,禁止用户自行注册。如果你禁止了用户自行注册,那么你只能在左侧 `User Management` 里手动添加用户。
<Image
alt="关闭用户注册"
src="https://github.com/user-attachments/assets/6b2e6f7b-fec5-41c6-864a-a1add40f74a0"
/>
8. 重启 LobeChat 服务:
```sh
docker compose up -d
```
<Callout type="warning">
请注意,管理员账户不等同于注册用户,不要用你的管理员账户登录 LobeChat那样只会报错。
</Callout>
### S3 对象存储服务配置
本文以 MinIO 为例,解释配置过程,如果你使用的是其他 S3 服务商,请参照其文档进行配置。
<Callout type="warning">
请记得注意配置对应 S3 服务商的 CORS 跨域配置,以确保 LobeChat 能够正常访问 S3 服务。
在本文中,你需要允许 `https://lobe.example.com` 的跨域请求。这既可以在 MinIO WebUI 的 `Configuration - API - Cors Allow Origin` 中配置,也可以在 Docker Compose 中的 `minio - environment - MINIO_API_CORS_ALLOW_ORIGIN` 中配置。
如果你使用第二种方法(这也是默认的方法)进行配置,你将无法再在 MinIO WebUI 中配置。
</Callout>
你需要首先访问 WebUI 来进行配置:
- 如果你按照前文配置了反向代理,打开 `https://lobe-s3-ui.example.com`
- 否则,请在进行端口映射后,打开 `http://localhost:9001`
1. 在登录界面输入你设置的 `MINIO_ROOT_USER` 和 `MINIO_ROOT_PASSWORD`,然后点击登录
2. 在左侧面板 Administer / Buckets 中点击 `Create Bucket`,输入 `lobe`(对应你的 `S3_BUCKET` 环境变量),然后点击 `Create`
<Image
alt="创建 MinIO 桶"
src="https://github.com/user-attachments/assets/79f44a13-00d3-4302-a6bc-5f4c6cdbffab"
/>
3. 选中你的桶,点击 Summary - Access Policy编辑选择 `Custom`,输入 `minio-bucket-config.json` 中的内容(见附录)并保存(同样默认你的桶名为 `lobe`
<Image
alt="选中 MinIO 桶策略"
src="https://github.com/user-attachments/assets/57032a82-7604-45d3-ba12-884af6fbcb7c"
/>
<Image
alt="配置 MinIO 桶策略"
src="https://github.com/user-attachments/assets/d8109f4e-71fc-4ba8-8402-ede92669d5e0"
/>
4. 在左侧面板 User / Access Keys 处,点击 `Create New Access Key`,无需额外修改,将生成的 `Access Key` 和 `Secret Key` 填入你的 `.env` 文件中的 `S3_ACCESS_KEY_ID` 和 `S3_SECRET_ACCESS_KEY` 中
<Image
alt="创建 MinIO 访问密钥"
src="https://github.com/user-attachments/assets/72f02ce5-9991-425b-9864-9113ee1ed6bf"
/>
5. 重启 LobeChat 服务:
```sh
docker compose up -d
```
至此,你已经成功部署了 LobeChat 数据库版本,你可以通过 `https://lobe.example.com` 访问你的 LobeChat 服务。
## 附录
为方便一键复制,在此汇总域名方式下生产部署配置服务端数据库所需要的示例配置文件(对于本地快速启动、局域网 IP 访问等场景,请直接使用 `setup.sh` 脚本生成后自行修改):
### `.env`
```sh
# 必填LobeChat 域名,用于 tRPC 调用
# 请保证此域名在你的 NextAuth 鉴权服务提供商、S3 服务商的 CORS 白名单中
APP_URL=https://lobe.example.com/
# Postgres 相关,也即 DB 必需的环境变量
# 必填,用于加密敏感信息的密钥,可以使用 openssl rand -base64 32 生成
KEY_VAULTS_SECRET=Kix2wcUONd4CX51E/ZPAd36BqM4wzJgKjPtz2sGztqQ=
# 必填Postgres 数据库连接字符串,用于连接到数据库
# 格式postgresql://username:password@host:port/dbname如果你的 pg 实例为 Docker 容器且位于同一 docker-compose 文件中,亦可使用容器名作为 host
DATABASE_URL=postgresql://postgres:uWNZugjBqixf8dxC@postgresql:5432/lobe
# NEXT_AUTH 相关,也即鉴权服务必需的环境变量
# 可以使用 auth0、Azure AD、GitHub、Authentik、Zitadel、Logto 等,如有其他接入诉求欢迎提 PR
# 目前支持的鉴权服务提供商请参考https://lobehub.com/zh/docs/self-hosting/advanced/auth#next-auth
# 如果你有 ACCESS_CODE请务必清空我们以 NEXT_AUTH 作为唯一鉴权来源
# 必填,用于 NextAuth 的密钥,可以使用 openssl rand -base64 32 生成
NEXT_AUTH_SECRET=NX2kaPE923dt6BL2U8e9oSre5RfoT7hg
# 必填,指定鉴权服务提供商,这里以 Logto 为例
NEXT_AUTH_SSO_PROVIDERS=logto
# 必填NextAuth 的 URL用于 NextAuth 的回调
NEXTAUTH_URL=https://lobe.example.com/api/auth
# NextAuth 鉴权服务提供商部分,以 Logto 为例
# 其他鉴权服务提供商所需的环境变量请参考https://lobehub.com/zh/docs/self-hosting/environment-variables/auth
AUTH_LOGTO_ID=YOUR_LOGTO_CLIENT_ID
AUTH_LOGTO_SECRET=YOUR_LOGTO_CLIENT_SECRET
AUTH_LOGTO_ISSUER=https://lobe-auth-api.example.com/oidc
# 代理相关,如果你需要的话(比如你使用 GitHub 作为鉴权服务提供商)
# HTTP_PROXY=http://localhost:7890
# HTTPS_PROXY=http://localhost:7890
# S3 相关,也即非结构化数据(文件、图片等)存储必需的环境变量
# 这里以 MinIO 为例
# 必填S3 的 Access Key ID对于 MinIO 来说,直到在 MinIO UI 中手动创建之前都是无效的
S3_ACCESS_KEY_ID=YOUR_S3_ACCESS_KEY_ID
# 必填S3 的 Secret Access Key对于 MinIO 来说,直到在 MinIO UI 中手动创建之前都是无效的
S3_SECRET_ACCESS_KEY=YOUR_S3_SECRET_ACCESS_KEY
# 必填S3 的 Endpoint用于服务端/客户端连接到 S3 API
S3_ENDPOINT=https://lobe-s3-api.example.com
# 必填S3 的 Bucket直到在 MinIO UI 中手动创建之前都是无效的
S3_BUCKET=lobe
# 必填S3 的 Public Domain用于客户端通过公开连接访问非结构化数据
S3_PUBLIC_DOMAIN=https://lobe-s3-api.example.com
# 选填S3 的 Enable Path Style
# 对于主流 S3 Cloud 服务商,一般填 0 即可;对于自部署的 MinIO请填 1
# 请参考https://lobehub.com/zh/docs/self-hosting/advanced/s3#s-3-enable-path-style
S3_ENABLE_PATH_STYLE=1
# 其他基础环境变量,视需求而定。注意不要有 ACCESS_CODE
# 请参考https://lobehub.com/zh/docs/self-hosting/environment-variables/basic
# 请注意,对于服务端版本,其 API 必须支持嵌入OpenAI text-embedding-3-small模型否则无法对上传文件进行处理但你无需在 OPENAI_MODEL_LIST 中指定此模型
# OPENAI_API_KEY=sk-xxxx
# OPENAI_PROXY_URL=https://api.openai.com/v1
# OPENAI_MODEL_LIST=...
```
### `docker-compose.yml`
```yaml
name: lobe-chat-database
services:
postgresql:
image: pgvector/pgvector:pg16
container_name: lobe-postgres
ports:
- '5432:5432'
volumes:
- './data:/var/lib/postgresql/data'
environment:
- 'POSTGRES_DB=lobe'
- 'POSTGRES_PASSWORD=uWNZugjBqixf8dxC'
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U postgres']
interval: 5s
timeout: 5s
retries: 5
restart: always
minio:
image: minio/minio
container_name: lobe-minio
ports:
- '9000:9000'
- '9001:9001'
volumes:
- './s3_data:/etc/minio/data'
environment:
- 'MINIO_ROOT_USER=YOUR_MINIO_USER'
- 'MINIO_ROOT_PASSWORD=YOUR_MINIO_PASSWORD'
- 'MINIO_DOMAIN=lobe-s3-api.example.com'
- 'MINIO_API_CORS_ALLOW_ORIGIN=https://lobe.example.com' # Your LobeChat's domain name.
restart: always
command: >
server /etc/minio/data --address ":9000" --console-address ":9001"
logto:
image: svhd/logto
container_name: lobe-logto
ports:
- '3001:3001'
- '3002:3002'
depends_on:
postgresql:
condition: service_healthy
environment:
- 'TRUST_PROXY_HEADER=1'
- 'DB_URL=postgresql://postgres:uWNZugjBqixf8dxC@postgresql:5432/logto'
- 'ENDPOINT=https://lobe-auth-api.example.com'
- 'ADMIN_ENDPOINT=https://lobe-auth-ui.example.com'
entrypoint: ['sh', '-c', 'npm run cli db seed -- --swe && npm start']
lobe:
image: lobehub/lobe-chat-database
container_name: lobe-chat
ports:
- '3210:3210'
depends_on:
- postgresql
- minio
- logto
env_file:
- .env
restart: always
volumes:
data:
driver: local
s3_data:
driver: local
```
### `minio-bucket-config.json`
```json
{
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": ["*"]
},
"Action": ["s3:GetBucketLocation"],
"Resource": ["arn:aws:s3:::lobe"]
},
{
"Effect": "Allow",
"Principal": {
"AWS": ["*"]
},
"Action": ["s3:ListBucket"],
"Resource": ["arn:aws:s3:::lobe"],
"Condition": {
"StringEquals": {
"s3:prefix": ["files/*"]
}
}
},
{
"Effect": "Allow",
"Principal": {
"AWS": ["*"]
},
"Action": ["s3:PutObject", "s3:DeleteObject", "s3:GetObject"],
"Resource": ["arn:aws:s3:::lobe/files/**"]
}
],
"Version": "2012-10-17"
}
```
[docker-pulls-link]: https://hub.docker.com/r/lobehub/lobe-chat-database
[docker-pulls-shield]: https://img.shields.io/docker/pulls/lobehub/lobe-chat-database?color=45cc11&labelColor=black&style=flat-square
[docker-release-link]: https://hub.docker.com/r/lobehub/lobe-chat-database
[docker-release-shield]: https://img.shields.io/docker/v/lobehub/lobe-chat-database?color=369eff&label=docker&labelColor=black&logo=docker&logoColor=white&style=flat-square
[docker-size-link]: https://hub.docker.com/r/lobehub/lobe-chat-database
[docker-size-shield]: https://img.shields.io/docker/image-size/lobehub/lobe-chat-database?color=369eff&labelColor=black&style=flat-square