ToolJet 3.20 Docker Compose 部署指南

ToolJet v3.20.246-lts 社区版 Docker Compose 从零部署实战:官方部署文件、密钥生成、内置 PostgreSQL、管理员开通、数据持久化、备份与升级全流程实测。

ToolJetToolJet低代码2026/10/21

ToolJet 3.20 Docker Compose 部署指南

目标:在一台 Ubuntu 22.04 服务器上,使用官方 Docker Compose 方案从零部署 ToolJet v3.20.246-lts(社区版),覆盖官方部署文件获取、密钥生成、内置 PostgreSQL、服务启动、管理员开通、数据持久化、备份与升级全流程,已在 Ubuntu 22.04 服务器(Web 端口 8137)实测通过。

一、环境信息

本篇所有命令与回显均在下列环境中实测(2026-10-21):

  • 操作系统:Ubuntu 22.04.4 LTS(x86_64)
  • Docker:Docker version 29.8.1, build 4a63305
  • Docker Compose:Docker Compose version v5.5.1
  • ToolJet:v3.20.246-lts(社区版,tooljet/tooljet-ce,2026-10-15 发布,实查 GitHub Releases 与 Docker Hub)
  • 数据库:PostgreSQL 16(官方部署方案指定版本)
  • Web 端口:8137(ToolJet 默认 80,本文映射为 8137,读者可按需调整)
  • 部署目录:/opt/tooljet/(compose 文件、.env 与数据目录均在此)
  • 实测资源占用(部署完成空闲态):ToolJet 主服务约 450MiB 内存,PostgreSQL 约 32MiB 内存

💡 说明:ToolJet 官方发布通道包含 LTS 稳定通道与 Beta 预览通道。LTS 版本号形如 v3.20.246-lts,Beta 版本号形如 v3.21.78-beta。生产部署一律选 LTS 通道并锁定具体版本号,不要使用滚动 latest 标签。

二、镜像选型说明

ToolJet 在 Docker Hub 上提供两套镜像仓库,对应两个版本 edition:

镜像仓库对应版本说明
tooljet/tooljet-ce社区版(CE)AGPL-3.0 开源协议,功能完整可自托管,本文采用
tooljet/tooljet企业版(EE)需商业授权(License Key),含 SSO 高级特性、审计等

社区版常用标签(Docker Hub 实查,2026-10-21):

标签含义
ce-latest社区版最新构建(含 Beta,滚动更新,不推荐生产)
ce-lts-latest社区版最新 LTS(滚动,升级有意外风险)
v3.20.246-lts社区版具体 LTS 版本(本文实测采用)

关键差异与选型建议:生产环境务必用「仓库 + 精确版本 tag」(如 tooljet/tooljet-ce:v3.20.246-lts),保证升级可控、可回滚;latest 类滚动标签在 compose pull 后可能直接跳到 Beta 构建导致数据结构提前升级。数据库选 postgres:16(官方 docker-compose-db.yaml 指定版本),PostgreSQL 15/17 同样可用,但建议跟随官方组合减少兼容性变量。

