PostgreSQL 安裝與部署:從套件管理器到 Docker 完整指南 | PostgreSQL

2026/07/16
PostgreSQL 安裝與部署:從套件管理器到 Docker 完整指南 | PostgreSQL

正確的安裝與初始化是 PostgreSQL 穩定運行的基礎。本文涵蓋從 apt/yum/Homebrew 套件管理器安裝到 原始碼編譯Docker 容器部署、initdb 初始化、pg_hba.conf 認證設定與 systemd 服務管理的完整流程。

安裝方式比較

在開始安裝之前,先了解不同安裝方式的優缺點,以選擇最適合你的場景:

方式優點缺點建議場景
套件管理器(apt/yum/brew)快速、自動處理相依性版本可能落後裸機 Linux/macOS
原始碼編譯完全控制編譯選項耗時、需手動維護升級需要特殊編譯選項
Docker/Container隔離性好、易於版本切換I/O 效能略低、volume 管理需注意開發環境、CI/CD
雲端託管(Managed)零維運、自動備份成本較高、客製化受限無專職 DBA 的團隊

部署架構概覽

PostgreSQL 支援從開發用單機到生產用高可用叢集的多種部署拓撲:

架構描述適用場景
單機(Standalone)單一 Primary 節點,無備援開發、測試、小型應用
主從(Primary/Replica)一主多從,支援讀取擴展生產環境基本配置
高可用叢集(HA Cluster)Patroni/Repmgr 管理自動故障切換關鍵業務、零停機需求
雲端託管(Managed)RDS/Cloud SQL/Aurora 等降低維運負擔

目錄結構

安裝完成後,PostgreSQL 的檔案分布於以下主要目錄:

/usr/lib/postgresql/17/          # 二進位檔(Debian/Ubuntu)
├── bin/                         # 執行檔(postgres, psql, pg_dump...)
└── lib/                         # 動態函式庫

$PGDATA(例:/var/lib/postgresql/17/main/)
├── PG_VERSION                   # 主版本號
├── base/                        # 資料庫資料目錄
├── global/                      # 叢集全域表(pg_database, pg_authid...)
├── pg_hba.conf                  # 用戶端認證設定
├── postgresql.conf              # 主要設定檔
├── postgresql.auto.conf         # ALTER SYSTEM 寫入的覆蓋設定
├── pg_wal/                      # Write-Ahead Log
├── pg_xact/                     # 交易狀態(commit log)
└── postmaster.pid               # 執行中的 PID 檔

PGDATA 是最重要的環境變數,指向 PostgreSQL 的資料目錄。所有設定檔、資料檔、WAL 都存放於此。


Debian/Ubuntu 安裝(apt)

PostgreSQL Global Development Group(PGDG)維護官方 APT Repository,版本比系統內建更新:

# 步驟 1:安裝必要工具
sudo apt install -y curl ca-certificates

# 步驟 2:新增 PostgreSQL APT Repository
sudo install -d /usr/share/postgresql-common/pgdg
sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail \
  https://www.postgresql.org/media/keys/ACCC4CF8.asc

sudo sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] \
  https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" \
  > /etc/apt/sources.list.d/pgdg.list'

# 步驟 3:更新並安裝
sudo apt update
sudo apt install -y postgresql-17

# 驗證安裝
psql --version
# 輸出:postgresql 17.x

# 確認服務狀態
sudo systemctl status postgresql@17-main

安裝後的重要路徑:

/etc/postgresql/17/main/         # 設定目錄(postgresql.conf、pg_hba.conf)
/var/lib/postgresql/17/main/     # 資料目錄(PGDATA)
/var/log/postgresql/             # 日誌目錄
/usr/lib/postgresql/17/bin/      # 執行檔目錄

若只需要客戶端工具(不含伺服器):

# 僅安裝 psql 等客戶端工具
sudo apt install -y postgresql-client-17

RHEL/CentOS/Rocky 安裝(yum/dnf)

# 步驟 1:停用系統內建的 PostgreSQL 模組(RHEL8+)
sudo dnf -qy module disable postgresql

