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_PASSWORD | superuser 密碼(必填) | 無 |
POSTGRES_USER | superuser 帳號 | postgres |
POSTGRES_DB | 預設建立的資料庫 | 同 POSTGRES_USER |
PGDATA | 容器內的資料目錄 | /var/lib/postgresql/data |
POSTGRES_INITDB_ARGS | 傳給 initdb 的額外參數 | 無 |
POSTGRES_HOST_AUTH_METHOD | pg_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-8 或 C |
--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 | 連線類型 | local、host、hostssl |
| DATABASE | 目標資料庫 | all、mydb |
| USER | 目標使用者 | all、myuser |
| ADDRESS | 來源 IP/網段 | 127.0.0.1/32、10.10.1.0/24 |
| METHOD | 認證方式 | scram-sha-256、peer、cert |
認證方法比較
| 方法 | 安全等級 | 說明 | 適用場景 |
|---|---|---|---|
trust | 最低 | 無需密碼 | 禁止在生產環境使用 |
md5 | 低 | MD5 雜湊密碼 | 舊版相容 |
scram-sha-256 | 高 | SCRAM 挑戰回應 | 現代標準,強烈推薦 |
peer | 高 | 核對 OS 使用者名稱(僅 local) | 本地連線 |
cert | 最高 | 客戶端 SSL 憑證 | 高安全需求 |
ldap | 高 | LDAP 目錄服務認證 | 企業 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 |
superuser | superuser 可在 session 中修改 |
user | 任何使用者可在 session 中修改 |
多版本並存
Debian/Ubuntu 的 postgresql-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 要求目錄為空且屬於 postgres | chown 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-checksums | PG12+ 可離線啟用 |
版本演進
| 版本 | 年份 | 安裝相關特性 |
|---|---|---|
| PostgreSQL 10 | 2017 | 原生分區表、邏輯複製、SCRAM 認證 |
| PostgreSQL 12 | 2019 | pg_checksums(離線啟用 checksums) |
| PostgreSQL 14 | 2021 | 連線效能改進 |
| PostgreSQL 15 | 2022 | public schema 安全變更(REVOKE CREATE) |
| PostgreSQL 16 | 2023 | pg_hba.conf 支援正規表達式 |
| PostgreSQL 17 | 2024 | 增量備份、記憶體最佳化 |
總結
本文涵蓋了 PostgreSQL 安裝與部署的完整流程:
- 套件管理器安裝:Debian/Ubuntu(apt)、RHEL/CentOS(dnf)、macOS(Homebrew)
- 原始碼編譯:
configure→make→make install→initdb - Docker 部署:快速啟動與 docker-compose 生產配置
- initdb 初始化:編碼、locale、data checksums
- pg_hba.conf 認證:生產環境建議使用
scram-sha-256 - postgresql.conf 基礎設定:連線、記憶體、日誌
- systemd 服務管理:start/stop/restart/reload 的差異
- 安全加固:密碼設定、權限收緊、SSL
下一篇,我們將探討 PostgreSQL 的日常維護——從 VACUUM 排程策略、索引重建、日誌輪替到磁碟空間監控的完整維運手冊。