Docker 部署 PostgreSQL
1.实现内容
持久化存储:数据库的数据存储在 Docker 命名卷
postgres_data中,即使容器被删除或重启,所有数据都不会丢失,为博客内容提供稳定可靠的持久层。
安全传输与访问控制:
密码通过 Docker Secrets 机制以文件形式注入
(/run/secrets/postgres_password),彻底避免在环境变量或配置文件中明文硬编码,防止密码泄露。端口仅映射到宿主机的特定内网 IP(10.1.0.13:5432),限制数据库暴露范围,公网和其他非授权网络无法直接访问,显著缩小攻击面。
性能调优:根据中小型博客的负载特点,通过自定义启动参数对 PostgreSQL 进行针对性优化——包括 shared_buffers、max_connections、work_mem、effective_cache_size 等关键内存与连接参数,并开启 WAL 压缩,在内存 1-2GB 的 VPS 上也能获得流畅的响应体验。
高可用性保障:采用
unless-stopped重启策略,使容器在异常退出或 Docker 重启后自动恢复,无需人工干预。同时,内置基于 pg_isready 的健康检查,确保数据库真正完成初始化并能够接收连接后,才对外提供服务,可与编排工具配合实现可靠的服务依赖顺序。微服务集成:容器接入预先创建的外部网络
blog-network,与博客应用、缓存等其他微服务解耦连接,内部通过服务名直接通信,无需经由宿主机端口转发,既提升了通信效率,也增强了架构的整体性与扩展性。
2.执行流程
创建Docker网络 blog-network
创建密码文件 /opt/secrets/postgres-password.txt
创建YAML文件 docker-compose-postgresql.yaml
启动服务
# 创建 docker 网络
docker network create blog-network
# 创建 secrets 目录,并设置仅 root 可访问
sudo mkdir -p /opt/secrets
sudo chmod 700 /opt/secrets
# 交互式输入密码,不会在终端留下痕迹
sudo tee /opt/secrets/postgres-password.txt < /dev/null
# 收紧文件权限(600 = 仅 root 可读写)
sudo chmod 600 /opt/secrets/postgres-password.txt
# 启动服务
docker-compose -f docker-compose-postgresql.yaml up -d 3.YAML文件
# ================================================================
# Docker Compose 配置 PostgreSQL 17 数据库服务
# 功能:数据持久化、安全加固、性能调优、健康监控
# ================================================================
services:
postgres:
image: docker pull postgres:17.9 # 或使用私有仓库镜像
# 固定容器名称,带日期和生产标识,方便运维识别
container_name: testname
# 容器退出后总是自动重启(除非被手动 docker stop),保证数据库高可用
restart: unless-stopped
# 接入预先创建的独立 Docker 网络,用于与其他微服务内部通信
networks:
- blog-network
# 端口映射:仅将 5432 绑定到宿主机内网 IP 10.1.0.13,公网或其他网络无法直接访问,缩小攻击面
ports:
- "10.1.0.13:5432:5432"
# 挂载命名卷持久化数据库文件,即使容器被删除重建,数据也不会丢失
volumes:
- postgres_data:/var/lib/postgresql/data
# 引用 Docker Secret,将密码以文件形式安全挂载到容器内,避免在环境变量中明文出现
secrets:
- postgres_password
# 数据库初始化环境变量
environment:
POSTGRES_USER: testuser # 创建的超级用户
POSTGRES_DB: testdb # 初始化后自动创建的博客数据库
POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password # 从 Secret 挂载的文件读取密码,更安全
# 自定义 PostgreSQL 启动参数,针对小型博客场景(内存 ~1-2GB)进行适度调优
command:
[
"postgres",
"-c", "shared_buffers=256MB", # 共享内存缓冲区,约系统内存的 25%
"-c", "max_connections=50", # 最大并发连接数,防止资源耗尽
"-c", "work_mem=8MB", # 单个排序或哈希操作可使用内存
"-c", "maintenance_work_mem=128MB", # VACUUM、索引创建等维护操作内存
"-c", "autovacuum_work_mem=32MB", # 自动真空操作内存上限
"-c", "effective_cache_size=1GB", # 告知查询规划器操作系统可用于缓存的大小,优化索引扫描
"-c", "wal_compression=on" # 开启 WAL 日志压缩,降低磁盘 IO
]
# 健康检查:判断数据库是否真正准备好接受连接(比仅检查进程更可靠)
healthcheck:
test: ["CMD-SHELL", "pg_isready -U blogjob -d BLOGdb"]
interval: 10s # 每隔 10 秒执行一次检查
timeout: 5s # 单次检查若 5 秒无响应即视为失败
retries: 5 # 连续失败 5 次后标记为 unhealthy
start_period: 30s # 容器启动后预留 30 秒初始化时间,之后才开始健康检查
# -------------------- 全局资源声明 --------------------
secrets:
# 定义用于存储数据库密码的 secret,内容来自宿主机文件(需提前创建,权限最好设为 600)
postgres_password:
file: /opt/secrets/postgres-password.txt
volumes:
# 声明名为 postgres_data 的持久化卷,由 Docker 自动管理,不随容器删除而消失
postgres_data:
networks:
# 声明引用的外部网络,管理员须先执行:docker network create blog-network
blog-network:
external: true