为什么选 PostgreSQL?
PostgreSQL 是目前最流行的开源关系型数据库。它支持 JSON 查询、全文搜索、地理空间数据(PostGIS),被大量生产系统使用。用 Docker 部署 PG,好处是环境干净、随时重建、不会污染宿主机。
准备工作
你需要:
- 一台 VPS(推荐:1 核 CPU、1 GB 内存、20 GB 磁盘)
- Docker 和 Docker Compose(已安装)
- 一个 SSH 客户端(用于从本地连接)
如果还没装 Docker,跑一行命令就行:
curl -fsSL https://get.docker.com | bash
第一步:创建项目目录
mkdir -p ~/pg-dev && cd ~/pg-dev
第二步:写 docker-compose.yml
version: '3.8'
services:
postgres:
image: postgres:16-alpine
container_name: pg-dev
restart: unless-stopped
ports:
- "5432:5432"
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: dev123456
POSTGRES_DB: myapp
volumes:
- pg_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U dev -d myapp"]
interval: 10s
timeout: 5s
retries: 5
networks:
- pg_net
volumes:
pg_data:
networks:
pg_net:
driver: bridge
关键说明:
postgres:16-alpine用 Alpine 镜像,体积仅 100 MB 左右POSTGRES_USER、POSTGRES_PASSWORD、POSTGRES_DB设置初始用户和密码pg_data卷保证容器删了数据还在init.sql会在首次启动时自动执行,用来建表
第三步:写初始化 SQL
cat > init.sql << 'EOF'
-- 创建扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
-- 示例表
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT NOW()
);
-- 插入测试数据
INSERT INTO users (username, email) VALUES
('alice', 'alice@example.com'),
('bob', 'bob@example.com')
ON CONFLICT DO NOTHING;
EOF
第四步:启动服务
cd ~/pg-dev
docker compose up -d
等待几秒让数据库初始化完成:
sleep 5
docker compose ps
输出应该类似这样:
NAME IMAGE STATUS
pg-dev postgres:16-alpine Up 10 seconds (healthy)
注意 healthy 状态,说明数据库已经就绪。
第五步:验证连接
1. 在容器内测试
docker exec -it pg-dev psql -U dev -d myapp -c "\dt"
你应该看到 users 表。再查一下数据:
docker exec -it pg-dev psql -U dev -d myapp -c "SELECT * FROM users;"
输出:
id | username | email | created_at
--------------------------------------+----------+--------------------+----------------------------
a1b2c3d4-e5f6-... | alice | alice@example.com | 2026-07-12 10:05:00
b2c3d4e5-f6a7-... | bob | bob@example.com | 2026-07-12 10:05:00
2. 从本机连接 VPS 上的数据库
在本地终端运行(需要安装 psql 或任何 PG 客户端):
psql "host=<你的VPS_IP> port=5432 dbname=myapp user=dev password=dev123456"
如果连不上,检查 VPS 防火墙是否放行了 5432 端口:
# 在 VPS 上执行
sudo ufw allow 5432/tcp
# 或者如果用 firewalld
sudo firewall-cmd --permanent --add-port=5432/tcp
sudo firewall-cmd --reload
第六步:配置自动备份
写一个备份脚本,放在 ~/pg-dev/backup.sh:
cat > backup.sh << 'SCRIPT'
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/opt/pg-backups"
mkdir -p "$BACKUP_DIR"
docker exec pg-dev pg_dump -U dev myapp > "$BACKUP_DIR/myapp_$DATE.sql"
# 只保留最近 7 天的备份
find "$BACKUP_DIR" -name "*.sql" -mtime +7 -delete
echo "Backup completed: $DATE"
SCRIPT
chmod +x backup.sh
添加到 crontab,每天凌晨 3 点自动备份:
crontab -e
# 添加这一行:
0 3 * * * /home/ubuntu/pg-dev/backup.sh >> /var/log/pg-backup.log 2>&1
常见问题
Q1: 容器启动后一直不健康?
检查日志:docker logs pg-dev。常见原因是密码太简单被安全策略拦截,或者磁盘空间不足。
Q2: 本地连不上远程 PG?
除了防火墙,还要确认 postgresql.conf 中的 listen_addresses 设为 '*'。Docker 默认已处理,如果你直接装 PG 而不是用容器,需要手动改这个配置。
Q3: 怎么修改密码?
docker exec -it pg-dev psql -U dev -c "ALTER USER dev WITH PASSWORD 'newpassword';"
然后更新 docker-compose.yml 里的 POSTGRES_PASSWORD,重启容器:docker compose up -d
Q4: 想装 PostGIS 扩展怎么办?
把镜像换成 postgis/postgis:16-3.4,其他配置不变。它内置了 PostGIS 扩展,初始化 SQL 里 CREATE EXTENSION postgis; 就能用。
Q5: 数据卷占太多磁盘?
Alpine 版 PG 本身很小,但数据会增长。定期清理旧备份,或者用 VACUUM 回收空间:
docker exec -it pg-dev psql -U dev -d myapp -c "VACUUM VERBOSE;"
搞定。现在你有了一个干净的 PostgreSQL 开发环境,随时可以开始写代码了。
下一步要不要试试给 PG 配个 Web 管理界面?Adminer 比 phpMyAdmin 轻量得多,一行命令就能跑。