PostgreSQL 18.6 Docker Compose 部署指南

使用 Docker Compose 一键部署 PostgreSQL 18.6(官方镜像 `postgres:18.6`),涵盖数据目录持久化、常用环境变量与参数配置(`-c` 传参)、健康检查,并给出等价的 `docker run` 运行方式。本文档已在 `/opt/data/ops/postgresql` 目录实测通过

PostgreSQLPostgreSQL安装部署容器化2026/09/27

PostgreSQL 18.6 Docker Compose 部署指南

目标:使用 Docker Compose 一键部署 PostgreSQL 18.6(官方镜像 postgres:18.6),涵盖数据目录持久化、常用环境变量与参数配置(-c 传参)、健康检查,并给出等价的 docker run 运行方式。本文档已在 /opt/data/ops/postgresql 目录实测通过。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS
  • 系统架构:x86_64
  • Docker 版本:Docker Engine 27.x(含 Compose v2 插件)
  • 镜像版本:postgres:18.6(与《Ubuntu 22.04 安装 PostgreSQL 18 指南》版本一致)
  • 容器名称:postgres-18-6
  • 端口映射:宿主机 15432 → 容器 5432
  • 数据目录:宿主机 /opt/data/ops/postgresql/data(挂载到容器 /var/lib/postgresql)
  • 部署文件:/opt/data/ops/postgresql/docker-compose.yaml

二、镜像选型说明

镜像标签对应版本特点
postgres:18.6PostgreSQL 18.6(当前最新稳定版)含全部小版本安全修复,支持新特性
postgres:18PostgreSQL 18 系列最新小版本会跟随上游小版本自动变化
postgres:latest最新稳定版(当前指向 18.x)版本会随上游变化,不建议生产锁定

💡 说明:官方镜像仓库为 docker.io/library/postgres。国内拉取可配置阿里云 / daocloud 镜像加速器,或通过中转节点拉取后 docker load 导入宿主机(本文档实测即采用此方式,镜像已 load 到宿主机)。

三、前置条件

  • 已安装 Docker Engine 与 Docker Compose 插件:docker --version && docker compose version
  • 已规划数据目录(建议放在独立磁盘,避免系统盘被数据占满)
  • 已准备好强密码(禁止使用默认/弱密码,见"六、常用环境变量表"章节)

四、部署步骤

4.1 创建部署目录

sudo mkdir -p /opt/data/ops/postgresql
cd /opt/data/ops/postgresql

4.2 编写 docker-compose.yaml

将以下内容保存为 /opt/data/ops/postgresql/docker-compose.yaml:

# =============================================================================
# PostgreSQL 18.6 Docker Compose 部署文件
# 镜像版本:postgres:18.6(与《Ubuntu 22.04 安装 PostgreSQL 18 指南》版本一致)
# 使用方式:cd /opt/data/ops/postgresql && docker compose up -d
# 密码等敏感值通过环境变量注入,请先 export(见文档"六、常用环境变量表"章节)
# =============================================================================

services:
  postgres:
    # 镜像版本:18.6 官方镜像
    image: postgres:18.6

    # 容器名称,方便 docker ps / docker logs 定位
    container_name: postgres-18-6

    # 重启策略:容器异常退出时自动重启(除非手动 stop)
    restart: unless-stopped

    # ---- 常用环境变量配置(值由外部环境变量注入)----
    environment:
      - TZ=Asia/Shanghai                        # 容器时区(与宿主机一致)
      - POSTGRES_USER=${POSTGRES_USER:-app_user}      # 超级用户(默认 app_user)
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?请在环境变量中设置} # 超级用户密码
      - POSTGRES_DB=${POSTGRES_DB:-app_db}            # 自动创建的默认数据库

    # ---- 常用配置参数(-c 等价于写进 postgresql.conf)----
    # 说明:参数已统一放入 ./conf/postgresql.conf(见下方 volumes 挂载),
    # 修改配置只需编辑该文件后 docker compose restart postgres,无需改 yaml
    command:
      - "-c"
      - "config_file=/etc/postgresql/postgresql.conf"   # 使用自定义配置文件(完整替换默认 conf)

    # ---- 端口映射:宿主机15432 -> 容器5432 ----
    ports:
      - "15432:5432"

    # ---- 数据持久化(重要)----
    # 18+ 官方镜像使用 pg_ctlcluster 布局(数据在 /var/lib/postgresql/<版本>/<集群名>),
    # 必须挂载父目录 /var/lib/postgresql,否则容器启动报错
    volumes:
      - ./data:/var/lib/postgresql
      # ---- 配置文件持久化(重要)----
      # ./conf 为宿主机配置目录,挂载到 /etc/postgresql,
      # 通过 -c config_file 指定使用该配置文件,编辑后 docker compose restart postgres 生效
      - ./conf:/etc/postgresql

    # ---- 健康检查:容器内 pg_isready 判断数据库就绪 ----
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"]
      interval: 10s      # 每 10 秒检查一次
      timeout: 5s        # 单次检查超时
      retries: 10        # 连续 10 次失败视为不健康
      start_period: 30s  # 启动后 30 秒才开始检查

    # 容器日志大小限制,防止磁盘被日志占满
    logging:
      driver: json-file
      options:
        max-size: "50m"
        max-file: "3"

