创建时间: 2026-09-01最后更新: 2026-09-01

1. 准备环境

PostgreSQL 是独立运行的服务。为了让不同操作系统上的读者获得尽量一致的环境,本章使用 Docker 启动 PostgreSQL,而不是直接安装到操作系统中。

macOS 和 Windows 通常安装 Docker Desktop,它已经包含 Docker Engine、命令行工具和 Compose。Linux 可以直接安装 Docker Engine,并额外安装 Compose 插件。先根据自己的操作系统选择一种安装方式:

如果 Linux 上已经安装过发行版自带的 docker.io、旧版 docker-compose、podman-docker,或者单独安装过 containerd、runc,不要直接与 Docker 官方仓库的软件包混装。应先参考下方对应发行版的官方文档确认并卸载冲突包;卸载软件包通常不会自动删除已有镜像、容器和卷,但重要数据仍应提前备份。

macOS-Homebrew.sh
Windows-Installer.ps1
Ubuntu.sh
Debian.sh
Fedora.sh
Linux-quick-install.sh
1
brew update
2
brew install --cask docker-desktop
3
open -a Docker

macOS 也可以从 Docker 官方安装页 下载与 Apple 芯片或 Intel 芯片对应的 Docker.dmg,再将 Docker 拖入 Applications。Windows 可以从 Docker 官方安装页 下载图形化安装器,也可以通过 Microsoft Store 安装。Docker Desktop 首次启动时还需要接受许可协议并完成初始化。

Windows 默认使用 WSL 2 后端。如果 wsl --version 没有输出版本信息,需要以管理员身份打开 PowerShell,执行 wsl --install,重启 Windows 后再执行 wsl --update 和 Docker Desktop 安装命令。还要确认 BIOS 或 UEFI 中已经开启硬件虚拟化。

Ubuntu、Debian 和 Fedora 标签使用 Docker 官方软件仓库,后续可以继续通过系统包管理器升级。Linux-quick-install.sh 使用 Docker 提供的快捷脚本,只适合本地学习、测试或临时开发环境。执行之前应先查看 --dry-run 输出;生产服务器应该使用对应发行版的软件仓库,明确管理安装版本和升级过程。

Linux 安装完成后,默认可能只能通过 sudo docker 访问 Docker Engine。如果希望后续命令不带 sudo,可以把当前用户加入 docker 组:

docker-group.bash
1
sudo usermod -aG docker "$USER"
2
newgrp docker

docker 组拥有接近 root 的主机权限,只能加入可信用户。也可以不修改用户组,继续为后续 Docker 命令添加 sudo;对权限隔离要求更高时,应使用 Docker 的 rootless 模式。

安装后要先启动 Docker Desktop 或 Docker Engine,再在终端执行:

check-docker.bash
1
docker --version
2
docker compose version
3
docker info
4
docker run --rm hello-world

前两条命令确认 Docker CLI 与 Compose 插件已经安装,docker info 会连接 Docker Engine,最后一条命令会下载并运行一个一次性测试容器。如果前两条有版本输出,但 docker info 提示无法连接守护进程,通常是 Docker Desktop 尚未启动、Docker 服务没有运行,或者当前用户没有访问 Docker Engine 的权限。

接下来的命令都要在 FastAPI 项目根目录执行。可以先确认当前位置,再查看现有文件:

check-project-directory.bash
1
pwd
2
ls

项目根目录是 pyproject.toml 等项目文件所在的位置,也是我们接下来创建 compose.yaml 的位置。Compose 默认会从当前目录寻找这个文件,因此在错误目录执行命令,经常会得到找不到配置文件的提示。

2. Compose 配置

在 FastAPI 项目根目录创建 compose.yaml:

compose.yaml
01
services:
02
postgres:
03
image: postgres:18
04
environment:
05
POSTGRES_DB: task_app
06
POSTGRES_USER: task_app
07
POSTGRES_PASSWORD: task_app_dev_password
08
ports:
09
- "127.0.0.1:5432:5432"
10
volumes:
11
- postgres_data:/var/lib/postgresql
12
healthcheck:
13
test: ["CMD-SHELL", "pg_isready -U task_app -d task_app"]
14
interval: 5s
15
timeout: 3s
16
retries: 10
17
start_period: 10s
18
19
volumes:
20
postgres_data:

