大家好,我是Goya!
今天是Docker部署系列的第四篇文章:用Docker部署PostgreSQL。
PostgreSQL(简称Postgres)被誉为"开发者最爱的数据库",它以功能强大、标准兼容性好著称,是许多大厂的首选。很多开发者说:“用MySQL会了,用Postgres才是真的懂数据库”。
本篇要点:

  • ✅ 一分钟启动PostgreSQL容器

  • ✅ 设置用户名密码和数据持久化

  • ✅ 使用docker-compose一键部署PostgreSQL + pgAdmin

  • ✅ 初始化脚本自动创建表和数据

  • ✅ 支持远程客户端连接

  • ✅ pgAdmin图形化管理界面

  • ✅ PostgreSQL vs MySQL核心区别

一、为什么选择PostgreSQL?

特性PostgreSQLMySQL
SQL标准兼容⭐⭐⭐⭐⭐ 高度兼容⭐⭐⭐ 部分扩展
JSON支持⭐⭐⭐⭐⭐ JSONB类型强大⭐⭐ 基础JSON
并发性能⭐⭐⭐⭐⭐ MVCC实现优秀⭐⭐⭐⭐ 还行
GIS地理信息⭐⭐⭐⭐⭐ PostGIS扩展⭐ 需要第三方
全文检索内置强大需要插件
适合场景复杂查询、数据分析简单读写、Web应用

**一句话总结:**MySQL简单易用,适合CRUD为主的Web应用;PostgreSQL功能强大,适合复杂业务和数据分析。

二、准备工作

2.1 检查Docker环境

docker --version
docker-compose --version

如果没有docker-compose,先安装:

# Ubuntu/Debian系统
apt update
apt install docker-compose -y

2.2 拉取PostgreSQL镜像

docker pull postgres:16
docker pull dpage/pgadmin4

查看镜像:

docker images | grep -E "postgres|pgadmin"

三、创建项目目录

# 创建项目目录
mkdir -p ~/docker/postgres-project
cd ~/docker/postgres-project

# 创建数据目录和初始化脚本目录
mkdir -p postgres/{data,init}
mkdir -p pgadmin

# 设置权限
chmod -R 777 pgadmin

目录结构说明:

~/docker/postgres-project/
├── docker-compose.yml
├── postgres/
│ ├── data/ # 数据库数据文件
│ └── init/ # 初始化脚本
└── pgadmin/ # pgadmin配置文件

四、创建初始化脚本(可选,但推荐)

初始化脚本会在数据库第一次启动时自动执行,非常方便。

vim postgres/init/01-init.sql

粘贴以下内容:

-- 创建UUID扩展(用于生成唯一ID)
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";

-- 创建products表
CREATE TABLE IF NOT EXISTS products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(200) NOT NULL,
    price DECIMAL(10,2),
    stock INTEGER DEFAULT 0,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- 插入测试数据
INSERT INTO products (name, price, stock) VALUES 
    ('手机', 2999.00, 100),
    ('电脑', 5999.00, 50),
    ('耳机', 299.00, 200),
    ('键盘', 199.00, 150),
    ('鼠标', 89.00, 300);