# 步驟 2:安裝 PGDG YUM Repository
sudo dnf install -y \
  https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm

# 步驟 3:安裝 PostgreSQL 17
sudo dnf install -y postgresql17-server postgresql17-contrib

# 步驟 4:初始化資料庫(YUM 安裝不自動 initdb)
sudo /usr/pgsql-17/bin/postgresql-17-setup initdb

# 步驟 5:啟動並設定開機自啟
sudo systemctl enable --now postgresql-17

# 驗證
sudo -u postgres psql -c "SELECT version();"

RHEL/CentOS 的重要路徑:

/var/lib/pgsql/17/data/          # 資料目錄(PGDATA)
/usr/pgsql-17/bin/               # 執行檔目錄

macOS 安裝(Homebrew)

# 安裝 PostgreSQL 17
brew install postgresql@17

# 將執行檔加入 PATH
echo 'export PATH="/opt/homebrew/opt/postgresql@17/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

# 啟動服務(以 launchd 管理)
brew services start postgresql@17

# 連線(macOS 預設使用 trust 認證本地連線)
psql postgres

# 確認版本
psql --version

Homebrew 安裝路徑(Apple Silicon):

/opt/homebrew/opt/postgresql@17/     # 軟體目錄
/opt/homebrew/var/postgresql@17/     # 資料目錄(PGDATA)

原始碼編譯安裝

從原始碼編譯可以啟用特殊功能或針對硬體最佳化:

# 步驟 1:安裝編譯相依套件(Debian/Ubuntu)
sudo apt install -y \
  build-essential libreadline-dev zlib1g-dev \
  libssl-dev libicu-dev libxml2-dev libxslt1-dev \
  libperl-dev python3-dev pkg-config

# 步驟 2:下載並解壓原始碼
wget https://ftp.postgresql.org/pub/source/v17.0/postgresql-17.0.tar.bz2
tar xjf postgresql-17.0.tar.bz2
cd postgresql-17.0

# 步驟 3:configure(設定編譯選項)
./configure \
  --prefix=/usr/local/pgsql \
  --with-openssl \
  --with-icu \
  --with-llvm \
  --with-perl \
  --with-python \
  --enable-debug

# 步驟 4:編譯並安裝
make -j$(nproc)
make check          # 執行回歸測試(建議)
sudo make install

# 步驟 5:建立 postgres 使用者並初始化
sudo useradd -r -m -d /var/lib/postgresql postgres
sudo mkdir -p /var/lib/postgresql/17/data
sudo chown postgres:postgres /var/lib/postgresql/17/data
sudo -u postgres /usr/local/pgsql/bin/initdb \
  -D /var/lib/postgresql/17/data \
  --encoding=UTF8 \
  --locale=en_US.UTF-8 \
  --data-checksums

常用編譯選項:

選項說明
--with-openssl啟用 SSL/TLS 加密連線
--with-icu啟用 ICU 國際化排序
--with-llvm啟用 JIT 編譯,加速複雜查詢
--with-perl啟用 PL/Perl 語言支援
--with-python啟用 PL/Python 語言支援
--enable-debug產生除錯符號(勿用於生產)

Docker 部署

Docker 是快速啟動開發環境的最佳選擇。

快速啟動

# 啟動 PostgreSQL 17 容器
docker run -d \
  --name pg17 \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -e POSTGRES_USER=myuser \
  -e POSTGRES_DB=mydb \
  -p 5432:5432 \
  -v pgdata:/var/lib/postgresql/data \
  postgres:17

# 連線至容器內的 psql
docker exec -it pg17 psql -U myuser -d mydb

# 從主機連線
psql -h localhost -U myuser -d mydb

docker-compose 範例

# docker-compose.yml
version: '3.9'

