在 VPS 上用 Docker 搭建 PostgreSQL 开发环境:从零到可连接

为什么选 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_USERPOSTGRES_PASSWORDPOSTGRES_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 轻量得多,一行命令就能跑。

这篇文章对你有帮助吗?