本地数据库客户端只能自己用?用 cpolar 安全访问 NAS 上的 PostgreSQL 管理台

本地数据库客户端只能自己用?用 cpolar 安全访问 NAS 上的 PostgreSQL 管理台

图:用 cpolar 安全访问 NAS 上的 PostgreSQL 管理台

我以前最怕这种验收:数据库跑在家里 NAS 或办公室小主机上,本地客户端连得好好的,同事一问"我能不能看一下表结构和几条测试数据",现场就开始尴尬。

直接把 PostgreSQL 的 5432 端口映射出去肯定不合适。数据库端口不是演示页面,公网裸露风险太高;更别说很多测试库里还混着调试数据,一不小心就把权限放大了。

这篇换个更稳的做法:在 NAS/Docker 上跑 PostgreSQL 测试库和 pgAdmin Web 管理台,只给同事一个临时 HTTPS 入口进管理台,用只读账号验收查询结果。验收结束后关掉 cpolar,入口消失,数据库端口一直不对公网开放。

1 这次要做成什么?

这套方案的重点不是"远程连接数据库",而是"临时验收 Web 管理台"。

最终链路长这样:

text 复制代码
同事浏览器
   ↓ HTTPS 临时地址
cpolar HTTP 隧道
   ↓
NAS 上的 pgAdmin Web 管理台:5050
   ↓ Docker 内网
PostgreSQL 测试库:5432

划重点:外部访问的是 pgAdmin 的 Web 页面,不是 PostgreSQL 的 5432 端口。pgAdmin 再使用 Docker 内网地址连接 PostgreSQL。

这篇里我会用 PostgreSQL 官方镜像和 pgAdmin 官方镜像做演示。pgAdmin 官方文档要求容器启动时设置 PGADMIN_DEFAULT_EMAIL 和 PGADMIN_DEFAULT_PASSWORD,容器默认监听 80,我们把它映射到 NAS 的 5050 端口,方便本地浏览器访问。

安全边界先说清楚:

  • 不公网暴露 PostgreSQL 5432。
  • 不给同事超级管理员账号。
  • 只使用脱敏测试库和只读数据库账号。
  • cpolar 只用于临时验收,验收结束立刻关闭隧道。
  • 生产环境走正式远程接入方案、堡垒机或统一网关,不拿临时隧道当长期入口。

2 环境准备:NAS 上先有 Docker

这篇默认你的 NAS、迷你主机或 Linux 服务器已经能运行 Docker 和 Docker Compose。群晖、威联通、Ubuntu 小主机都可以,命令写法以标准 Docker Compose 为准。

先在 NAS 上建一个单独目录,别把测试库文件散落到系统目录里:

bash 复制代码
mkdir -p ~/pg-review-demo
cd ~/pg-review-demo

这里单独建目录有两个好处:后面清理简单,Compose 文件、初始化 SQL、数据卷都能按项目收口。临时验收结束后,如果确定不用了,整个目录也更容易归档。

再确认 Docker Compose 可用:

bash 复制代码
docker version
docker compose version

如果 docker compose version 没有输出版本号,先把 NAS 的 Docker 套件或 Docker Compose 插件补齐。这里别急着往下跑,Compose 不通,后面的服务编排会直接卡住。

3 部署 PostgreSQL 测试库和 pgAdmin

先写一份 docker-compose.yml。这份配置包含两个服务:

  • postgres:测试用 PostgreSQL 数据库,容器内端口仍是 5432,但不映射到宿主机公网端口。
  • pgadmin:Web 管理台,对宿主机开放 5050,后面 cpolar 只穿透这个端口。