services:
  postgres:
    image: postgres:17-alpine
    container_name: pg17
    restart: unless-stopped
    environment:
      POSTGRES_USER: ${POSTGRES_USER:-admin}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}       # 必填
      POSTGRES_DB: ${POSTGRES_DB:-appdb}
      PGDATA: /var/lib/postgresql/data/pgdata
    ports:
      - "5432:5432"
    volumes:
      - pgdata:/var/lib/postgresql/data
      - ./init-scripts:/docker-entrypoint-initdb.d  # 初始化 SQL 腳本
      - ./postgresql.conf:/etc/postgresql/postgresql.conf
    command: >
      postgres
        -c config_file=/etc/postgresql/postgresql.conf
        -c log_statement=all
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-admin}"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

volumes:
  pgdata:
    driver: local

重要的環境變數

變數說明預設值
POSTGRES_PASSWORDsuperuser 密碼(必填)
POSTGRES_USERsuperuser 帳號postgres
POSTGRES_DB預設建立的資料庫POSTGRES_USER
PGDATA容器內的資料目錄/var/lib/postgresql/data
POSTGRES_INITDB_ARGS傳給 initdb 的額外參數
POSTGRES_HOST_AUTH_METHODpg_hba.conf 預設認證方式scram-sha-256

安全提醒:切勿將 POSTGRES_HOST_AUTH_METHOD=trust 用於生產環境。


initdb 初始化

initdb 是建立 PostgreSQL 資料叢集(Database Cluster)的命令。套件管理器安裝通常會自動執行,但理解其參數至關重要:

# 完整建議的初始化命令
sudo -u postgres initdb \
  --pgdata=/var/lib/postgresql/17/data \
  --encoding=UTF8 \
  --locale=en_US.UTF-8 \
  --lc-collate=en_US.UTF-8 \
  --lc-ctype=en_US.UTF-8 \
  --data-checksums \
  --auth-host=scram-sha-256 \
  --auth-local=peer

重要參數

參數說明建議值
--encoding預設字元編碼UTF8
--locale地區設定(影響排序)en_US.UTF-8C
--lc-collate字串排序規則C(最快)或 en_US.UTF-8
--data-checksums啟用資料頁校驗碼強烈建議開啟
--auth-host遠端連線的預設認證scram-sha-256
--auth-local本地連線的預設認證peer

資料校驗碼(Data Checksums)

--data-checksums 啟用後,PostgreSQL 會對每個資料頁計算 CRC 校驗碼,讀取時自動驗證:

  • 偵測硬體故障:磁碟靜默錯誤(Silent Data Corruption)是生產環境的隱形殺手
  • 偵測儲存系統問題:SAN/NAS 的韌體 Bug 可能造成資料損壞而不報錯
  • 代價:約 1-2% 的寫入效能開銷,保護遠大於代價
-- 確認是否已啟用 checksums
SHOW data_checksums;
# 若初始化時未啟用,PostgreSQL 12+ 可離線啟用
sudo systemctl stop postgresql@17-main
sudo -u postgres pg_checksums --enable -D /var/lib/postgresql/17/main
sudo systemctl start postgresql@17-main

pg_hba.conf 認證設定

pg_hba.conf(Host-Based Authentication)是 PostgreSQL 的防火牆,控制誰可以從哪裡以什麼方式連線。

格式

每行格式為:

TYPE  DATABASE  USER  ADDRESS  METHOD  [OPTIONS]
欄位說明範例
TYPE連線類型localhosthostssl
DATABASE目標資料庫allmydb
USER目標使用者allmyuser
ADDRESS來源 IP/網段127.0.0.1/3210.10.1.0/24
METHOD認證方式scram-sha-256peercert

認證方法比較

方法安全等級說明適用場景
trust最低無需密碼禁止在生產環境使用
md5MD5 雜湊密碼舊版相容
scram-sha-256SCRAM 挑戰回應現代標準,強烈推薦
peer核對 OS 使用者名稱(僅 local)本地連線
cert最高客戶端 SSL 憑證高安全需求
ldapLDAP 目錄服務認證企業 AD/LDAP 整合

生產環境建議設定

# pg_hba.conf — 生產環境建議
# TYPE  DATABASE  USER       ADDRESS          METHOD

# 1. local 連線使用 peer 認證
local   all       postgres                    peer
local   all       all                         peer

# 2. 本地 TCP 連線
host    all       all        127.0.0.1/32     scram-sha-256
host    all       all        ::1/128          scram-sha-256