postgres:18 固定了 PostgreSQL 的大版本,避免重新拉取镜像时意外跨大版本升级。这个标签仍会随 PostgreSQL 18 的修订版本更新;本地学习环境可以及时获得缺陷和安全修复,生产环境则需要结合升级流程决定是否固定到更精确的标签或镜像摘要。

端口映射由三部分组成:

port-mapping.txt
1
127.0.0.1 : 5432 : 5432
2
绑定地址 宿主机 容器

它把宿主机的 127.0.0.1:5432 转发到容器内的 5432。显式绑定 127.0.0.1,可以避免这个本地教学数据库监听所有宿主机网络接口。同一 Compose 网络中的其他容器访问 PostgreSQL 时,不经过这条端口映射,而是通过服务名 postgres 连接。

PostgreSQL 官方镜像从 18 开始使用版本化的数据目录,默认 PGDATA 是 /var/lib/postgresql/18/docker,镜像声明的卷挂载点则改为 /var/lib/postgresql。因此 PostgreSQL 18 应该像示例一样,把命名卷挂载到 /var/lib/postgresql。PostgreSQL 17 及更早版本通常挂载 /var/lib/postgresql/data,不能在不同大版本之间机械复制配置,更不能只更换镜像标签来升级已有数据。

三个 POSTGRES_* 环境变量负责第一次初始化:

变量初始化时的作用
POSTGRES_DB创建名为 task_app 的数据库
POSTGRES_USER创建名为 task_app 的 PostgreSQL 超级用户
POSTGRES_PASSWORD设置该超级用户的密码

这些变量只在数据目录为空时生效。命名卷一旦完成初始化,后来修改用户名、数据库名或密码并不会自动改动已有数据库。

这里的账号和密码只用于本地学习。官方镜像会赋予 POSTGRES_USER 指定的角色超级用户权限,生产应用不应该直接使用这个初始化超级用户,而应该创建权限受限的应用角色,并通过密钥管理方案提供密码。

3. 校验与启动

启动之前,先让 Compose 解析并校验配置:

validate-compose.bash
1
docker compose config --quiet

命令没有输出并以成功状态结束,表示 YAML 可以被 Compose 正常解析。它只能检查配置结构,不能证明端口没有被占用,也不会尝试连接数据库。

接着创建容器并等待健康检查通过:

start-postgres.bash
1
docker compose up -d --wait postgres

第一次执行时,Docker 会先下载 PostgreSQL 镜像,因此等待时间可能稍长。-d 让容器在后台运行,--wait 会一直等待服务进入 running 或 healthy 状态。当前配置提供了健康检查,所以命令会等到 PostgreSQL 可以接收连接后再返回。

如果本机 Compose 版本不支持 --wait,可以先更新 Docker,也可以使用下面的方式启动后自行查看状态:

start-without-wait.bash
1
docker compose up -d postgres
2
docker compose ps

无论使用哪一种方式,都可以再次查看容器状态:

postgres-status.bash
1
docker compose ps postgres

正常情况下,状态中会出现 healthy。也可以手动执行与健康检查相同的命令:

check-postgres-ready.bash
1
docker compose exec postgres pg_isready -U task_app -d task_app

看到 accepting connections,说明服务正在接收连接。pg_isready 检查的是服务器状态,即使提供了错误的用户名或数据库名,也可能返回服务已就绪,因此它不能代替后面的真实登录与 SQL 验证。

启动失败时先查看最近的日志:

postgres-logs.bash
1
docker compose logs --tail=100 postgres

需要持续观察日志时再添加 -f:

follow-postgres-logs.bash
1
docker compose logs -f postgres

日志中出现 database system is ready to accept connections,表示 PostgreSQL 已经完成启动。按 Ctrl + C 只会结束日志跟踪,不会停止后台容器。

正在验证登录状态
请稍候,验证完成后将继续显示文章内容