# 私有部署（Docker）

在自己的服务器上部署 AskTable，完成初始化和访问验证。

部署说明 · 模块: deploy · 管理人员 · 部署形态：私有部署 · 已确认产品版本：资料未说明 · 来源：现有文档

私有部署把 AskTable 的主服务、PostgreSQL、Redis 和 Python 沙箱跑在自己的服务器上。只有主服务对宿主机开端口，其余服务通过 Compose 内部网络通信。

服务器能访问镜像仓库时，选择**网络部署**；完全内网隔离时，选择**离线部署**，在外网下载离线包和安装脚本，再拷入内网安装。

## 前置条件

| 项目     | 要求                                                                                                                                                                                            |
| ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 架构     | Linux x86\_64（amd64）或 ARM64（arm64）；离线包必须与目标服务器的 Docker 架构匹配                                                                                                                                   |
| 最低配置   | 4 核 CPU、16G 内存、100G 磁盘                                                                                                                                                                        |
| 操作系统   | Linux 服务器                                                                                                                                                                                     |
| Docker | [Docker Engine](https://docs.docker.com/engine/install/) + [Docker Compose](https://docs.docker.com/compose/install/) **v2.23.1 或更高**。compose 里的 `configs.content`（内联建库 SQL）从这个版本才有，低版本解析直接失败 |
| 模型服务   | 准备可访问的模型服务；完全内网隔离时，使用内网模型服务                                                                                                                                                                   |
| 端口     | 宿主机 8000 空闲（容器内监听 80）                                                                                                                                                                         |

## 操作步骤

**网络部署**

网络部署需要通过 HTTPS（443）访问镜像仓库；模型与追踪服务按实际使用情况放行：

| 地址                                    | 用途                    | 不放开的表现                      |
| ------------------------------------- | --------------------- | --------------------------- |
| `registry.cn-shanghai.aliyuncs.com`   | 拉取全部镜像                | `docker compose pull` 卡住后超时 |
| `dockerauth.cn-hangzhou.aliyuncs.com` | 阿里云镜像仓库鉴权             | `docker login` 报鉴权失败，拉不到镜像  |
| `aiproxy.asktable.com`                | 用 AskTable 托管算力时的模型服务 | 向导里填完算力 API Key 后点「测试模型」不通过 |
| `lf.asktable.com`                     | 调用追踪（Langfuse）        | 对话功能正常，服务日志里追踪上报报错          |

**保存 docker-compose.yaml**

在服务器上新建一个目录（例如 `/opt/asktable`），把本页签下方“docker-compose.yaml”一节的内容原样存成该目录下的 `docker-compose.yaml`。

端口和卷路径都别改：端口决定访问地址，卷路径决定数据落在宿主机的哪个目录。

**启动**

在 `docker-compose.yaml` 所在目录执行：

```bash
docker compose up -d
```

`asktable` 容器启动时会先跑一遍数据库结构迁移（`syncdb`），再拉起 API、nginx、后台任务进程和内置 MCP 服务。首次启动会自动建 `asktable` 和 `asktable_workbook` 两个库。

### docker-compose.yaml

四个服务的作用写在行内注释里。后端服务之间通过 Compose 内部网络通信，只有 `asktable` 对外暴露端口。

```yaml docker-compose.yaml download="docker-compose.yaml" downloadLabel="下载"
services:
  # 主服务：后端 API + 前端 + 内置 MCP（对外暴露的唯一服务）
  asktable:
    image: registry.cn-shanghai.aliyuncs.com/datamini/asktable-all-in-one:latest  # 中国大陆；海外用 datamini/asktable-all-in-one:latest
    container_name: asktable
    depends_on:
      - asktable-pg
      - asktable-redis
      - asktable-atbox
    ports:
      - "8000:80"
    privileged: true
    environment:
      TZ: Asia/Shanghai
      AT_REGION: cn                       # cn 或 global；部署后保持不变
      DATABASE_HOST: asktable-pg
      DATABASE_PORT: 5432
      DATABASE_USER: asktable
      DATABASE_PASSWORD: asktable          # 【建议修改】
      DATABASE_DB: asktable
      REDIS_URL: redis://asktable-redis:6379
      ATBOX_URL: http://asktable-atbox:5300
      # Workbook 独立数据库：同实例同角色，独立 database（PG 无跨库查询 → 硬隔离）
      WORKBOOK_PG_DSN: postgresql://asktable:asktable@asktable-pg:5432/asktable_workbook
    volumes:
      - ./asktable_data:/asktable

  # PostgreSQL 17（pgvector）：主数据库（元数据、配置、字段向量）
  asktable-pg:
    image: registry.cn-shanghai.aliyuncs.com/dminfra/pgvector:pg17
    container_name: asktable-pg
    restart: unless-stopped
    command: ["postgres", "-c", "max_connections=100"]
    environment:
      POSTGRES_USER: asktable
      POSTGRES_PASSWORD: asktable          # 【建议修改】与 DATABASE_PASSWORD 保持一致
      POSTGRES_DB: asktable
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    configs:
      # 仅在数据卷为空的全新部署首次执行一次，建 workbook 独立库
      - source: workbook-initdb
        target: /docker-entrypoint-initdb.d/01-create-workbook-db.sql

  # Redis 7.4：任务队列
  asktable-redis:
    image: registry.cn-shanghai.aliyuncs.com/dminfra/redis:7.4.4
    container_name: asktable-redis
    restart: unless-stopped
    command: redis-server --appendonly yes
    volumes:
      - ./redis_data:/data

  # Python 沙箱：隔离执行智能体生成的不可信 Python。
  # 下面标「安全」的是沙箱本体，请勿删改；标「可调」的资源上限可按机器调整。
  asktable-atbox:
    image: registry.cn-shanghai.aliyuncs.com/datamini/asktable-atbox:latest  # 中国大陆；海外用 datamini/asktable-atbox:latest
    container_name: asktable-atbox
    restart: unless-stopped
    environment:
      TZ: Asia/Shanghai
      ATBOX_MAX_WORKERS: 8          # 可调：并发 worker 数
      ATBOX_DEFAULT_TIMEOUT: 30s    # 可调：默认执行超时
      ATBOX_MAX_TIMEOUT: 120s       # 可调：最大执行超时
      ATBOX_ENABLE_NETWORK: "0"     # 安全：沙箱内禁用网络
    # 安全：只读 rootfs + 临时可写区（/var/atbox/root/tmp 是 chroot 工作目录），两者配套，勿删
    read_only: true
    tmpfs:
      - /var/atbox/root/tmp:rw,noexec,nosuid,nodev,mode=1777,size=512m
      - /tmp:rw,noexec,nosuid,nodev,mode=1777,size=64m
    # 安全：丢弃全部 capability，只加回 chroot + 降 UID 所需的最小集，勿改
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - SETUID
      - SETGID
      - SYS_CHROOT
    security_opt:
      - no-new-privileges:true      # 安全：禁止提权
    pids_limit: 128                 # 可调：进程数上限（防 fork 炸弹）
    mem_limit: 1g                   # 可调：内存上限
    cpus: 1.0                       # 可调：CPU 上限

configs:
  # 内联建库 SQL，需 Docker Compose v2.23.1+（configs.content 支持）
  workbook-initdb:
    content: |
      CREATE DATABASE asktable_workbook;
```

**Warning**

生产部署前务必改掉标了 **【建议修改】** 的默认密钥：`DATABASE_PASSWORD`、`POSTGRES_PASSWORD` 与 `WORKBOOK_PG_DSN` 中的密码必须一致。

**离线部署**

适用于目标服务器不能连接公网的环境。离线包包含运行 AskTable 所需的镜像与 Compose 配置，**不包含 Docker 安装包或大模型权重**。请提前在内网服务器安装 Docker / Compose，并准备可从 AskTable 容器访问的内网模型服务。

**确认目标服务器架构**

在内网服务器上执行：

```bash
docker info --format '{{.Architecture}}'
docker compose version
```

`x86_64` 或 `amd64` 选择 AMD64 包；`aarch64` 或 `arm64` 选择 ARM64 包。安装脚本也支持 `docker-compose` 命令，版本同样需要 **2.23.1 或更高**。

**在外网下载离线包与安装脚本**

在能联网的电脑上，下载**一个匹配目标服务器架构的离线包**，以及安装脚本：

| 文件              | 下载                                                                                                                                                |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| Linux AMD64 离线包 | [asktable-offline-linux-amd64.tar.gz](https://datamini-release.oss-cn-shanghai.aliyuncs.com/asktable/offline/asktable-offline-linux-amd64.tar.gz) |
| Linux ARM64 离线包 | [asktable-offline-linux-arm64.tar.gz](https://datamini-release.oss-cn-shanghai.aliyuncs.com/asktable/offline/asktable-offline-linux-arm64.tar.gz) |
| 安装脚本（两种架构通用）    | [install-asktable.sh](https://datamini-release.oss-cn-shanghai.aliyuncs.com/asktable/offline/install-asktable.sh)                                 |

脚本会校验压缩包，请一起下载同次发布的脚本和包，不要改名，也不要手动解压。

**拷入内网服务器**

将压缩包和 `install-asktable.sh` 放在服务器上的**同一个可写目录**，例如 `/opt/asktable-offline`。该目录用于存放安装文件，与部署目录 `/opt/asktable` 分开。

安装过程中会在包旁解压镜像，再导入 Docker。安装文件所在磁盘要留出解压空间，Docker 数据目录所在磁盘也要留出镜像空间；此外还要保留业务数据增长空间。

下方命令使用 `sudo`：执行账号需要管理 Docker，并能写入安装文件目录和部署目录。首次安装的部署目录必须为空或不存在；已有部署请先看本页“升级”。

**预检查部署计划**

进入安装文件目录，预检查压缩包、架构和部署配置：

```bash
cd /opt/asktable-offline
sudo sh install-asktable.sh --dir /opt/asktable --dry-run
```

确认输出的部署目录、项目、离线包版本和镜像计划符合预期。`--dry-run` 不导入镜像、不修改部署配置，也不启动服务；若报告校验失败，请重新取得同次发布的脚本和压缩包。

**安装并启动**

预检查通过后，在同一目录执行：

```bash
sudo sh install-asktable.sh --dir /opt/asktable
```

脚本会导入本地镜像，首次安装时写入包内的 Compose 配置，并以 `--pull never --no-build` 启动服务，安装过程无需拉取公网镜像。

安装命令完成后，继续下方的初始化和访问验证，确认页面与模型调用均正常。

## 完成初始化向导

网络部署与离线部署首次安装都从 `http://<服务器地址>:8000/` 访问。数据库里还没有用户时，会进入 `/setup` 初始化向导，依次完成「创建管理员」「配置模型」。已有部署升级后沿用原访问地址和账号。

1. **创建管理员和组织**：填写组织名称、管理员邮箱、密码和确认密码，按页面密码要求提交。该账号创建为系统管理员，并建立默认组织。
2. **配置模型**：联网环境可选「AskTable 官方 API 渠道」并填算力 API Key；完全内网隔离时，选「自定义渠道」，填写内网模型服务的 Base URL、API Key 和模型名称，点「完成配置」。配置说明见 [配置大模型](https://docs.asktable.com/admin/models)。
3. **验证使用**：用刚创建的管理员账号登录，按后续引导完成项目创建，确认控制台能打开、模型测试通过，再连接一组数据完成一次提问。容器启动成功并不等于模型或业务已经可用。

**Note**

要让团队在飞书或 Slack 中问数，还需要额外加一个网关容器，见 [部署消息网关](https://docs.asktable.com/deploy/feishu-gateway)。

## 访问地址

| 入口                 | 地址                                 |
| ------------------ | ---------------------------------- |
| 控制台                | `http://<服务器>:8000/`               |
| API 文档（ReDoc）      | `http://<服务器>:8000/api/v1/redoc`   |
| API 文档（Swagger UI） | `http://<服务器>:8000/api/v1/docs`    |
| 当前版本（JSON）         | `http://<服务器>:8000/api/v1/version` |
| MCP 服务             | `http://<服务器>:8000/mcp/`           |

## 启用 Workbook

Workbook 用于在 AskTable 内创建和编辑表格，数据存放在独立的 PostgreSQL database 中。`WORKBOOK_PG_DSN` 决定连接哪个库，不能指向 AskTable 主数据库。

本页完整 Compose 已配置 `WORKBOOK_PG_DSN`，并在 PostgreSQL **空数据卷首次初始化**时创建 `asktable_workbook`。全新部署无需重复建库；复用已有数据卷时，初始化 SQL 不会再次执行，仅更新 Compose 不会补建这个库。

已有部署按以下步骤检查和补齐：

1. 确认 PostgreSQL 中已存在独立的 Workbook 数据库。若使用本页的服务名和数据库账号，且尚未建库，在部署目录执行一次：

   ```bash
   docker compose exec asktable-pg psql -U asktable -d asktable -c "CREATE DATABASE asktable_workbook;"
   ```

   使用外部 PostgreSQL 或自定义账号时，由数据库管理员创建独立库，并让 Workbook 连接账号有权连接及创建 schema、表和读写数据。

2. 在 `asktable` 服务的 `environment` 中确认 `WORKBOOK_PG_DSN` 指向该独立库。以下为格式示意，用户名、密码、地址和库名均需替换为实际值：

   ```text
   postgresql://<用户名>:<密码>@<数据库主机>:5432/<Workbook库名>
   ```

   使用本页 Compose 时，数据库主机是容器网络中的 `asktable-pg`，不是 `localhost`；密码必须与实际数据库账号一致。显式设置 `WORKBOOK_PG_DSN` 为空字符串会停用 Workbook。

3. 配置调整后执行 `docker compose up -d asktable`，让主服务应用配置。登录后实际创建一个 Workbook、录入数据并查询，确认可用。

界面显示“已配置”只说明 DSN 非空，不代表数据库连接成功。若提示 Workbook 不可用，查看 `docker compose logs asktable` 中的连接错误，核对库是否存在、账号密码和网络是否可达；无需删除已有数据卷。

## 关键约束

| 项目              | 值或默认                                                                                                | 在哪里改                                                                             |
| --------------- | --------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- |
| 对外暴露的端口         | 只有 `asktable` 的 `8000:80`；`asktable-pg`、`asktable-redis`、`asktable-atbox` 都不映射宿主机端口                 | `docker-compose.yaml` 的 `ports`                                                  |
| 数据库密码           | 示例值 `asktable`                                                                                      | `DATABASE_PASSWORD`、`POSTGRES_PASSWORD` 与 `WORKBOOK_PG_DSN` 中的密码，三处保持一致          |
| 沙箱鉴权            | 不做 API Key，只认内网来源                                                                                   | 因此 `asktable-atbox` 不要加 `ports`                                                  |
| 沙箱网络            | `ATBOX_ENABLE_NETWORK: "0"`，沙箱内禁用网络                                                                 | `asktable-atbox` 的 `environment`                                                 |
| 沙箱并发与超时         | `ATBOX_MAX_WORKERS: 8`、`ATBOX_DEFAULT_TIMEOUT: 30s`、`ATBOX_MAX_TIMEOUT: 120s`                       | 同上                                                                               |
| 容器时区            | 网络部署示例和离线包的主服务与沙箱均设为 `Asia/Shanghai`                                                                | 对应服务的 `environment` 中设置 `TZ`                                                     |
| 部署 Region       | 默认 `cn`，可设 `global`；私有部署始终以邮箱为账号标识                                                                  | `AT_REGION`，部署后固定，后续变更需迁移身份数据                                                    |
| PostgreSQL 连接上限 | 示例为 100；默认应用保守峰值 51                                                                                 | `asktable-pg.command`；扩容前见[运维与容量规划](https://docs.asktable.com/deploy/operations) |
| 后台任务进程数         | 1                                                                                                   | `asktable` 的 `environment` 加 `AT_WORKER_NUM_PROCS`                               |
| 数据落盘位置          | `./asktable_data`（上传文件在 `filestore/`、日志在 `log/`、向量模型缓存在 `models/`）、`./postgres_data`、`./redis_data` | `docker-compose.yaml` 的 `volumes`                                                |
| Workbook 独立库    | `asktable_workbook`，与主库同实例同角色、独立 database                                                           | `WORKBOOK_PG_DSN` 与内联建库 SQL                                                      |
| 镜像标签            | `:latest`                                                                                           | 要能按版本回滚就写死版本号，发版同时推 `{version}` 和 `latest`                                       |
| 管理员入口           | 第一个用户由 `/setup` 向导创建，之后的用户从「系统设置」→「用户注册」控制                                                          | 头像 →「系统设置」→「用户注册」                                                                |

## 出问题怎么判断

| 现象                                | 判定条件                                                                                  | 处理                                                                                                 |
| --------------------------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| 浏览器打不开                            | `docker compose ps` 里 `asktable` 不是 `running`                                         | 看 `docker compose logs asktable` 开头的初始化日志                                                          |
| 页面能开但接口全 502                      | `curl -sS http://127.0.0.1:8000/api/v1/version` 不返回 JSON                              | 容器内 API 进程没起来，看 `docker compose logs asktable`                                                     |
| 后端连不上数据库                          | 日志里是数据库认证失败，且 `DATABASE_PASSWORD` 与 `POSTGRES_PASSWORD` 不同                            | 两处改成同一个值，再 `docker compose up -d` 重建容器                                                             |
| `docker compose up` 起不来           | 报错里出现 `port is already allocated`                                                     | 停掉占用 8000 的进程，或把 `ports` 改成 `"18000:80"` 后从新端口访问                                                   |
| 日志出现 `collation version mismatch` | 换过 PostgreSQL 镜像且复用了旧 `postgres_data`                                                 | 按 [版本升级与迁移](https://docs.asktable.com/deploy/migration) 先重建索引再刷新版本号                                |
| 反复出现 `DATABASE_BUSY`              | 日志显示等待连接超时或 PostgreSQL 连接耗尽                                                           | 先检查数据库余量和后台并发，按[运维与容量规划](https://docs.asktable.com/deploy/operations)处理                            |
| 工作簿相关操作报错                         | 页面提示 Workbook 不可用，或 `docker compose logs asktable` 出现 `Workbook PG connection failed` | 按[启用 Workbook](https://docs.asktable.com/deploy/docker#%E5%90%AF%E7%94%A8-workbook)检查独立数据库、连接配置及权限 |
| 拉不到镜像                             | `docker compose pull` 报 TLS 超时或鉴权失败                                                   | 网络部署按对应页签的地址表放行；隔离环境使用离线包安装                                                                        |
| 向导进不去                             | 打开首页直接到登录页，没有 `/setup`                                                                | 库里已经有用户了，用管理员账号登录；忘记密码走登录页的找回流程                                                                    |

## 升级

两种方式升级前都应备份数据库和业务数据，并阅读 [版本升级与迁移](https://docs.asktable.com/deploy/migration)。

**网络部署**：在部署目录执行：

```bash
docker compose pull
docker compose down
docker compose up -d
```

网络部署示例使用 `:latest`，`pull` 会拉到当前最新版；要升到指定版本，把 `image` 的 `:latest` 换成具体版本号。

**离线部署**：在外网重新下载同次发布的脚本与对应架构的包，拷入内网。按上方离线步骤先执行 `--dry-run`，再去掉该参数安装；`--dir` 必须指向原部署目录。脚本会识别已有部署，按计划更新镜像，保留原有端口、卷和其他配置，无需执行 `docker compose pull`。

脚本生成的恢复记录只用于恢复本机升级前的配置和本地镜像标签，**不包含数据库与业务数据备份**。升级后仍需检查容器日志、原访问地址和一次实际查询；数据库迁移与数据恢复按迁移文档处理。

## 卸载

```bash
docker compose down
rm -rf asktable_data postgres_data redis_data
```

**Warning**

删数据卷会清空所有数据，不可恢复。执行前先备份。

## 阿里云计算巢部署

通过[阿里云市场](https://market.aliyun.com/detail/cmgj00073069.html)购买的实例使用计算巢自动部署。按订单与计算巢服务实例中的流程完成部署，然后从实例提供的访问地址打开 AskTable，完成初始化及模型配置。需要激活企业许可证时，按[商业授权](https://docs.asktable.com/admin/license)操作。

## 下一步

- [部署认证配置](https://docs.asktable.com/deploy/authentication) — 登录方式、SMTP 与 SMS 环境变量
- [运维与容量规划](https://docs.asktable.com/deploy/operations) — 数据库连接池与后台并发
- [配置大模型](https://docs.asktable.com/admin/models) — 接入自己的或托管的模型
- [版本升级与迁移](https://docs.asktable.com/deploy/migration) — 升级、回滚和跨版本手动操作
- [部署 AI 搜索（值索引）](https://docs.asktable.com/deploy/ai-search) — 让简称也能命中完整值
- [部署消息网关](https://docs.asktable.com/deploy/feishu-gateway) — 让团队在飞书私聊和群里问数
- [进阶配置](https://docs.asktable.com/deploy/advanced) — 子路径部署与白标定制
- [连接数据源](https://docs.asktable.com/data/connect) — 把数据接进来
