PostgreSQL 17 + pgvector + pg_jieba + pg_textsearch,多阶段构建,面向所有 CPU 通用,不依赖任何外部数据。
镜像构建 + 启动严格遵守以下三条:
CPU_PORTABLE_BUILD=true 触发镜像内 portable rebuild:使用通用 CFLAGS(-march=x86-64/-march=armv8-a + -mtune=generic + -fno-tree-vectorize/-fno-tree-loop-vectorize/-fno-tree-slp-vectorize),避免 Illegal instruction。该 ARG 只控制 CPU 适配,不影响扩展是否安装/启用。pgvector / pg_textsearch / pg_jieba / pg_trgm / unaccent / ltree / hstore / pg_stat_statements 全部默认安装并在 template1 上 CREATE EXTENSION,业务库(含未来 CREATE DATABASE 创建的新库)自动继承。CPU_PORTABLE_BUILD=true 时只 git clone pgvector 源码)。运行期不再 bind-mount 任何 host 路径用于初始化(jieba 词典、init SQL、entrypoint 全部内置进镜像)。首启只做 initdb + 在 template1 创建扩展 + 创建 POSTGRES_DB(TEMPLATE template1)。没有 schema 自动导入,没有 bundle 自动导入。如需把外部 dump 导进数据库,使用 /usr/local/bin/import-migrate.sh,显式触发。
| 文件 | 作用 |
|---|---|
Dockerfile | 多阶段:vector-builder 重编 pgvector → 运行镜像复制内置资产 |
docker-compose.yml | 主部署文件,已挂载 /tmp/migrate -> /migrate:ro |
docker-compose.jieba-test.yml | 第二实例,端口 55432,独立 data 目录 |
scripts/entrypoint.sh | 启动脚本(initdb + 扩展,无业务数据) |
scripts/process-init-files.sh | /docker-entrypoint-initdb.d/ 调度 |
scripts/import-migrate.sh | 显式导入 /migrate/*.{dump,sql,sql.gz,sql.xz} |
init/001_extensions.sql | 仅 CREATE EXTENSION |
conf/postgresql.conf | 启动配置模板 |
jieba/dicts/novel_analyzer.dict | 唯一保留的用户词典 |
build_pgsql.sh | 裸机/VM 全量编译脚本(与 Dockerfile 同样的 portable CFLAGS) |
verify-running.sh / check-pg-capabilities.sh | 健康自检 |
POSTGRES_USER d2
POSTGRES_PASSWORD d2pass
POSTGRES_DB d2
PGPORT 5432
可通过 compose environment: 或 .env 覆盖。
cd /home/user/pgsql17-ubuntu24
bash build-and-up.sh
仅查看计划:
DRY_RUN=true bash build-and-up.sh
docker exec -it d2-pg17 /opt/postgresql/bin/psql -U d2 -d d2
SELECT extname FROM pg_extension ORDER BY extname;
预期至少包含:pg_textsearch、pg_jieba、vector、pg_trgm、unaccent、ltree、hstore、pg_stat_statements。
docker-compose.yml 已默认挂载:
volumes:
- /tmp/migrate:/migrate:ro
容器启动不会自动导入,需要显式执行:
# 导入全部支持的文件(按 *.sql -> *.sql.gz -> *.sql.xz -> *.dump 顺序)
docker exec -it d2-pg17 import-migrate.sh
# 只导一个文件(相对 /migrate 或绝对路径都行)
docker exec -it d2-pg17 import-migrate.sh novel_analyzer.dump
# 指定目标库
docker exec -it d2-pg17 import-migrate.sh -d d2 novel_analyzer.sql.gz
支持格式:
| 格式 | 处理方式 |
|---|---|
*.dump | pg_restore --no-owner --no-privileges --exit-on-error |
*.sql | psql -f |
*.sql.gz / *.sql.xz | 解压后管道喂给 psql |
*.tar.gz / *.tar | 忽略(视为数据集而非 DB dump) |
提示:
/tmp/migrate/novel_analyzer.dump是 PostgreSQL 17.5 自定义格式 dump,已用 pg_jieba/pg_textsearch/vector 扩展,导入前确保扩展已创建。
镜像只保留 novel_analyzer.dict(构建期复制到 /opt/pg_jieba/dicts/,启动时同步到 /opt/postgresql/share/tsearch_data/)。
如需新增用户词典:
*.dict 放进 jieba/dicts/PG_JIEBA_USER_DICT 中加入文件名(去掉 .dict)之前现象:
server process was terminated by signal 4: Illegal instruction
根因:上游预编译的 vector.so 带宿主机指令集优化(AVX2 / AVX-512),跑在不支持的 CPU 上就会 SIGILL。
CPU_PORTABLE_BUILD 这个 ARG 控制的是是否在镜像里以 portable CFLAGS 重新编译科学计算扩展(当前是 pgvector;未来若新增其它带 SIMD 的扩展会一并走这个分支)。它只关 CPU 适配,扩展始终默认安装并启用。
直接复用 base image 自带的二进制:
COPY)docker-compose build --build-arg CPU_PORTABLE_BUILD=true
# 或一次性环境变量
CPU_PORTABLE_BUILD=true bash build-and-up.sh
构建期 git clone pgvector ${PGVECTOR_VERSION},使用通用 CFLAGS:
make PG_CONFIG=/opt/postgresql/bin/pg_config OPTFLAGS="" \
PG_CFLAGS="-march=x86-64 -mtune=generic -O2 \
-fno-tree-vectorize -fno-tree-loop-vectorize -fno-tree-slp-vectorize"
aarch64 自动切 -march=armv8-a。
| 场景 | 主要瓶颈 | native 相比 portable | 备注 |
|---|---|---|---|
| 高维稠密向量距离(dim ≥ 768,BGE-M3=1024,OpenAI=1536) | SIMD 累加(dot / sqdiff) | 2.0-4.0x(AVX-512 上限更高) | pgvector 最热的内循环 |
| HNSW 批量建索引 | 反复距离计算 | 1.5-3.0x | 大批量入库时受益最明显 |
| HNSW / IVFFlat 在线 ANN 查询 | 距离 + 索引遍历 | 1.2-2.0x 端到端 | 索引开销稀释了 SIMD 收益 |
| 低维(dim ≤ 128)或低 QPS | I/O / 元组扫描 | < 1.1x(基本无差) | SIMD 不是瓶颈 |
何时考虑放开 native(额外加 -march=native,目前未实现,按需扩展):
保持 portable 的原因:
CPU_PORTABLE_BUILD=true,编出的 vector.so 也是 portable 的,性能与 base image 内置版本几乎一致——它解决的是「能跑」而非「跑得快」。build_pgsql.sh 走完全相同的 portable CFLAGS 路径。
docker-compose down
| Tag | Build 模式 | 适用机器 |
|---|---|---|
registry.cn-chengdu.aliyuncs.com/rapid7/pgsql17-ubuntu24-pg17:v2 | CPU_PORTABLE_BUILD=false(默认 base) | 与 base image 构建机指令集兼容(含 AVX2/AVX-512 等)的现代 x86_64 |
registry.cn-chengdu.aliyuncs.com/rapid7/pgsql17-ubuntu24-pg17:v2-i7-8865u | CPU_PORTABLE_BUILD=true(portable rebuild) | 老 CPU / 缺 SIMD(如 i7-8865U / Whiskey Lake、轻量虚机、ARM 机器)—— 跑默认 v2 出现 Illegal instruction 时换这个 |
拉镜像(无脑选):先试 :v2,启动后 CREATE EXTENSION vector 报 Illegal instruction 就改用 :v2-i7-8865u。
或者先用 verify-image.sh 验过:
sudo docker pull registry.cn-chengdu.aliyuncs.com/rapid7/pgsql17-ubuntu24-pg17:v2
bash scripts/verify-image.sh registry.cn-chengdu.aliyuncs.com/rapid7/pgsql17-ubuntu24-pg17:v2
bash verify-running.sh
bash check-pg-capabilities.sh
scripts/verify-image.sh 会拉起一个临时容器对指定镜像跑 25 项端到端检查(扩展存在性 + 行为 + template1 继承 + 镜像内置资产 + import 工具),自动清理。
# 默认校验本地构建镜像
bash scripts/verify-image.sh
# 校验远端镜像(先 pull)
sudo docker pull registry.cn-chengdu.aliyuncs.com/rapid7/pgsql17-ubuntu24-pg17:v2
bash scripts/verify-image.sh registry.cn-chengdu.aliyuncs.com/rapid7/pgsql17-ubuntu24-pg17:v2
# 自定义端口(避开 5432 占用)
HOST_PORT=15433 bash scripts/verify-image.sh
预期输出末尾:
PASS=25 FAIL=0
all checks passed
校验项覆盖:
vector / pg_textsearch / pg_jieba / pg_trgm / unaccent / ltree / hstore / pg_stat_statements 全部 pg_extension 中可见pg_jieba.user_dict=novel_analyzer 装载template1 已开启扩展,新建 DB 自动继承/opt/pg_jieba/dicts/ 镜像内只剩 novel_analyzer.dict/usr/local/bin/import-migrate.sh 存在且 --help 正常shared_preload_libraries 含 pg_jieba