4.3 设置环境变量并启动

# 注入密码(首次初始化生效,容器重建后需保持一致才能正常读取数据目录)
export POSTGRES_PASSWORD='your-password'

docker compose up -d

💡 说明:${POSTGRES_PASSWORD:?请在环境变量中设置} 语法表示:若该环境变量未设置,docker compose up 会直接报错退出,防止密码缺失导致初始化失败或使用默认值。

4.4 验证部署

# 查看容器状态(healthy 表示健康检查通过)
docker ps --filter name=postgres-18-6

# 连接测试
docker exec -it postgres-18-6 psql -U app_user -d app_db

五、数据持久化说明(重点)

  • 数据目录映射:./data:/var/lib/postgresql。
  • 配置目录映射:./conf:/etc/postgresql,通过 -c config_file=/etc/postgresql/postgresql.conf 生效,修改后重启容器生效(见"八、配置文件持久化(conf 挂载)"章节)。
  • ⚠️ 18+ 镜像布局变更:PostgreSQL 18 官方镜像的数据目录由 /var/lib/postgresql/data 改为 pg_ctlcluster 布局,实际数据在 /var/lib/postgresql/<版本>/<集群名>(如 /var/lib/postgresql/18/main)。
  • 必须挂载父目录 /var/lib/postgresql。若仍按旧文档挂载 ./data:/var/lib/postgresql/data,容器会反复重启(初始化脚本找不到预期目录结构)。
  • 重启容器(docker compose restart / docker compose up -d)数据不丢失。
  • 删除容器不会删除数据:docker compose down 只移除容器,./data 与 ./conf 目录仍在;只有 docker compose down -v 才会删除卷数据。
  • 备份:对宿主机 ./data 目录做快照/rsync,或使用 pg_dump 逻辑备份。
  • 权限说明:镜像内 PostgreSQL 以 postgres 用户(uid 999)运行,首次启动时镜像会自动对挂载目录做 chown,无需手动处理权限。

六、常用环境变量表

环境变量默认值说明
POSTGRES_USERapp_user超级用户(相当于默认的 postgres 用户)
POSTGRES_PASSWORD(必填,无默认)超级用户密码
POSTGRES_DBapp_db首次初始化自动创建的默认数据库(不设置则与用户名相同)
TZ镜像默认(UTC)容器时区,建议与宿主机一致

⚠️ 安全提醒:POSTGRES_PASSWORD 属于敏感值,务必通过环境变量注入,禁止写入 yaml 明文。生产环境可用 Docker secrets 或密码管理工具注入。

七、常用配置参数说明(-c 传参)

command 中以 -c key=value 方式传参,等价于写入 postgresql.conf。多个参数需重复 -c。本方案通过 -c config_file=/etc/postgresql/postgresql.conf 指定完整使用自定义配置文件(见下方"八、配置文件持久化(conf 挂载)"章节)。

参数说明
config_file=/etc/postgresql/postgresql.conf指定自定义配置文件路径(挂载自宿主机 ./conf)
shared_buffers=256MB共享缓冲区大小,建议设为物理内存的 25% 左右
max_connections=200最大连接数,按业务规模调整(过高会占用更多共享内存)
listen_addresses='*'监听所有网卡,配合端口映射供外部连接

💡 说明:shared_buffers、max_connections、listen_addresses 已写入 ./conf/postgresql.conf,与 -c config_file 组合生效。更多参数(如 work_mem、effective_cache_size)直接编辑该配置文件即可,参考《PostgreSQL 18 配置参数详解》文档。

八、配置文件持久化(conf 挂载)

本方案在 volumes 中挂载了配置目录 ./conf:/etc/postgresql,并通过 -c config_file 指定使用该配置文件,实现配置文件持久化,方便后续修改参数而无需改动 yaml:

# 配置文件位于宿主机,可随时编辑
sudo vim /opt/data/ops/postgresql/conf/postgresql.conf

./conf/postgresql.conf 内容如下(含常用参数示例):

# PostgreSQL 自定义配置文件(挂载到 /etc/postgresql/postgresql.conf)
# 启动参数:-c config_file=/etc/postgresql/postgresql.conf(完整替换默认 postgresql.conf)
# 修改后重启容器生效:docker compose restart postgres