# 3. 應用伺服器 IP 段
host    appdb     appuser    10.10.1.0/24     scram-sha-256

# 4. 管理用連線使用 SSL 憑證
hostssl all       dbaadmin   10.10.0.0/16     cert

# 5. 複製連線
host    replication replicator 10.10.1.0/24   scram-sha-256

# 注意:規則由上至下匹配,第一條符合的規則生效

修改後需 reload(不需重啟):

# 方法 1:SQL 命令
sudo -u postgres psql -c "SELECT pg_reload_conf();"

# 方法 2:systemd
sudo systemctl reload postgresql@17-main

postgresql.conf 基礎設定

postgresql.conf 是主設定檔,以下列出安裝後必須確認的初始參數:

# ─── 連線與認證 ───
listen_addresses = 'localhost'     # 開發環境
# listen_addresses = '*'           # 容器環境(配合 pg_hba.conf 限制)
port = 5432
max_connections = 100
superuser_reserved_connections = 3

# ─── 資源使用 ───
shared_buffers = 256MB             # 通常設為系統 RAM 的 25%
work_mem = 4MB                     # 每個 sort/hash 操作的記憶體
maintenance_work_mem = 64MB        # VACUUM、CREATE INDEX 等

# ─── WAL ───
wal_level = replica                # 支援備援(最低設定)

# ─── 日誌 ───
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 1d
log_min_duration_statement = 1000  # 記錄超過 1 秒的慢查詢

log_line_prefix = '%m [%p] %q%u@%d '
log_timezone = 'Asia/Taipei'
timezone = 'Asia/Taipei'

systemd 服務管理

現代 Linux 發行版使用 systemd 管理 PostgreSQL 服務:

# Debian/Ubuntu(服務名稱:postgresql@版本-叢集名稱)
sudo systemctl start postgresql@17-main
sudo systemctl stop postgresql@17-main
sudo systemctl restart postgresql@17-main    # 會中斷所有連線
sudo systemctl reload postgresql@17-main     # 僅重載設定,不中斷連線
sudo systemctl enable postgresql@17-main     # 開機自啟

# RHEL/CentOS(服務名稱:postgresql-版本)
sudo systemctl start postgresql-17
sudo systemctl enable postgresql-17

# 查看詳細狀態
sudo systemctl status postgresql@17-main
sudo journalctl -u postgresql@17-main -f

判斷需要重啟還是 Reload

-- 查看哪些參數已變更且尚未生效
SELECT name, setting, pending_restart
FROM pg_settings
WHERE pending_restart = true;
Context 值說明
internal由 initdb 設定,不可修改
postmaster需重啟服務
sighup僅需 reload
superusersuperuser 可在 session 中修改
user任何使用者可在 session 中修改

多版本並存

Debian/Ubuntupostgresql-common 套件提供完整的多版本管理工具:

# 列出所有已安裝的叢集
pg_lsclusters
# Ver Cluster Port Status Owner    Data directory
# 15  main    5433 online postgres /var/lib/postgresql/15/main
# 17  main    5432 online postgres /var/lib/postgresql/17/main

# 建立新叢集
sudo pg_createcluster 17 replica --port 5434

# 啟動/停止特定叢集
sudo pg_ctlcluster 17 main start
sudo pg_ctlcluster 17 main stop

# 刪除叢集(警告:資料遺失)
sudo pg_dropcluster 15 main --stop

# 使用 --cluster 指定版本
psql --cluster 17/main -U postgres

# 使用環境變數切換
export PGPORT=5433   # 切換至 15 版叢集
psql -U postgres

安全加固初始化清單

完成基本安裝後,執行以下安全加固步驟:

# 1. 設定 postgres superuser 密碼
sudo -u postgres psql -c "ALTER USER postgres PASSWORD 'strong_password_here';"

# 2. 移除預設的 public schema 寫入權限
sudo -u postgres psql -c "REVOKE CREATE ON SCHEMA public FROM PUBLIC;"