bash 复制代码
cat > docker-compose.yml <<'EOF'
services:
  postgres:
    image: postgres:16
    container_name: pg-review-postgres
    environment:
      POSTGRES_DB: reviewdb
      POSTGRES_USER: app_admin
      POSTGRES_PASSWORD: AdminPass_ChangeMe_2026
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./init:/docker-entrypoint-initdb.d:ro
    networks:
      - pg-review-net
    restart: unless-stopped

  pgadmin:
    image: dpage/pgadmin4:latest
    container_name: pg-review-pgadmin
    environment:
      PGADMIN_DEFAULT_EMAIL: admin@example.com
      PGADMIN_DEFAULT_PASSWORD: PgAdmin_ChangeMe_2026
      PGADMIN_DISABLE_POSTFIX: "1"
    ports:
      - "5050:80"
    depends_on:
      - postgres
    networks:
      - pg-review-net
    restart: unless-stopped

volumes:
  pgdata:

networks:
  pg-review-net:
    driver: bridge
EOF

提醒一下,示例密码是为了教程可复制。你自己跑的时候要改成更长的随机密码,尤其是 pgAdmin 登录密码。同事验收只需要 pgAdmin 的登录入口,不需要知道 app_admin 的密码。

这里没有写 5432:5432,是故意的。PostgreSQL 只在 Docker 网络里被 pgAdmin 访问,避免把数据库原始端口暴露到 NAS 宿主机和公网。

4 初始化测试表,并创建只读账号

为了让验收不只是"能打开页面",我们准备一张脱敏订单表,再创建一个只读账号 review_reader。同事后面用这个账号在 pgAdmin 里跑查询,能看到数据,但不能改表。

先创建初始化目录和 SQL 文件:

bash 复制代码
mkdir -p init
cat > init/01-review-demo.sql <<'EOF'
CREATE SCHEMA IF NOT EXISTS review_app;

