用 VPS 部署 CloudBeaver:把 PostgreSQL 和 MySQL 管理入口放进浏览器

从 Docker Compose、SSH 初始化到 Caddy HTTPS,讲清 CloudBeaver 社区版的工作区、数据库连接地址和上线检查。

查一条订单、看一张表的字段、给新服务补一份只读连接,原本都算不上大事。麻烦往往出在环境上:这台电脑没有客户端,那台电脑的连接配置过期了,临时借来的机器又不适合保存数据库密码。

CloudBeaver 把数据库客户端放到了服务器上。浏览器负责显示页面,真正与 PostgreSQL、MySQL 建立连接的是 VPS 上的 CloudBeaver。理解这个位置关系,后面的端口、域名和连接地址就不容易填错。

这篇从一台能运行 Docker Compose 的 Linux VPS 开始,搭建 CloudBeaver Community,先通过 SSH 隧道完成初始化,再交给宿主机上的 Caddy 提供 HTTPS。示例采用 26.2.1,是本文在 2026 年 9 月 30 日核对并验证的版本。以后安装时应先看发行说明,不必为了照抄本文永久停留在这个版本。

先确定:你需要的是一个数据库入口

CloudBeaver 不会把已有 PostgreSQL 搬进浏览器,也不会替你保存业务数据库的完整备份。它更像一台常驻 VPS 的工作电脑:连接数据库、查看对象、运行 SQL、处理结果集,操作依然受数据库账号权限约束。

社区版采用 Apache 2.0 许可证。日常查表和执行 SQL 可以从社区版开始,但不要把桌面 DBeaver、CloudBeaver Community 和商业版本的功能表混在一起。官方文档把拖拽式 Visual Query Builder 标为商业版本功能,本文不把它算进免费部署后的能力。项目仓库、可视化查询构建器说明

初始配置中也应检查禁用的驱动。本次 26.2.1 社区版向导把 SQLite、部分 H2 和 DuckDB 驱动列在禁用列表里,因此不能把“支持某种数据库”理解为装好以后每个驱动都已开放。本文使用 PostgreSQL,不需要为演示去放开文件型驱动。

个人查几个数据库,桌面客户端加 SSH 隧道也很好用。真正适合放到 VPS 的情形,是你经常换设备,或者希望给少量成员提供一个统一入口。相应的维护工作也跟着来了:账号清理、版本更新、工作区备份,以及谁能看到哪些连接。这些应在上线前想好。

VPS 不只看核数,先看它离数据库有多远

页面打开很快,不代表查询一定快。浏览器到 CloudBeaver 是一段网络,CloudBeaver 到数据库是另一段网络。数据库在国内机房,却把管理器放到遥远的海外节点,打开一棵包含大量表和字段的对象树,也可能有明显等待。

优先把管理器放在数据库附近,能走受控内网就走内网。购买另一台机器之前,先确认现有 VPS 还有多少可用内存,数据库能否接受新来源,以及这个节点是否需要额外的数据访问审批。

对少人数、轻查询的起步环境,可以先按 2 核、4GB 内存安排预算。这是便于留出余量的实践起点,不是官方最低要求,也不承诺能支撑多少并发。Java 堆、驱动、查询结果和系统都要占内存;如果数据库也在同一台小机器上,还需要给它单独留空间。不要用一次空闲状态的内存截图判断容量。

如果正好缺一台用于自托管的小服务器,可以到雨云查看当前云服务器方案。选配置时把机房到数据库的延迟、磁盘空间和后续扩容放在价格旁边一起看;活动价格和库存以页面为准。已有合适的 VPS,则可以直接复用。

留一个目录,把工作区明确放在持久卷里

先确认 Docker Engine 和 Compose 插件已经安装:

docker version
docker compose version
mkdir -p ~/services/cloudbeaver
cd ~/services/cloudbeaver

创建 compose.yaml:

name: cloudbeaver
services:
  cloudbeaver:
    image: dbeaver/cloudbeaver:26.2.1
    restart: unless-stopped
    ports:
      - "127.0.0.1:8978:8978"
    volumes:
      - workspace:/opt/cloudbeaver/workspace
    environment:
      JAVA_OPTS: "-Xms256m -Xmx1024m"
    mem_limit: 2g
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"
volumes:
  workspace:

这里有四个值得停下来看的地方。

第一,8978 只绑定 127.0.0.1。这不是给公网开一个新的管理端口,浏览器最终从 Caddy 的 HTTPS 入口进入。先限制监听地址,比安装完才补防火墙规则更清楚。

第二,workspace 是命名卷,挂在官方镜像的工作区位置。容器重建后,用户和连接相关状态仍需要它。不要把“容器可以删了重建”误解成“卷也可以随便删”。尤其不要把 docker compose down -v 当普通重启命令。官方 Docker 部署说明

第三,-Xmx1024m 约束的是 Java 堆,不是整个容器。这里另设 2GB 容器上限,为堆外内存和运行时留空间;实际负载上来后要观察,而不是凭这个数值保证永不 OOM。少量查询时也不必把服务器剩余内存全部分给 Java。JVM 参数说明