# 共享缓冲区(默认 128MB,建议设为物理内存的 25% 左右)
shared_buffers = 256MB

# 最大连接数(默认 100)
max_connections = 200

# 监听所有网卡(配合端口映射供外部连接)
listen_addresses = '*'

# 更多常用参数示例(按需取消注释):
# work_mem = 16MB                    # 排序/哈希等操作的内存上限
# effective_cache_size = 4GB         # 操作系统缓存评估值(约物理内存的 50%~75%)
# maintenance_work_mem = 256MB       # 维护操作(VACUUM/索引重建)内存
# log_min_duration_statement = 1000  # 记录执行超过 1 秒的慢 SQL(毫秒)
# log_statement = 'none'             # 日志级别:none/ddl/mod/all

⚠️ 注意:-c config_file=... 会完整替换默认的 postgresql.conf。因此自定义配置文件中需包含必需的参数(如 listen_addresses);若容器启动异常,先检查该文件语法(docker logs postgres-18-6 查看报错)。修改后执行 docker compose restart postgres 即生效(已验证)。

九、等价 docker run 运行方式

不使用 Compose 时,可用以下 docker run 达到相同效果:

# 先注入环境变量
export POSTGRES_PASSWORD='your-password'

docker run -d \
  --name postgres-18-6 \
  --restart unless-stopped \
  -e TZ=Asia/Shanghai \
  -e POSTGRES_USER=app_user \
  -e POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \
  -e POSTGRES_DB=app_db \
  -p 15432:5432 \
  -v /opt/data/ops/postgresql/data:/var/lib/postgresql \
  -v /opt/data/ops/postgresql/conf:/etc/postgresql \
  --health-cmd='pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"' \
  --health-interval=10s \
  --health-timeout=5s \
  --health-retries=10 \
  --health-start-period=30s \
  postgres:18.6 \
  -c config_file=/etc/postgresql/postgresql.conf

参数对照:

Compose 写法docker run 写法
image: postgres:18.6末尾镜像名 postgres:18.6
container_name--name
restart: unless-stopped--restart unless-stopped
environment-e KEY=value
ports: "15432:5432"-p 15432:5432
volumes: ./data:/var/lib/postgresql-v /opt/data/ops/postgresql/data:/var/lib/postgresql
volumes: ./conf:/etc/postgresql-v /opt/data/ops/postgresql/conf:/etc/postgresql
healthcheck--health-cmd / --health-interval 等
command镜像名之后的附加参数

💡 说明:--health-cmd 中 "$POSTGRES_USER" 会被 shell 展开为容器内环境变量值,故无需转义 $(与 Compose 中需 $$ 转义不同)。

十、常用运维命令

# 查看日志
docker logs -f postgres-18-6

# 重启容器(数据保留)
docker compose restart

# 停止并移除容器(保留数据)
docker compose down

# 彻底移除容器 + 数据目录(谨慎操作!)
docker compose down -v

# 进入 psql 交互
docker exec -it postgres-18-6 psql -U app_user -d app_db

十一、常见问题(FAQ)

11.1 容器反复重启(Exited / Restarting 循环)?

最常见原因是卷挂载目录错误。确认挂载的是 /var/lib/postgresql(18+ 布局)而非 /var/lib/postgresql/data。查看日志:docker logs postgres-18-6,若报 FATAL: data directory ... has invalid permissions 或 initdb: error,请检查挂载路径与目录权限。

11.2 端口映射失败:宿主机 15432 已被占用?

修改 ports 为其他宿主机端口,如 "15433:5432"。注意客户端连接地址随之变化。

11.3 修改密码后连接报 password authentication failed?

  • POSTGRES_PASSWORD 只在首次初始化数据目录时生效;数据目录已存在时修改该变量不会改变密码。
  • 已部署后改密请用 SQL:ALTER USER app_user WITH PASSWORD '新密码';。

11.4 外部连接被拒绝?

确认已传 -c listen_addresses=*,且宿主机防火墙/安全组放行对应端口(15432)。

11.5 容器重启后数据还在吗?

在:docker compose restart / down 后 up -d 都不会删除 ./data 目录。只有 docker compose down -v 会删除卷数据。

11.6 如何自定义更多参数?

本方案已挂载配置目录 ./conf:/etc/postgresql 并通过 -c config_file 指定使用,直接编辑 ./conf/postgresql.conf 追加参数(如 work_mem、effective_cache_size),然后 docker compose restart postgres 即生效,无需改动 yaml。注意 config_file 会完整替换默认配置,请保留 listen_addresses 等必要参数。更多参数含义参考《PostgreSQL 18 配置参数详解》文档。