-- 创建users表(使用UUID)
CREATE TABLE IF NOT EXISTS users (
    id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- 插入测试用户
INSERT INTO users (username, email) VALUES 
    ('zhangsan', 'zhangsan@example.com'),
    ('lisi', 'lisi@example.com'),
    ('wangwu', 'wangwu@example.com')
ON CONFLICT (username) DO NOTHING;

-- 创建索引
CREATE INDEX idx_products_name ON products(name);
CREATE INDEX idx_users_username ON users(username);

-- 创建orders表(关联查询示例)
CREATE TABLE IF NOT EXISTS orders (
    id SERIAL PRIMARY KEY,
    user_id UUID REFERENCES users(id),
    product_id INTEGER REFERENCES products(id),
    quantity INTEGER NOT NULL,
    total_price DECIMAL(10,2),
    order_date TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- 插入一些订单数据
INSERT INTO orders (user_id, product_id, quantity, total_price)
SELECT 
    u.id,
    p.id,
    1,
    p.price
FROM users u, products p
WHERE u.username = 'zhangsan' AND p.name = '手机'
LIMIT 1;

保存退出(:wq)。

五、编写docker-compose.yml

这是本文的核心!一条命令启动两个服务。

vim docker-compose.yml

粘贴以下内容:

version: '3.8'

services:
  # PostgreSQL服务
  postgres:
    image: postgres:16
    container_name: postgres16
    restart: always
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: 123456
      POSTGRES_DB: myapp
      # 时区设置
      TZ: Asia/Shanghai
    volumes:
      # 数据持久化
      - ./postgres/data:/var/lib/postgresql/data
      # 初始化脚本
      - ./postgres/init:/docker-entrypoint-initdb.d
    networks:
      - postgres-network

  # pgAdmin管理界面
  pgadmin:
    image: dpage/pgadmin4
    container_name: pgadmin
    restart: always
    ports:
      - "5050:80"
    environment:
      PGADMIN_DEFAULT_EMAIL: admin@admin.com
      PGADMIN_DEFAULT_PASSWORD: 123456
      # 中文界面
      PGADMIN_CONFIG_LANGUAGE: 'zh_CN'
    volumes:
      - ./pgadmin:/var/lib/pgadmin
    depends_on:
      - postgres
    networks:
      - postgres-network

# 定义网络,让容器可以互相通信
networks:
  postgres-network:
    driver: bridge

配置详解:

参数说明
ports: - "5432:5432"映射PostgreSQL端口
POSTGRES_PASSWORD设置超级用户密码(必须)
POSTGRES_USER设置超级用户名(默认postgres)
POSTGRES_DB初始化时创建的数据库
volumes挂载数据目录和初始化脚本
depends_onpgAdmin依赖postgres,会等它启动后再启动

六、启动所有服务

cd ~/docker/postgres-project
docker-compose up -d

看到类似输出就成功了:

Creating postgres16 ... done
Creating pgadmin    ... done

查看运行状态:

docker-compose ps

应该两个都是Up状态。

查看日志:

docker-compose logs -f

看到database system is ready to accept connections说明PostgreSQL启动成功。

七、验证PostgreSQL

7.1 进入容器连接数据库

# 直接连接
docker-compose exec postgres psql -U admin -d myapp

或者:

docker exec -it postgres16 psql -U admin -d myapp

7.2 验证初始化脚本

看到myapp=#提示符后,执行:

-- 查看所有表
\dt

-- 查询products表
SELECT * FROM products;

-- 查询users表
SELECT * FROM users;

-- 查看关联查询
SELECT 
    u.username,
    p.name as product,
    o.quantity,
    o.total_price,
    o.order_date
FROM orders o
JOIN users u ON o.user_id = u.id
JOIN products p ON o.product_id = p.id;

-- 退出
\q

如果能查到数据,说明初始化脚本执行成功!

7.3 测试数据持久化

# 重启容器
docker-compose restart

# 再次连接查看数据
docker-compose exec postgres psql -U admin -d myapp -c "SELECT COUNT(*) FROM products;"

数据应该还在,说明持久化生效。

八、配置pgAdmin图形化管理界面

8.1 访问pgAdmin

打开浏览器,访问:

http://你的服务器IP:5050
登录信息:

  • 邮箱:admin@admin.com

  • 密码:123456

8.2 添加PostgreSQL服务器

登录后点击 “Add New Server”:

General标签页:

  • Name: 我的PostgreSQL(随便写)

  • Connection标签页(重要):

  • Host name/address:postgres(注意:不是IP,是服务名!)

  • Port:5432

  • Maintenance database: myapp

  • Username:admin

  • Password: 123456

  • Save password: ✅ 勾选

点击 “Save”。

8.3 验证连接成功

如果一切正常,左侧会展开数据库树形结构:

Servers (1)
└── 我的PostgreSQL
    ├── Databases
    │   └── myapp
    │       ├── Schemas
    │       │   └── public
    │       │       ├── Tables
    │       │       │   ├── orders
    │       │       │   ├── products
    │       │       │   └── users

8.4 执行SQL查询

右键点击myapp数据库 → “Query Tool”,执行:

SELECT * FROM products;

就能看到我们初始化插入的数据了!

九、配置远程连接(客户端连接)

9.1 查看服务器IP

curl ifconfig.me

9.2 配置防火墙/安全组

Ubuntu系统(UFW):

ufw allow 5432/tcp
ufw status

云服务器:在安全组中开放5432端口。

9.3 使用客户端连接

推荐客户端:

  • DBeaver(免费,全功能)

  • Navicat(付费,好用)

  • DataGrip(JetBrains出品)

连接信息:

  • **主机:**你的服务器公网IP

  • 端口: 5432

  • 数据库: myapp

  • 用户: admin

  • 密码:123456

十、docker-compose常用命令

# 启动所有服务
docker-compose up -d

# 停止所有服务
docker-compose down

# 重启所有服务
docker-compose restart

# 查看实时日志
docker-compose logs -f

# 查看某个服务的日志
docker-compose logs postgres

# 进入容器
docker-compose exec postgres bash

# 执行SQL
docker-compose exec postgres psql -U admin -d myapp -c "SELECT * FROM users;"

# 查看容器状态
docker-compose ps

# 停止并删除容器(数据还在)
docker-compose down

# 停止并删除容器+删除数据卷(谨慎!数据会丢)
docker-compose down -v

十一、备份与恢复

11.1 备份数据库

# 备份整个数据库
docker-compose exec postgres pg_dump -U admin myapp > backup.sql

# 只备份数据(不备份表结构)
docker-compose exec postgres pg_dump -U admin --data-only myapp > data.sql

# 压缩备份
docker-compose exec postgres pg_dump -U admin myapp | gzip > backup.sql.gz

11.2 恢复数据库

# 恢复备份
cat backup.sql | docker-compose exec -T postgres psql -U admin myapp

# 从压缩文件恢复
gunzip -c backup.sql.gz | docker-compose exec -T postgres psql -U admin myapp

十二、常见问题排查

Q1:容器启动失败

# 查看错误日志
docker-compose logs postgres

Q2:pgAdmin连不上postgres

# 测试网络连通性
docker exec -it pgadmin sh
ping postgres
# 按Ctrl+C停止
exit

如果ping不通,检查docker-compose.yml中的网络配置。
Q3:远程连接不上

# 检查端口监听
netstat -tlnp | grep 5432

# 检查防火墙
ufw status

# 进入容器查看PostgreSQL配置
docker exec -it postgres16 bash
cat /var/lib/postgresql/data/postgresql.conf | grep listen
# 应该看到 listen_addresses = '*'

Q4:"关系不存在"错误
表名大小写问题。PostgreSQL对表名大小写敏感:

-- 如果创建时用"Users",查询时必须加引号
SELECT * FROM "Users";

-- 推荐都用小写
SELECT * FROM users;

Q5:容器名冲突

# 查看冲突的容器
docker ps -a | grep postgres16

# 删除旧容器
docker rm -f postgres16

# 重新启动
docker-compose up -d

十三、总结

通过本文,我们成功实现了:

功能实现方式验证方法
✅ Docker部署PostgreSQLdocker-composedocker-compose ps
✅ 设置用户名密码环境变量psql登录
✅ 初始化数据库和表初始化脚本SELECT * FROM products;
✅ 数据持久化数据卷挂载重启后数据还在
✅ pgAdmin图形界面docker-compose浏览器访问5050端口
✅ 远程连接端口映射DBeaver/Navicat连接
✅ 备份恢复pg_dump命令导出导入测试

现在你的服务器上已经有了一整套PostgreSQL数据库环境,既可以命令行操作,也可以用pgAdmin图形化管理!
搞定! 🎯 现在你的服务器上有了:

  • ✅ MySQL(关系型数据库)

  • ✅ Redis(缓存)

  • ✅ Nginx(Web服务器)

  • ✅ PostgreSQL(另一个关系型数据库)+ pgAdmin
    如果本文对你有帮助,欢迎点赞、收藏、评论!

更多推荐