CREATE TABLE IF NOT EXISTS review_app.orders (
  id BIGSERIAL PRIMARY KEY,
  order_no TEXT NOT NULL UNIQUE,
  customer_name TEXT NOT NULL,
  amount NUMERIC(10, 2) NOT NULL,
  status TEXT NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

INSERT INTO review_app.orders (order_no, customer_name, amount, status, created_at) VALUES
  ('T20260720001', '测试用户A', 128.50, 'PAID', '2026-07-20 10:20:00+08'),
  ('T20260720002', '测试用户B', 68.00, 'PENDING', '2026-07-20 10:35:00+08'),
  ('T20260720003', '测试用户C', 299.90, 'PAID', '2026-07-20 11:05:00+08')
ON CONFLICT (order_no) DO NOTHING;

CREATE ROLE review_reader LOGIN PASSWORD 'ReaderPass_ChangeMe_2026'
  NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION;

GRANT CONNECT ON DATABASE reviewdb TO review_reader;
GRANT USAGE ON SCHEMA review_app TO review_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA review_app TO review_reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA review_app GRANT SELECT ON TABLES TO review_reader;
EOF

PostgreSQL 官方文档里,CREATE ROLE 可以明确指定 LOGIN、NOSUPERUSER、NOCREATEDB、NOCREATEROLE 这些权限属性。这里把危险权限全部关掉,只保留登录和查询需要的权限。

注意:/docker-entrypoint-initdb.d 里的 SQL 只会在数据库数据目录首次初始化时执行。如果你已经启动过一次 PostgreSQL,再改初始化 SQL 不会自动重跑。测试阶段想重置环境,可以执行:

bash 复制代码
docker compose down -v
docker compose up -d

down -v 会删除 Compose 创建的数据卷,测试数据也会一起清掉。别在真实库上这么干,这一步只适合当前这种临时演示库。

5 启动服务,本地先确认管理台能打开

现在启动两个容器:

bash 复制代码
docker compose up -d

看一下状态:

bash 复制代码
docker compose ps

正常情况下能看到 pg-review-postgres 和 pg-review-pgadmin 都处于运行状态。如果 pgAdmin 还在启动中,等十几秒再刷新页面,它第一次初始化会比普通静态页面慢一点。

在局域网电脑上打开:

text 复制代码
http://NAS_IP:5050

把 NAS_IP 换成你的 NAS 地址,比如 192.168.1.20。登录账号使用刚才配置里的:

text 复制代码
admin@example.com
PgAdmin_ChangeMe_2026

图:局域网先通过 pgAdmin :5050 验收数据库

这一步应该看到 pgAdmin 的登录页和主界面。图里适合截两块:浏览器地址栏里的 :5050,以及 pgAdmin 登录后的首页。这样读者能一眼看懂:现在只是局域网访问,还没对外开放。

如果打不开,先查三件事:

bash 复制代码
docker compose ps
docker logs pg-review-pgadmin --tail=80
curl -I http://127.0.0.1:5050

curl 能返回 HTTP 响应,说明 pgAdmin 在 NAS 本机端口已经起来;局域网电脑打不开,多半是 NAS 防火墙、Docker 端口映射或访问地址填错。

6 在 pgAdmin 里添加 PostgreSQL 服务器

登录 pgAdmin 后,需要手动把 Docker 内网里的 PostgreSQL 加进去。

在左侧或首页找到添加服务器入口,填写这些信息:

text 复制代码
General / Name: review-postgres
Connection / Host name/address: postgres
Connection / Port: 5432
Connection / Maintenance database: reviewdb
Connection / Username: review_reader
Connection / Password: ReaderPass_ChangeMe_2026

这里最容易填错的是 Host。不要填 127.0.0.1,也不要填 NAS 的局域网 IP。pgAdmin 和 PostgreSQL 在同一个 Docker Compose 网络里,服务名 postgres 就是可解析的内网主机名。

为什么这一步用 review_reader,而不是 app_admin?因为验收只需要看表结构和跑查询,不需要建库、删表、改权限。把只读账号提前接好,同事拿到 Web 页面后也只能做只读验证。

连接成功后,展开:

text 复制代码
Servers → review-postgres → Databases → reviewdb → Schemas → review_app → Tables → orders

在 Query Tool 里执行:

sql 复制代码
SELECT id, order_no, customer_name, amount, status, created_at
FROM review_app.orders
ORDER BY id;

能看到 3 条测试订单,说明数据库、权限和 Web 管理台链路都通了。

再试一条写入语句验证只读限制:

sql 复制代码
UPDATE review_app.orders
SET status = 'CANCELLED'
WHERE order_no = 'T20260720002';

这条语句会被权限拒绝。这个报错是好事,说明只读账号没有被放大权限。验收前建议自己先跑一遍,别等同事打开页面才发现权限给多了或给少了。

7 用 cpolar 开临时 HTTPS 入口给同事验收

本地确认没问题后,再让外网同事访问。这里用 cpolar 开 HTTP 隧道,目标端口是 pgAdmin 的 5050。

Linux 环境可以使用官方一键安装脚本:

bash 复制代码
curl -L https://www.cpolar.com/static/downloads/install-release-cpolar.sh | sudo bash

安装完成后,先确认本机管理端口能打开:

bash 复制代码
cpolar version
curl -s http://127.0.0.1:9200 >/dev/null && echo "cpolar web ui ok"

cpolar 支持通过 Web UI 登录完成账号绑定,也支持命令行手动写入 authtoken。纯命令行环境可以执行:

bash 复制代码
cpolar authtoken YOUR_CPOLAR_AUTH_TOKEN

把 YOUR_CPOLAR_AUTH_TOKEN 换成你自己后台里的 token。这里不要把 token 发给同事,也不要写进公开仓库。

临时验收直接运行:

bash 复制代码
cpolar http 5050

命令输出里会出现公网访问地址,选择 https:// 开头的地址发给同事。免费随机地址适合这种短时演示,cpolar 已核对规则里免费套餐的随机公网地址会在 24 小时内变化,所以不要把它写进长期文档。

图:cpolar HTTPS 临时入口交付同事验收

这张图适合截 cpolar 输出的 HTTPS 地址,以及同事浏览器打开 pgAdmin 登录页的状态。注意截图时遮住邮箱、token、真实公网地址里的敏感片段,只保留能说明"HTTPS 临时入口已生成"的部分。

发给同事时,只给这几项:

text 复制代码
pgAdmin 临时地址:https://xxxx.cpolar.xxx
pgAdmin 登录账号:admin@example.com
pgAdmin 登录密码:PgAdmin_ChangeMe_2026
数据库连接名:review-postgres
可验收查询:SELECT * FROM review_app.orders ORDER BY id;

更稳一点的做法,是验收前把 pgAdmin 密码改成一次性的强密码,验收后再改掉或直接关闭容器。别把自己长期使用的 pgAdmin 管理员密码拿出来共享。

8 验收结束后怎么收口

同事确认能登录、能看表、能跑只读查询后,立刻关闭 cpolar 隧道。

如果你是在前台运行 cpolar http 5050,在终端按:

bash 复制代码
Ctrl+C

再确认外网地址打不开,pgAdmin 页面就不会继续暴露在公网入口上。

如果这套 PostgreSQL 和 pgAdmin 只是本次验收使用,也可以停掉容器:

bash 复制代码
docker compose down

如果连测试数据也不保留,执行:

bash 复制代码
docker compose down -v

再次提醒,down -v 会删除 PostgreSQL 数据卷。只要里面有任何需要留存的数据,就不要加 -v。

这里还有几个收口动作我建议固定做:

  • 删除或更换 pgAdmin 临时登录密码。
  • 确认没有在路由器、防火墙、NAS 控制台里额外开放 5432。
  • 如果测试库来自生产数据,验收前只保留脱敏字段,手机号、邮箱、地址、真实姓名不要原样放进去。

9 总结

这次我们做成的不是"把 PostgreSQL 放到公网",而是把 NAS 上的 pgAdmin Web 管理台临时拿出来给同事验收。数据库仍然待在 Docker 内网里,外部只通过 HTTPS 临时入口访问管理台,再用只读账号查看测试表。

关键步骤可以记成三件事:

  • PostgreSQL 不映射 5432,pgAdmin 映射到 NAS 的 5050。
  • 数据库里提前创建 review_reader,只给 CONNECT、USAGE 和 SELECT。
  • cpolar 只穿透 pgAdmin 的 Web 端口,验收结束马上关闭。

安全边界也别省:同事验收用脱敏测试库,不给超级管理员,不共享长期密码;生产环境使用正式远程接入方案、堡垒机或统一网关。临时演示就用临时入口,做完收口,这样既能让协作顺畅,也不会把数据库安全押在侥幸上。

相关推荐
姚远Oracle ACE9 小时前
为什么无法连接到 PostgreSQL?
数据库·postgresql
ss2739 小时前
AI时代首先数据库-PostgreSQL实战笔记 | 22 PostgreSQL实例与集群
数据库·笔记·postgresql
ss2739 小时前
AI时代首先数据库-PostgreSQL实战笔记 | 21 PostgreSQL进程与内存架构介绍
数据库·笔记·postgresql
云贝贝贝13 小时前
删了却没变小:PostgreSQL 死元组与表膨胀排查
数据库·postgresql
IvorySQL15 小时前
PostgreSQL 18 性能与执行计划新特性实测
数据库·postgresql
cpolar技术支持17 小时前
磁盘明明没满,服务却写不进去?做个 inode 与分区占用只读报表页,cpolar 给异地同事看
linux·内网穿透·cpolar·inode·运维排障
l1t21 小时前
DeepSeek总结的 PostgreSQL 中的二进制只读副本,第一部分
数据库·postgresql
longerxin20201 天前
Ubuntu 22.04 ARM64 云镜像开启 root 密钥登录(保留 ubuntu 密钥登录,禁止密码登录)
数据库·ubuntu·postgresql
YuanDaima20481 天前
系统架构与数据库理论基础:PostgreSQL 与 pgvector
数据库·人工智能·docker·postgresql·系统架构·产品经理
IvorySQL1 天前
PostgreSQL 日报|恢复期 COPY TO 未日志表修复(10 月 21 日)
数据库·postgresql·区块链