# 3. 移除 template1 的 PUBLIC CONNECT 權限
sudo -u postgres psql -c "REVOKE CONNECT ON DATABASE template1 FROM PUBLIC;"

# 4. 建立應用專用使用者(最小權限原則)
sudo -u postgres psql <<EOF
CREATE USER appuser WITH PASSWORD 'app_password';
CREATE DATABASE appdb OWNER appuser;
REVOKE ALL ON DATABASE appdb FROM PUBLIC;
GRANT CONNECT ON DATABASE appdb TO appuser;
EOF

# 5. 確認 pg_hba.conf 無 trust 規則
grep -v '^#' /etc/postgresql/17/main/pg_hba.conf | grep trust

# 6. 確認 SSL 已啟用
sudo -u postgres psql -c "SHOW ssl;"

自動化部署

生產環境建議使用 Infrastructure as Code 管理部署:

Ansible 範例

- name: 安裝 PostgreSQL 17
  hosts: db_servers
  roles:
    - role: geerlingguy.postgresql
      vars:
        postgresql_version: "17"
        postgresql_config_options:
          - option: shared_buffers
            value: "{{ (ansible_memtotal_mb * 0.25) | int }}MB"
          - option: max_connections
            value: "200"
        postgresql_hba_entries:
          - type: local
            database: all
            user: postgres
            auth_method: peer
          - type: host
            database: all
            user: all
            address: "10.10.0.0/16"
            auth_method: scram-sha-256

Terraform 範例(AWS RDS)

resource "aws_db_instance" "postgres" {
  identifier        = "prod-postgres"
  engine            = "postgres"
  engine_version    = "17.0"
  instance_class    = "db.r6g.xlarge"
  allocated_storage = 100
  storage_type      = "gp3"
  storage_encrypted = true

  db_name  = "appdb"
  username = "admin"
  password = var.db_password

  backup_retention_period = 7
  multi_az               = true
  deletion_protection    = true
}

常見陷阱

陷阱說明解法
密碼認證失敗pg_hba.conf 設定 scram-sha-256 但客戶端不支援確認 libpq >= 10
連線被拒來源 IP 不在 pg_hba.conf 允許範圍新增規則並 reload
目錄權限錯誤initdb 要求目錄為空且屬於 postgreschown postgres:postgres + chmod 700
端口被占用5432 已被其他程序使用ss -tlnp | grep 5432 檢查
locale 不一致initdb 時 locale 與系統不符locale-gen en_US.UTF-8
Docker volume 遺失未使用 named volume,容器刪除後資料消失使用 named volume 而非 bind mount
listen_addresses預設只監聽 localhost容器環境需設為 '*'
未啟用 checksums初始化時忘記 --data-checksumsPG12+ 可離線啟用

版本演進

版本年份安裝相關特性
PostgreSQL 102017原生分區表、邏輯複製、SCRAM 認證
PostgreSQL 122019pg_checksums(離線啟用 checksums)
PostgreSQL 142021連線效能改進
PostgreSQL 152022public schema 安全變更(REVOKE CREATE)
PostgreSQL 162023pg_hba.conf 支援正規表達式
PostgreSQL 172024增量備份、記憶體最佳化

總結

本文涵蓋了 PostgreSQL 安裝與部署的完整流程:

  1. 套件管理器安裝:Debian/Ubuntu(apt)、RHEL/CentOS(dnf)、macOS(Homebrew)
  2. 原始碼編譯configuremakemake installinitdb
  3. Docker 部署:快速啟動與 docker-compose 生產配置
  4. initdb 初始化:編碼、locale、data checksums
  5. pg_hba.conf 認證:生產環境建議使用 scram-sha-256
  6. postgresql.conf 基礎設定:連線、記憶體、日誌
  7. systemd 服務管理:start/stop/restart/reload 的差異
  8. 安全加固:密碼設定、權限收緊、SSL

下一篇,我們將探討 PostgreSQL 的日常維護——從 VACUUM 排程策略、索引重建、日誌輪替到磁碟空間監控的完整維運手冊。

BenZ Software Developer

熱愛技術的軟體開發者,在這裡分享程式開發經驗與學習筆記。