🐘 使用 Docker 快速部署与加固 PostgreSQL 数据库

摘要:本文详细介绍如何使用官方容器镜像快速部署 PostgreSQL 数据库,包括镜像下载、启动命令、持久化设置、健康检查、以及密码加固与认证机制说明。


一、镜像下载与来源

官方镜像地址:
👉 https://hub.docker.com/_/postgres

拉取命令:

# 推荐使用指定版本,保证环境一致性
docker pull postgres:17

# 或者拉取最新版本(不推荐生产环境使用)
docker pull postgres:latest

二、准备持久化目录

为了防止容器删除后数据丢失,需将数据库目录映射到宿主机:

mkdir -p /opt/pgdata
# 或者使用 Docker 卷
docker volume create pgdata

三、快速启动 PostgreSQL 容器

3.1 使用主机目录持久化

docker run -d --name pg17   -e POSTGRES_USER=appuser   -e POSTGRES_PASSWORD='StrongPassw0rd!'   -e POSTGRES_DB=appdb   -e TZ=Asia/Shanghai   -p 5432:5432   -v /opt/pgdata:/var/lib/postgresql/data   --health-cmd="pg_isready -U appuser -d appdb || exit 1"   --health-interval=10s --health-timeout=5s --health-retries=5   postgres:17

3.2 使用 Docker 卷持久化

docker run -d --name pg17   -e POSTGRES_USER=appuser   -e POSTGRES_PASSWORD='StrongPassw0rd!'   -e POSTGRES_DB=appdb   -e TZ=Asia/Shanghai   -p 5432:5432   -v pgdata:/var/lib/postgresql/data   postgres:17

✅ 建议首次初始化时添加字符集参数:

-e POSTGRES_INITDB_ARGS="--encoding=UTF8 --lc-collate=zh_CN.UTF-8 --lc-ctype=zh_CN.UTF-8"

四、Docker Compose 部署(推荐)

docker-compose.yml 示例:

services:
  postgres:
    image: postgres:17
    container_name: pg17
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD: StrongPassw0rd!
      POSTGRES_DB: appdb
      TZ: Asia/Shanghai
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser -d appdb || exit 1"]
      interval: 10s
      timeout: 5s
      retries: 5

volumes:
  pgdata:

启动命令:

docker compose up -d

五、连接与验证

5.1 查看容器状态

docker ps --filter name=pg17
docker logs -f pg17

5.2 容器内验证

docker exec -it pg17 bash
psql -U appuser -d appdb -c "SELECT version();"
psql -U appuser -d appdb -c "CREATE TABLE t1(id int primary key, v text);"
psql -U appuser -d appdb -c "INSERT INTO t1 VALUES (1,'ok');"
psql -U appuser -d appdb -c "SELECT * FROM t1;"

5.3 宿主机验证

psql "postgresql://appuser:StrongPassw0rd!@127.0.0.1:5432/appdb" -c "SELECT now();"

六、为什么不用密码也能连接?

PostgreSQL 的密码验证规则由 pg_hba.conf 控制。容器初始化时可能设置了:

local   all             all                                     trust

这会导致 本地 Unix socket 连接免密
要强制所有连接必须密码验证,请执行以下步骤:

6.1 查看当前配置文件路径

docker exec -it pg17 psql -U appuser -d appdb -c "SHOW hba_file;"

6.2 修改认证策略

docker exec -it pg17 bash
cat >/var/lib/postgresql/data/pg_hba.conf <<'HBA'
# TYPE  DATABASE        USER            ADDRESS                 METHOD
local   all             all                                     scram-sha-256
host    all             all             127.0.0.1/32            scram-sha-256
host    all             all             ::1/128                 scram-sha-256
host    all             all             0.0.0.0/0               scram-sha-256
host    all             all             ::0/0                   scram-sha-256
HBA
exit

docker exec -it pg17 psql -U appuser -d appdb -c "SELECT pg_reload_conf();"

重新测试后应提示输入密码:

psql -h 127.0.0.1 -U appuser -d appdb -W -c "SELECT now();"

⚠️ 如果你的 pg_hba.conftrustpeer,任何本地连接可能都不需要密码。


七、安全强化建议

类别 建议措施
认证 全部改用 scram-sha-256
密码 不使用默认密码;设置复杂度高的密码
网络 仅暴露 5432 给可信来源
数据 使用卷或目录持久化 /var/lib/postgresql/data
日志 定期查看 pg_log 与容器日志
备份 定期 pg_dump + 远程存储
初始化 禁止使用 POSTGRES_HOST_AUTH_METHOD=trust

八、备份与恢复

导出

docker exec -t pg17 pg_dump -U appuser appdb > appdb_$(date +%F).sql

恢复

cat appdb_2025-11-15.sql | docker exec -i pg17 psql -U appuser -d appdb

九、查看当前认证方式

docker exec -it pg17 psql -U appuser -d appdb -c "
SELECT type, database, user_name, address, auth_method
FROM pg_hba_file_rules
WHERE error IS NULL
ORDER BY line_no;"

🔚 总结

  • 你无需密码可能是因为 pg_hba.conftrustpeer 认证;
  • 正确加固应使用 scram-sha-256
  • 容器参数的 POSTGRES_PASSWORD 仅在第一次初始化时生效;
  • 若数据目录复用旧实例,需手动修改 pg_hba.conf 才能强制密码登录。

一句话总结:

Postgres 容器初始化后若想强制密码认证,必须修改 pg_hba.confpg_reload_conf()

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