三、前置条件

  1. 一台 4GB 内存以上的 Linux 服务器(实测环境 32GB 内存,ToolJet 空闲态内存占用约 450MiB,2C4G 起步可用);
  2. 已安装 Docker 与 Docker Compose 插件(安装方法见 Docker 官方文档 https://docs.docker.com/engine/install/ 与 https://docs.docker.com/compose/install/ );
  3. 服务器能访问外网(拉取镜像与更新检查);拉取国外镜像缓慢时可为 Docker 配置代理(如 http://<代理IP>:7897);
  4. 放行防火墙端口:本文使用 TCP 8137(按需改为 80/443 或其他空闲端口);
  5. openssl 命令(生成部署密钥,Ubuntu 自带)。

四、部署步骤

4.1 建立部署目录

所有部署文件与数据统一放在 /opt/tooljet/:

mkdir -p /opt/tooljet/postgres_data
cd /opt/tooljet

postgres_data 子目录用于承载 PostgreSQL 数据文件(部署文件会以绑定挂载方式使用它)。

4.2 获取 docker-compose.yaml

官方在生产部署文档中提供的下载方式(来源:docs.tooljet.ai/docs/setup/docker,查询日期 2026-10-21):

curl -LO https://tooljet-deployments.s3.us-west-1.amazonaws.com/docker/docker-compose-db.yaml
mv docker-compose-db.yaml docker-compose.yaml

官方原版文件内容如下(实测下载,v3.20.246-lts 时期版本):

name: Tooljet app

services:
  tooljet:
    tty: true
    stdin_open: true
    container_name: Tooljet-app
    image: tooljet/tooljet:ee-lts-latest
    platform: linux/amd64
    restart: always
    env_file: .env
    ports:
      - 80:80
    depends_on:
      - postgres
    environment:
      SERVE_CLIENT: "true"
      PORT: "80"
    command: npm run start:prod

  postgres:
    container_name: ${PG_HOST}
    image: postgres:16
    restart: always
    volumes:
      - postgres:/var/lib/postgresql/data
    env_file: .env
    environment:
      - POSTGRES_USER=${PG_USER}
      - POSTGRES_PASSWORD=${PG_PASS}


volumes:
  postgres:
    driver: local
    driver_opts:
      o: bind
      type: none
      device: ${PWD}/postgres_data
  certs:
  logs:
  fallbackcerts:

官方原版默认拉企业版镜像 tooljet/tooljet:ee-lts-latest 且监听 80 端口。社区版自托管建议改用本文的实测版本:锁定 CE 版本号、改用空闲端口、显式声明内部网络(在多套部署并存的服务器上固定网段,避免地址池冲突)。

本文实测采用的 docker-compose.yaml(逐行与官方结构一致,仅调整 4 处:镜像改为 CE 锁版本、端口改 8137、数据卷显式绑定宿主路径、网络显式声明):

name: tooljet-v3.20.246-lts-stack

services:
  tooljet:
    tty: true
    stdin_open: true
    container_name: tooljet-3.20.246-lts-app
    image: tooljet/tooljet-ce:v3.20.246-lts
    platform: linux/amd64
    restart: always
    env_file: .env
    ports:
      - "8137:80"
    depends_on:
      - postgres
    environment:
      SERVE_CLIENT: "true"
      PORT: "80"
    command: npm run start:prod
    networks:
      - tooljetnet

  postgres:
    container_name: tooljet-3.20.246-lts-postgres
    image: postgres:16
    restart: always
    volumes:
      - /opt/tooljet/postgres_data:/var/lib/postgresql/data
    env_file: .env
    environment:
      - POSTGRES_USER=${PG_USER}
      - POSTGRES_PASSWORD=${PG_PASS}
    networks:
      - tooljetnet

networks:
  tooljetnet:
    driver: bridge
    ipam:
      config:
        - subnet: 10.89.57.0/24

逐项说明:

  • name:Compose 项目名。多套部署并存时务必唯一(如带上版本号),否则同名项目执行 down 会误删其他项目的服务;
  • image:tooljet/tooljet-ce:v3.20.246-lts 社区版锁定版本;
  • ports: "8137:80":宿主机 8137 映射到服务 80 端口(ToolJet 镜像内以 PORT=80 提供服务);
  • env_file: .env:两个服务共享同一份环境变量文件;
  • environment 的 SERVE_CLIENT=true 与 PORT=80:让主服务同进程托管前端页面并监听 80;
  • command: npm run start:prod:生产模式启动命令;
  • postgres 服务的 POSTGRES_USER/POSTGRES_PASSWORD 取自 .env 的 PG_USER/PG_PASS,数据目录绑定挂载到 /opt/tooljet/postgres_data;
  • networks 显式声明网段:10.89.57.0/24 为实测时选取的空闲网段,单套部署的服务器可直接删除整个 networks 配置让引擎自动分配。

4.3 生成 .env

ToolJet 需要 3 把随机密钥(数据源凭据加密、会话加密、内置数据库 API 认证)与数据库口令。官方提供 internal.sh 交互脚本自动生成,也可手工生成。手工方式(实测):

cd /opt/tooljet
openssl rand -hex 32
# 30f0b8b62ab3360b21759611df643f8210ba00e2a9a7e29da5f2d3e1c22b1b0d   ← 示例输出(LOCKBOX_MASTER_KEY,实测每次随机)
openssl rand -hex 64
# 9d2fb7c47d4a51e29c1a6f9e5e4c0b8a7d3f2e1c0b9a8f7e6d5c4b3a29180f7e6d5c4b3a29180f7e6d5c4b3a29180f7e6d5c4b3a29180f7e6d5c4b3a29180f1   ← 示例输出(SECRET_KEY_BASE,实测 128 位十六进制)
openssl rand -hex 32
# 74c1a9e3f2b5d480a6c9e1b3f7d52084c6a9e2b1f4d7308a5c2e9b6f1d3408a7   ← 示例输出(PGRST_JWT_SECRET)

⚠️ 注意:三把密钥一旦开始生产使用不可随意更换(LOCKBOX_MASTER_KEY 加密着全部数据源凭据,更换将导致凭据无法解密)。请把生成结果妥善备份。密钥轮换方法见官方脚本 rotate:keys:prod(支持 --dry-run 演练)。

写入 /opt/tooljet/.env(实测内容,口令与密钥为实验室演示值,生产请替换为自己的随机值):

TOOLJET_HOST=http://192.168.1.62:8137
LOCKBOX_MASTER_KEY=30f0b8b62ab3360b21759611df643f8210ba00e2a9a7e29da5f2d3e1c22b1b0d
SECRET_KEY_BASE=9d2fb7c47d4a51e29c1a6f9e5e4c0b8a7d3f2e1c0b9a8f7e6d5c4b3a29180f7e6d5c4b3a29180f7e6d5c4b3a29180f7e6d5c4b3a29180f7e6d5c4b3a29180f1

# DATABASE CONFIG
ORM_LOGGING=error
PG_DB=tooljet_production
PG_USER=postgres
PG_HOST=postgres
PG_PASS=q1w2e3r4
PG_PORT=5432

# TOOLJET DATABASE
TOOLJET_DB=tooljet_db
TOOLJET_DB_USER=postgres
TOOLJET_DB_HOST=postgres
TOOLJET_DB_PASS=q1w2e3r4
TOOLJET_DB_RECONFIG=true
TOOLJET_DB_STATEMENT_TIMEOUT=60000

PGRST_DB_URI=postgres://postgres:q1w2e3r4@postgres/tooljet_db
PGRST_HOST=localhost:3002
PGRST_JWT_SECRET=74c1a9e3f2b5d480a6c9e1b3f7d52084c6a9e2b1f4d7308a5c2e9b6f1d3408a7
PGRST_SERVER_PORT=3002
PGRST_DB_PRE_CONFIG=postgrest.pre_config

CHECK_FOR_UPDATES=true
DISABLE_TOOLJET_TELEMETRY=true

DEFAULT_FROM_EMAIL=hello@tooljet.io
SMTP_DISABLED=true

USER_SESSION_EXPIRY=2880
DEPLOYMENT_PLATFORM=docker
ENABLE_MULTIPLAYER_EDITING=true
WORKER=true
TOOLJET_WORKFLOW_CONCURRENCY=5
WORKFLOW_TIMEOUT_SECONDS=60

逐项说明:

  • TOOLJET_HOST:实例对外访问地址,必须是 http:// 或 https:// 开头的完整 URL,端口要与 ports 映射一致(实测 http://192.168.1.62:8137);此值影响应用内生成的分享链接、密码重置链接等;
  • PG_HOST=postgres:指向 compose 内数据库服务的名称(compose 内置 DNS 解析),不要写 localhost;
  • PG_DB/PG_USER/PG_PASS:主库库名/账号/口令,首次启动自动建库;
  • TOOLJET_DB_*:内置数据库(ToolJet Database 功能)的第二套连接信息,库 tooljet_db 启动时自动创建;
  • PGRST_DB_URI:内置数据库 REST API(PostgREST)的连接串,账号口令须与 TOOLJET_DB_* 一致;
  • WORKER=true:开启工作流任务处理(单实例内建队列,无需外部 Redis);
  • DISABLE_TOOLJET_TELEMETRY=true:关闭每 24 小时一次的使用数据上报;
  • SMTP_DISABLED=true:实验室环境关闭邮件发送;生产接入 SMTP 时删除此行并补 SMTP_USERNAME/SMTP_PASSWORD/SMTP_DOMAIN/SMTP_PORT。

💡 官方脚本方式:官方还提供 internal.sh 自动填写三把密钥与数据库口令(下载地址 https://tooljet-deployments.s3.us-west-1.amazonaws.com/docker/internal.sh,配合 .env.internal.example 使用,执行 ./internal.sh 交互输入或回车自动生成)。手工方式与脚本方式二选一即可。

4.4 启动服务

cd /opt/tooljet
docker compose up -d

实测输出(首次启动会拉取约 1.5GB 镜像,耗时视带宽):

[+] Running 3/3
 ✔ Network tooljet-v3.20.246-lts-stack_tooljetnet  Created
 ✔ Container tooljet-3.20.246-lts-postgres         Started
 ✔ Container tooljet-3.20.246-lts-app              Started

首次启动时主服务自动完成建库与数据结构迁移(实测启动日志节选,逐行照抄):

tooljet-3.20.246-lts-app  | Redis started
tooljet-3.20.246-lts-app  | wait-for-it.sh: waiting 300 seconds for postgres:5432
tooljet-3.20.246-lts-app  | wait-for-it.sh: postgres:5432 is available after 1 seconds
tooljet-3.20.246-lts-app  |
tooljet-3.20.246-lts-app  | > tooljet@1.18.0 db:setup:prod
tooljet-3.20.246-lts-app  | > npm --prefix server run db:setup:prod
tooljet-3.20.246-lts-app  |
tooljet-3.20.246-lts-app  | > server@0.0.1 db:create:prod
tooljet-3.20.246-lts-app  | > node dist/scripts/create-database.js
tooljet-3.20.246-lts-app  |
tooljet-3.20.246-lts-app  | Picking up config from the environment
tooljet-3.20.246-lts-app  | Created database tooljet_production
tooljet-3.20.246-lts-app  | Connected to PostgreSQL
tooljet-3.20.246-lts-app  | creating table
tooljet-3.20.246-lts-app  | Data populated for table: products
tooljet-3.20.246-lts-app  | creating table
tooljet-3.20.246-lts-app  | Data populated for table: sample_data_country_gdp
tooljet-3.20.246-lts-app  | creating table
tooljet-3.20.246-lts-app  | Data populated for table: sample_data_orders
tooljet-3.20.246-lts-app  | creating table
tooljet-3.20.246-lts-app  | Data populated for table: sample_data_organizations
tooljet-3.20.246-lts-app  | creating table
tooljet-3.20.246-lts-app  | Data populated for table: sample_data_product_cars
tooljet-3.20.246-lts-app  | creating table
tooljet-3.20.246-lts-app  | Data populated for table: sample_data_users

日志要点:主服务启动内建 Redis(单实例任务队列用)→ 等待数据库就绪(wait-for-it,最长 300 秒)→ 自动创建 tooljet_production 库并填充示例数据表 → 执行 TypeORM 迁移。迁移完成即进入服务状态。

4.5 验证部署

健康检查接口(实测):

curl http://localhost:8137/api/health
{"works":"yeah","license":{"valid":false,"expired":true}}

works: yeah 表示服务正常;社区版无授权,license 显示无效属预期。登录页可达性验证(实测):

curl -sS -o /dev/null -w '%{http_code}\n' http://localhost:8137/login
200

服务状态检查(实测):

docker compose ps
NAME                            IMAGE                              COMMAND                   SERVICE    CREATED          STATUS          PORTS
tooljet-3.20.246-lts-app        tooljet/tooljet-ce:v3.20.246-lts   "./server/entrypoint…"   tooljet    2 minutes ago    Up 2 minutes    0.0.0.0:8137->80/tcp, [::]:8137->80/tcp
tooljet-3.20.246-lts-postgres   postgres:16                        "docker-entrypoint.s…"   postgres   2 minutes ago    Up 2 minutes    5432/tcp

数据库侧确认(实测):主库 tooljet_production 与内置库 tooljet_db 均已自动创建:

docker compose exec postgres psql -U postgres -c '\l'
                                                           List of databases
        Name        |  Owner   | Encoding | Locale Provider |  Collate   |   Ctype    | ICU Locale | ICU Rules |   Access privileges
--------------------+----------+----------+-----------------+------------+------------+------------+-----------+-----------------------
 postgres           | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           |
 sample_db          | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           |
 template0          | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | =c/postgres          +
                    |          |          |                 |            |            |            |           | postgres=CTc/postgres
 template1          | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           | =c/postgres          +
                    |          |          |                 |            |            |            |           | postgres=CTc/postgres
 tooljet_db         | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           |
 tooljet_production | postgres | UTF8     | libc            | en_US.utf8 | en_US.utf8 |            |           |
(6 rows)

4.6 首次开通管理员

浏览器访问 http://<服务器IP>:8137/,首次访问进入管理员开通页,依次填写:

  • 姓名(Name):admin
  • 邮箱(Email):admin@tooljet.local
  • 密码(Password):不少于 5 位(本文示例 q1w2e3r4)
  • 工作区名称(Workspace Name):admin-ws

提交后即创建实例首个管理员并进入工作台。上述表单对应的开通接口(实测,可用于自动化初始化):

curl -sS -X POST http://localhost:8137/api/onboarding/setup-super-admin \
  -H 'Content-Type: application/json' \
  -d '{"name":"admin","email":"admin@tooljet.local","password":"q1w2e3r4","workspaceName":"admin-ws"}' \
  -w '\nHTTP %{http_code}\n'

实测返回 HTTP 201,响应体节选(关键字段):

{"organization_id":"b464cb3c-5922-47d8-b4c5-b8eb11f31ffd","organization":"admin-ws",...,"id":"dba689fc-7d89-4e1d-b369-92a24c78d777","email":"admin@tooljet.local","first_name":"admin","admin":true,...}

⚠️ 注意:该接口仅在实例还没有任何用户时可用(首个用户注册保护);name 与 workspaceName 为必填字段名,误用 first_name/workspace 会返回 400 并提示 name should not be empty/workspaceName should not be empty(实测报错原文)。

登录验证接口(实测):

curl -sS -X POST http://localhost:8137/api/authenticate \
  -H 'Content-Type: application/json' \
  -d '{"email":"admin@tooljet.local","password":"q1w2e3r4"}' \
  -w '\nHTTP %{http_code}\n'

实测返回 HTTP 200,响应体开头:

{"organization_id":"b464cb3c-5922-47d8-b4c5-b8eb11f31ffd","organization":"admin-ws",...,"email":"admin@tooljet.local","first_name":"admin",...}

浏览器使用 admin@tooljet.local / q1w2e3r4 登录 http://<服务器IP>:8137/ 即可开始构建应用。

五、数据持久化说明

  • 主库数据:PostgreSQL 数据目录绑定挂载在宿主机 /opt/tooljet/postgres_data,服务重建、升级后数据不丢。确认方法:ls /opt/tooljet/postgres_data 可见 base/、global/、pg_wal/ 等目录;
  • 应用数据:应用定义、用户、数据源凭据(加密)全部存于主库 tooljet_production;ToolJet 内置数据库(内部表)存于 tooljet_db;
  • 文件附件:社区版单实例部署的图片等文件默认存于主服务本地目录,随主服务实例存在;迁移实例时需一并处理(建议生产接入 S3 兼容对象存储);
  • 备份:两套库都要备份。实测导出主库(fresh install 约 229KB):
docker compose exec postgres sh -c 'pg_dump -U postgres tooljet_production' > tooljet_production-$(date +%F).sql
(无输出即成功,实测生成 228863 字节 SQL 文件,文件头两行:)
--
-- PostgreSQL database dump
--

内置库同理:pg_dump -U postgres tooljet_db。官方还提供一键备份/恢复脚本 backup-restore.sh(下载地址 https://tooljet-deployments.s3.us-west-1.amazonaws.com/docker/backup-restore.sh,仅适用于内置数据库方案)。

六、环境变量表(部署必备最小集)

变量必填示例值说明
TOOLJET_HOST是http://192.168.1.62:8137实例对外地址,须带 http(s) 前缀
LOCKBOX_MASTER_KEY是openssl rand -hex 32 生成数据源凭据加密主钥,32 字节十六进制
SECRET_KEY_BASE是openssl rand -hex 64 生成会话 Cookie 加密密钥,64 字节十六进制
PG_HOST是postgres主库地址(compose 内为服务名)
PG_DB是tooljet_production主库名,自动创建
PG_USER是postgres主库账号
PG_PASS是q1w2e3r4主库口令
TOOLJET_DB_HOST是postgres内置库地址
TOOLJET_DB是tooljet_db内置库名,自动创建
TOOLJET_DB_USER / TOOLJET_DB_PASS是postgres / q1w2e3r4内置库账号口令
PGRST_DB_URI是postgres://postgres:q1w2e3r4@postgres/tooljet_db内置库 REST 连接串
PGRST_JWT_SECRET是openssl rand -hex 32 生成内置库 API JWT 密钥
PGRST_DB_PRE_CONFIG是postgrest.pre_config内置库预配置(固定值)
WORKER建议true开启工作流任务处理
USER_SESSION_EXPIRY可选2880会话时长(分钟),默认 2880 即 2 天
DISABLE_TOOLJET_TELEMETRY可选true关闭使用数据上报
CHECK_FOR_UPDATES可选true每 24 小时检查新版本

更多可选参数(SMTP、SSO、限流、工作流超时等约 80 项)的逐项说明见《ToolJet 3.20 配置参数详解》。

七、配置参数说明

  • 部署后约 80% 的配置调整都只改 .env 一处,然后 docker compose up -d 重建服务生效;
  • compose 文件里的 SERVE_CLIENT=true、PORT=80、command: npm run start:prod 保持官方默认即可,不要改动;
  • 数据库连接既可用分散变量(PG_HOST/PG_DB/...),也可合并为连接串 DATABASE_URL=postgres://用户:口令@主机:5432/库名?sslmode=disable(设置了 DATABASE_URL 时启动脚本会从连接串解析数据库地址);
  • 参数的完整分类、默认值与生效验证方法见《ToolJet 3.20 配置参数详解》。

八、配置文件挂载

本方案没有需要手工维护的应用配置文件,配置面收敛为两处:

  1. .env(宿主机 /opt/tooljet/.env):通过 compose 的 env_file: .env 注入两个服务。修改后执行 docker compose up -d 重建生效;
  2. PostgreSQL 数据目录(宿主机 /opt/tooljet/postgres_data):绑定挂载,数据库配置走默认值。如需定制 PostgreSQL 参数(如 max_connections),可在 compose 的 postgres 服务下追加 command: postgres -c max_connections=300 之类的启动参数,或挂载自定义 postgresql.conf。

⚠️ 注意:postgres_data 目录属数据库进程所有,不要手工改动其中文件;备份恢复一律通过 pg_dump/pg_restore 或官方 backup-restore.sh 进行。

九、等价 docker run

不使用 Compose 时,等价于先建网络、再分别启动两个服务的命令形态(与上文 compose 等价,参数一一对应):

# 1. 创建专用网络
docker network create --subnet 10.89.57.0/24 tooljetnet

# 2. 启动 PostgreSQL(数据目录绑定挂载)
docker run -d \
  --name tooljet-3.20.246-lts-postgres \
  --network tooljetnet \
  --restart always \
  -e POSTGRES_USER=postgres \
  -e POSTGRES_PASSWORD=q1w2e3r4 \
  --env-file /opt/tooljet/.env \
  -v /opt/tooljet/postgres_data:/var/lib/postgresql/data \
  postgres:16

# 3. 启动 ToolJet 主服务(等数据库就绪后启动)
docker run -d \
  --name tooljet-3.20.246-lts-app \
  --network tooljetnet \
  --restart always \
  -p 8137:80 \
  -e SERVE_CLIENT=true \
  -e PORT=80 \
  --env-file /opt/tooljet/.env \
  tooljet/tooljet-ce:v3.20.246-lts \
  npm run start:prod

要点:--env-file 复用同一份 .env;主服务必须挂在同一网络才能按服务名 postgres 解析数据库;生产建议仍用 Compose(依赖顺序、一键升级、日志管理更省心)。

十、常用运维命令

cd /opt/tooljet

docker compose ps                      # 服务状态(实测输出见 4.5 节)
docker compose logs -f tooljet         # 跟踪主服务日志(Ctrl+C 退出)
docker compose logs --tail 100 tooljet # 最近 100 行日志
docker compose restart tooljet         # 重启主服务
docker compose down                    # 停止并移除服务(数据目录保留)
docker compose up -d                   # 启动(.env 或 compose 修改后重建生效)
docker compose exec tooljet sh         # 进入主服务排障

升级到新 LTS 版本的流程(官方升级指引,来源 docs.tooljet.ai/docs/setup/docker,查询日期 2026-10-21):

# 1. 备份两套库(务必两套都备)
docker compose exec postgres sh -c 'pg_dump -U postgres tooljet_production' > tooljet_production-$(date +%F).sql
docker compose exec postgres sh -c 'pg_dump -U postgres tooljet_db' > tooljet_db-$(date +%F).sql

# 2. 停止服务(保留数据)
docker compose down

# 3. 编辑 docker-compose.yaml,把 image 改为新版本 tag(先到 Docker Hub 确认最新 LTS tag)
#    image: tooljet/tooljet-ce:v3.x.y-lts

# 4. 拉取新镜像并启动(启动时自动执行增量迁移)
docker compose pull
docker compose up -d

# 5. 验证:compose ps 状态 Up;curl /api/health 返回 {"works":"yeah",...};登录检查应用列表

⚠️ 注意:跨多个大版本升级前,先阅读官方 Release Notes 的升级要求;跨大版本(v2→v3)迁移需要先升到官方指定的中间版本再跨到最新 LTS,不要一步跨多个大版本。

十一、常见问题(FAQ)

Q1:docker compose up -d 后主服务反复重启,日志报数据库连接失败? 日志中看到 wait-for-it.sh: timeout occurred after waiting 300 seconds for postgres:5432 或连接拒绝,多为 PG_HOST 填错。compose 部署必须填服务名 postgres,填 localhost 会让主服务连自己(实测验证 PG_HOST=postgres 可用)。改 .env 后 docker compose up -d 重建。

Q2:TOOLJET_HOST 填错会怎样? 页面能打开但应用内生成的分享链接、邀请链接、密码重置链接都指向错误地址。确认规则:必须带 http:// 或 https:// 前缀,端口与对外映射端口一致(实测值 http://192.168.1.62:8137)。

Q3:首次启动日志里大量 QUERY (...) 行刷屏? 这是 ORM_LOGGING=all 的效果(全量 SQL 调试日志)。生产建议 ORM_LOGGING=error(仅错误与慢查询)或留空,改后重建生效。本文 .env 示例已用 ORM_LOGGING=error。

Q4:访问 /metrics 返回的是网页 HTML 而不是指标数据? 在 .env 加 ENABLE_METRICS=true 并重建后,指标端点实际是 /api/metrics(实测:curl -H 'Accept: application/json' http://localhost:8137/api/metrics 返回内存/CPU JSON,Accept: text/plain 返回 Prometheus 格式文本)。根路径 /metrics 会被前端路由接管返回页面。

Q5:拉取 ToolJet 镜像很慢或超时? 社区版镜像压缩体积约 1.5GB。为 Docker 守护进程配置 HTTP 代理(如 http://<代理IP>:7897)后重新 docker compose pull。

Q6:up -d 提示端口被占用? ports: "8137:80" 的宿主侧端口与服务器其他服务冲突时,换一个空闲端口(同时同步修改 .env 的 TOOLJET_HOST 端口)。查占用:ss -ltnp | grep 8137。

Q7:升级后数据会丢吗? 只要 postgres_data 绑定挂载在宿主机且未执行 docker compose down -v 之外的卷删除操作,数据保留在 /opt/tooljet/postgres_data;升级前仍须按第十节流程备份两套库。

十二、参考链接