PostgreSQL 是一款开源免费的高级关系型数据库管理系统,始于 1986 年,由全球开发者社区持续维护迭代,兼具悠久历史与前沿特性。它严格遵循 ACID 事务原则,确保数据读写的一致性与可靠性,同时突破传统关系型数据库局限,支持多模型存储——既能兼容标准 SQL,又可高效处理 JSON、数组、地理空间(GIS)等复杂数据类型。
其核心优势在于极强的扩展性:可通过自定义函数、存储过程及丰富插件(如 PostGIS 用于地理信息分析)拓展功能,适配从中小型应用到企业级海量数据场景(如电商交易、日志分析、科学计算)。此外,它采用多版本并发控制(MVCC)优化高并发读写性能,内置数据加密、访问控制等安全机制,是平衡功能深度、稳定性与运维友好性的主流开源数据库优选。
🧰 准备工作
若你的系统尚未安装 Docker,请先一键安装:
Linux Docker & Docker Compose 一键安装
一键安装配置脚本(推荐方案):
该脚本支持多种 Linux 发行版,支持一键安装 Docker、Docker Compose 并自动配置轩辕镜像访问支持源。
bash <(wget -qO- https://xuanyuan.cloud/docker.sh)
1、查看 PostgreSQL 镜像详情
你可以在 轩辕镜像 中找到 PostgreSQL 镜像页面:👉 https://xuanyuan.cloud/r/library/postgres
在镜像页面中,你会看到多种拉取方式,下面逐一说明如何下载与部署(生产环境务必使用明确版本号,禁止直接使用 latest)。
2、下载 PostgreSQL 镜像
2.1 版本选择说明
镜像标签
适用场景
风险提示
postgres:latest
测试/学习
版本不固定,大版本升级可能导致数据不可用
postgres:16
生产环境推荐
稳定版本,兼容当前主流应用,升级需按官方流程
postgres:15
生产环境备选
长期支持版本,适合需要稳定性的 legacy 系统
2.2 使用轩辕镜像登录验证方式拉取
# 生产推荐(指定 16 版本)docker pull xxx.xuanyuan.run/library/postgres:16
2.3 拉取后改名(保持与官方镜像命名一致)
# 生产推荐(16 版本)docker pull xxx.xuanyuan.run/library/postgres:16 \&& docker tag xxx.xuanyuan.run/library/postgres:16 library/postgres:16 \&& docker rmi xxx.xuanyuan.run/library/postgres:16
说明:
- • docker pull:从轩辕镜像访问支持拉取
- • docker tag:重命名为 library/postgres:16,统一镜像引用方式
- • docker rmi:删除临时标签,避免重复占用空间
2.4 免登录方式拉取(推荐,无需配置账户)
# 生产推荐(16 版本)docker pull xxx.xuanyuan.run/library/postgres:16
带重命名的完整命令:
docker pull xxx.xuanyuan.run/library/postgres:16 \&& docker tag xxx.xuanyuan.run/library/postgres:16 library/postgres:16 \&& docker rmi xxx.xuanyuan.run/library/postgres:16
2.5 官方直连方式(网络支持时使用)
若网络可直连 Docker Hub,或已配置加速器,可直接:
# 测试用docker pull postgres:latest# 生产推荐docker pull postgres:16
2.6 查看镜像是否拉取成功
docker images
输出类似(生产环境应显示明确版本号):
REPOSITORY TAG IMAGE ID CREATED SIZEpostgres 16 5d2f9e78c6f1 2 weeks ago 374MB
3、部署 PostgreSQL
以下示例按「测试 → 准生产 → 企业级」分类,生产环境请优先选择 3.2 或 3.3 方案,并补充安全配置。
3.1 快速部署(✅ 测试/学习专用,禁止生产使用)
适合快速验证功能,数据不持久化,重启后丢失:
docker run -d --name pg-test \ -e POSTGRES_PASSWORD=StrongTestPass123! \ # 测试用强密码示例 -p 5432:5432 \ library/postgres:latest # 仅测试使用 latest
参数说明:
- • --name pg-test:容器名称
- • -e POSTGRES_PASSWORD=StrongTestPass123!:设置 postgres 超级用户密码(必填,测试也建议用强密码)
- • -p 5432:5432:将宿主机端口映射到容器 5432 端口
验证方式:
docker exec -it pg-test psql -U postgres
若成功进入 psql 命令行,说明部署完成。
3.2 挂载数据目录(⚠️ 准生产方案,需补充安全配置)
该方式解决了数据持久化问题,是生产环境的基础形态。必须补充版本锁定、密码管理、网络隔离、资源限制等安全措施后,方可用于真实生产环境。
第一步:创建宿主机目录并配置权限
PostgreSQL 容器内部使用 UID 999、GID 999 的 postgres 用户运行进程,宿主机目录需授权该用户可读写:
# 创建目录mkdir -p /data/postgres/{data,logs}# 配置权限(关键步骤,避免启动失败)chown -R 999:999 /data/postgreschmod -R 700 /data/postgres # 严格限制目录权限,仅所有者可访问
第二步:启动容器并挂载目录(生产推荐 16 版本)
docker run -d --name pg-web \ -e POSTGRES_PASSWORD=ComplexProdPass_2024! \ # 生产级强密码(字母+数字+特殊字符) -e POSTGRES_USER=appuser \ # 非默认超级用户,降低权限风险 -e POSTGRES_DB=appdb \ # 预先创建业务数据库,避免使用默认库 -e TZ=Asia/Shanghai \ # 指定时区,避免时间不一致问题 -p 127.0.0.1:5432:5432 \ # 仅本地监听,禁止公网直接访问(生产核心安全配置) --restart always \ # 容器异常自动重启 --memory 2G \ # 限制最大内存(根据服务器配置调整) --cpus 1 \ # 限制 CPU 核心数(根据服务器配置调整) -v /data/postgres/data:/var/lib/postgresql/data \ # 核心数据目录(必须挂载) library/postgres:16 # 生产环境锁定 16 版本
目录说明(官方镜像标准路径)
宿主机目录
容器目录
说明
是否必选
/data/postgres/data
/var/lib/postgresql/data
核心数据目录(含配置文件)
是
/data/postgres/logs
/var/log/postgresql
日志目录(需手动配置)
否
⚠️ 重要说明:
- 1. 官方 PostgreSQL 镜像的配置文件(postgresql.conf、pg_hba.conf)默认存储在
$PGDATA(即 /var/lib/postgresql/data)目录下,而非 /etc/postgresql(该路径为 Debian 系统原生安装路径,容器镜像不适用);- 2. 日志默认输出到 stdout,推荐通过 Docker 日志驱动收集(如 json-file、loki),而非直接挂载文件目录。
3.3 docker-compose 部署(🏭 企业级参考方案,需根据业务调整)
统一管理配置与容器,支持一键启动、集群扩展,适合生产环境规模化部署。
第一步:编写 docker-compose.yml(生产级配置)
version: '3.8' # 明确 Compose 版本services: postgres: image: library/postgres:16 # 锁定生产版本 container_name: pg-service restart: always # 异常自动重启 environment: POSTGRES_USER: ${DB_USER} # 从 .env 文件读取,避免明文 POSTGRES_PASSWORD: ${DB_PASSWORD} POSTGRES_DB: ${DB_NAME} TZ: Asia/Shanghai PGDATA: /var/lib/postgresql/data # 明确数据存储路径 ports: - "127.0.0.1:5432:5432" # 仅本地监听,通过应用或代理访问 volumes: - ./data:/var/lib/postgresql/data # 数据持久化 # - ./init-scripts:/docker-entrypoint-initdb.d # 初始化脚本目录(可选) deploy: resources: limits: cpus: '2' # 限制 CPU 使用率 memory: 4G # 限制最大内存 healthcheck: # 健康检查(生产必备) test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"] interval: 10s timeout: 5s retries: 3 networks: - app-network # 自定义网络,隔离其他服务networks: app-network: driver: bridge # 生产可替换为 overlay 网络(集群场景)
第二步:创建 .env 文件(密码管理,避免明文暴露)
在 docker-compose.yml 同级目录创建 .env 文件:
# .env 文件(需设置权限 chmod 600,仅所有者可读)DB_USER=appadminDB_PASSWORD=StrongProdPass@2024#DB_NAME=businessdb
第三步:启动服务
# 创建数据目录并授权mkdir -p ./data && chown -R 999:999 ./data && chmod 700 ./data# 启动容器(后台运行)docker compose up -d# 查看启动状态docker compose ps
补充说明:
- • 初始化脚本:若需启动时自动执行 SQL(如创建表、授权),可在 ./init-scripts 目录下放置 .sql 或 .sh 文件,容器启动时会自动执行;
- • 配置修改:直接编辑 ./data/postgresql.conf 和 ./data/pg_hba.conf,修改后需重启容器生效;
- • 网络隔离:通过自定义网络 app-network 隔离数据库服务,仅允许同网络内的应用访问。
4、结果验证
查看容器状态
# 普通部署docker ps | grep postgres# docker-compose 部署docker compose ps
应看到容器状态为 Up(健康检查通过会显示 healthy)。
进入 PostgreSQL 命令行
# 普通部署(pg-web 为容器名)docker exec -it pg-web psql -U appuser -d appdb# docker-compose 部署docker compose exec postgres psql -U ${DB_USER} -d ${DB_NAME}
创建测试表验证功能
CREATE TABLE test(id SERIAL PRIMARY KEY, name TEXT, create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP);INSERT INTO test(name) VALUES('Hello PostgreSQL!');SELECT * FROM test;
输出如下结果即表示数据库可用:
id | name | create_time----+--------------------+---------------------------- 1 | Hello PostgreSQL! | 2024-05-20 10:00:00+08(1 row)
5、生产环境关键配置补充(🏭 必看)
5.1 远程访问配置(⚠️ 严格限制访问范围)
默认配置仅允许本地访问,若需跨服务器访问(如应用与数据库分离),需修改配置文件,禁止直接开放 0.0.0.0/0:
第一步:修改 postgresql.conf
# 进入数据目录cd /data/postgres/data# 编辑配置文件(开启远程监听)sed -i 's/^listen_addresses = .*/listen_addresses = '*'/' postgresql.conf
第二步:修改 pg_hba.conf(限定内网网段)
# 编辑访问控制文件vi /data/postgres/data/pg_hba.conf# 添加内网网段授权(示例:允许 172.18.0.0/16 网段访问)echo "host all all 172.18.0.0/16 md5" >> pg_hba.conf
🚫 高危警告:
禁止添加host all all 0.0.0.0/0 md5(全网开放),若需公网访问,必须通过 VPN、反向代理或云数据库网关,同时启用 SSL 加密。
第三步:重启容器
docker restart pg-web # 普通部署# 或docker compose restart postgres # Compose 部署
5.2 密码安全优化
-
1. 定期更换密码:
进入容器执行docker exec -it pg-web psql -U postgresALTER USER appuser WITH PASSWORD 'NewStrongPass2024!';
-
2. 生产环境推荐使用 Docker Secrets 或云厂商密钥管理服务(如 AWS Secrets Manager),避免 .env 文件泄露。
5.3 日志配置(容器化最佳实践)
推荐使用 Docker 日志驱动收集日志,而非文件挂载:
# 启动时指定日志驱动(示例:json-file 并限制大小)docker run -d --name pg-web \ --log-driver json-file \ --log-opt max-size=10m \ --log-opt max-file=3 \ # 其他参数... library/postgres:16
如需输出日志到文件,需修改 postgresql.conf:
# 进入数据库执行ALTER SYSTEM SET logging_collector = on;ALTER SYSTEM SET log_directory = '/var/log/postgresql';ALTER SYSTEM SET log_filename = 'postgresql-%Y-%m-%d.log';ALTER SYSTEM SET log_rotation_age = '1d';ALTER SYSTEM SET log_rotation_size = '100MB';SELECT pg_reload_conf(); # 无需重启生效
5.4 备份策略(生产必备)
手动备份示例:
# 全量备份(推荐每日执行)docker exec pg-web pg_dump -U appuser -d appdb -F c -f /var/lib/postgresql/data/backup_$(date +%Y%m%d).dump# 复制备份文件到宿主机docker cp pg-web:/var/lib/postgresql/data/backup_20240520.dump /data/backups/
定时备份(使用 crontab):
# 编辑定时任务crontab -e# 添加每日凌晨 2 点备份(需替换容器名、用户名、数据库名)0 2 * * * docker exec pg-web pg_dump -U appuser -d appdb -F c -f /var/lib/postgresql/data/backup_$(date +%Y%m%d).dump && docker cp pg-web:/var/lib/postgresql/data/backup_$(date +%Y%m%d).dump /data/backups/ && find /data/backups/ -name "backup_*.dump" -mtime +7 -delete
6、常见问题排查
6.1 容器启动失败(日志显示权限错误)
原因:宿主机数据目录权限不足,容器内 postgres 用户(UID 999)无法读写。
解决:
chown -R 999:999 /data/postgreschmod -R 700 /data/postgres
6.2 无法连接数据库(应用或客户端报错)
-
1. 检查端口是否放行:
查看 5432 端口监听状态netstat -tulpn | grep 5432# 防火墙放行(仅内网环境)firewall-cmd --add-port=5432/tcp --permanent && firewall-cmd --reload
-
2. 检查 pg_hba.conf 配置:确保客户端 IP 在授权网段内;
-
3. 查看容器日志排查:
docker logs pg-web # 普通部署# 或docker compose logs postgres # Compose 部署
6.3 数据库时区不正确
解决:启动时添加时区环境变量:
-e TZ=Asia/Shanghai
已启动的容器可通过以下方式修改:
ALTER SYSTEM SET timezone = 'Asia/Shanghai';SELECT pg_reload_conf();
6.4 大版本升级(如 15 → 16)
⚠️ 重要提醒:PostgreSQL 大版本升级不可直接替换镜像版本,数据目录不兼容,需通过 pg_dump 备份 + 恢复 或 pg_upgrade 工具迁移。
示例流程(15 → 16):
-
1. 备份 15 版本数据:
docker exec pg-v15 pg_dumpall -U postgres -f /data/backup/all_dump.sql
-
2. 停止并删除 15 版本容器:
docker stop pg-v15 && docker rm pg-v15
-
3. 启动 16 版本容器(新数据目录):
docker run -d --name pg-v16 -e POSTGRES_PASSWORD=xxx -v /data/postgres-v16:/var/lib/postgresql/data library/postgres:16
-
4. 恢复数据到 16 版本:
docker cp /data/backup/all_dump.sql pg-v16:/tmp/docker exec pg-v16 psql -U postgres -f /tmp/all_dump.sql
6.5 日志文件过大
解决:启用日志轮转(参考 5.3 日志配置),或使用 logrotate 管理宿主机日志文件:
# 创建 logrotate 配置文件vi /etc/logrotate.d/postgres# 配置内容/data/postgres/logs/*.log { daily rotate 7 compress missingok notifempty create 0600 999 999 # 保持权限一致}
7、可选优化(提升专业度与安全性)
7.1 为什么不推荐 root 用户跑数据库?
- 1. 权限过大:容器内 root 用户可操作宿主机资源,存在安全风险;
- 2. 数据安全:意外操作(如 rm -rf)可能直接删除宿主机数据;
- 3. 符合最小权限原则:PostgreSQL 官方镜像默认使用非 root 用户,降低攻击面。
7.2 Docker Volume vs Bind Mount(数据挂载选择)
挂载方式
优点
缺点
适用场景
Bind Mount(宿主机目录)
直接访问文件,备份方便
权限配置复杂,跨平台兼容差
生产环境(可控服务器)
Docker Volume
权限自动管理,跨平台兼容
文件路径隐藏,需通过 docker volume 命令管理
测试/集群环境
7.3 PostgreSQL 在容器中与 K8s 的差异
- • 容器部署:适合中小规模应用,配置简单,运维成本低;
- • K8s 部署:适合大规模、高可用场景,支持自动扩缩容、滚动更新、StatefulSet 持久化,但需额外配置 PV/PVC、ConfigMap、Secret 等资源。
结尾
至此,你已掌握 PostgreSQL Docker 从测试到准生产的完整部署流程,包括镜像版本选择、数据持久化、安全配置、备份策略与问题排查。
- • 初学者:使用「3.1 快速部署」验证功能,熟悉 PostgreSQL 基础操作;
- • 中小团队:基于「3.2 挂载数据目录」或「3.3 docker-compose 部署」,补充权限控制、网络隔离、定时备份,即可满足大部分生产需求;
- • 企业级场景:需进一步探索主从复制、读写分离、SSL 加密、监控告警(如 Prometheus + Grafana)等进阶功能,结合业务需求优化配置。
始终牢记:生产环境无小事,版本锁定、权限最小化、数据备份、网络隔离是数据库安全的四大基石,切勿直接将测试配置用于真实业务场景。