第四,日志有轮转。管理工具平时不显眼,几个月后占满磁盘却会影响同机业务。这里的上限仅针对容器标准输出日志,不会替你清理工作区和导出文件。

运行:

docker compose config --quiet
docker compose pull
docker compose up -d
docker compose logs --tail=100 cloudbeaver
curl -I http://127.0.0.1:8978/

首次启动需要时间。curl 能拿到页面响应,只说明 Web 入口可达;还没有验证管理员登录,更没有验证任何数据库连接。

第一次配置,先走 SSH 隧道

在自己的电脑上执行,替换 SSH 用户和 VPS 地址:

ssh -N -L 18978:127.0.0.1:8978 your-user@your-vps

然后在本机浏览器打开 http://127.0.0.1:18978/。SSH 连接保持运行,关闭它以后这个临时入口就不可用了。如果本机 18978 被占用,可以只换前面的本地端口。

在初始化向导里设置管理员和强密码,确认服务器名称。对私人数据库入口关闭匿名访问,不要为了省一次登录给匿名用户分配连接。若暂时不需要让成员自己创建任意数据库连接,也不要开启相关选项。

正式域名确定后,核对服务器 URL 配置是否与实际 HTTPS 地址一致。初始化只需要一遍;重启以后再次出现欢迎向导,先检查是否挂错工作区,别急着再创建一套账号覆盖线索。

本地隔离环境中的 CloudBeaver 社区版界面

图为本文使用的隔离演示环境,数据均为虚构样例;不是线上业务数据库。

管理员是 CloudBeaver 的管理员,不等于数据库超级用户。这两个账号不要使用同一个密码,也不要因为界面登录成功,就认为数据库连接一定有权限。

用宿主机 Caddy 接入域名

假设你准备使用 db.example.com,并且 Caddy 运行在 VPS 宿主机上,可以添加:

db.example.com {
    reverse_proxy 127.0.0.1:8978
}

这是示例域名,发布前替换成自己的。域名应解析到这台 VPS,证书签发所需的网络条件也要满足。服务器已有网站时,只增加新的站点块,不要用这几行覆盖整份配置。

sudo caddy validate --config /etc/caddy/Caddyfile
sudo systemctl reload caddy
curl -I https://db.example.com/

Caddy 的反向代理能够处理 WebSocket 升级,常规部署不用照搬 Nginx 的 Upgrade 指令。HTTP 代理和身份认证代理是两回事:这份配置只代理流量,CloudBeaver 自己仍负责登录。Caddy reverse_proxy 文档

如果 Caddy 也在容器里,127.0.0.1 就指向 Caddy 容器本身,上面的地址不能照抄。应让两者加入一个专用 Docker 网络,再使用 CloudBeaver 的服务名和 8978 端口。不要为绕过这个问题,顺手把 8978 改成对所有网卡开放。

到这里可以关闭本机 SSH 隧道,重新从正式 HTTPS 域名登录。检查页面、登录状态、数据库连接和一次真实查询,四项都通过后再把地址交给其他人。

PostgreSQL 的 Host 该填什么

最容易出错的是填 localhost。CloudBeaver 在容器里时,它通常指向自己的容器,不是 VPS 宿主机,更不是你的笔记本。

数据库位置 连接地址如何选择 先核实什么
同一个 Docker 网络 数据库服务名或明确的网络别名 两个容器确实在同一网络,端口是容器内部端口
同机但在另一个容器网络 建立受控的共同网络后使用别名 不要为图省事加入与业务无关的全部网络
另一台内网服务器 可路由的内网地址或域名 路由、防火墙、数据库来源规则
云厂商托管数据库 厂商提供的连接端点 来源白名单、TLS、账号和目标数据库名

1Panel 安装的 PostgreSQL 也遵循这个规则。先查看它实际的容器、网络和别名,再在自己的 Compose 中声明外部网络;不要假定所有安装都叫同一个名字。使用宿主机映射端口还是容器内部端口,取决于你选择的连接路径,不能混用。

第一条连接建议使用专门创建的只读账号,目标也先选测试库。连接建立后执行:

SELECT current_database(), current_user, version();
SELECT 1 AS connection_check;

核对数据库名、账号和版本是否符合预期。只看绿色“连接成功”还不够:误连到另一套测试库,也可能得到完全正常的反馈。

打开页面之后,做一次真正的验收

把平时会做的工作走一遍:展开某张表,查看字段,执行带 LIMIT 的查询,导出少量结果,退出后再登录。然后重启 CloudBeaver,确认用户和连接仍在。验证重启时不要清理卷。

docker compose restart cloudbeaver
docker compose ps
docker compose logs --since=5m cloudbeaver

如果页面显示正常,但对象树一直转圈,问题可能在数据库连接或元数据读取权限。若请求直接得到 502,先查 Caddy 到 8978 的上游;若提示密码错误,就查看数据库账号和认证设置。把不同层的错误分开,通常比反复重启更快。

还有一项不在页面里:备份。至少保存 Compose、镜像版本、Caddy 站点配置和完整工作区。业务 PostgreSQL 则单独做自己的备份。管理器的工作区即使恢复成功,也不能恢复一条被误删的业务记录。

参考资料