跳至主要内容

PostgreSQL in Docker: A Step-by-Step Guide for Beginners

从搭建到最佳实践的完整指南,帮助您在 Docker 中运行 PostgreSQL,顺畅提升开发工作流、避免踩坑。
· 15分钟 阅读

使用 AI 探索

搭建 PostgreSQL 开发环境不该耗费数小时进行配置与排错——有了 Docker,这一点完全不必担心。

无论您的操作系统是什么,Docker 都能让您在几分钟内轻松启动并运行 PostgreSQL。只需几条命令,您就能创建一个与系统隔离的、功能完备的数据库环境,避免依赖冲突和安装麻烦。

在 Docker 中使用 PostgreSQL,您可以放心试验而不必担心破坏本地环境。您可以轻松创建、修改或删除数据库实例,测试不同的 PostgreSQL 版本,并在需要时随时恢复到干净状态。

在本指南中,我将带您全面了解如何在 Docker 容器中运行 PostgreSQL,助您获得顺畅的开发体验。

>对 PostgreSQL 经验不多?我们的入门课程可帮助您快速上手。

为什么在 Docker 中使用 PostgreSQL?

在 Docker 之前,搭建数据库常常意味着要遵循冗长的安装指南、解决系统特定问题,并小心管理系统依赖。Docker 完全改变了这种范式。

>究竟什么是 PostgreSQL 数据库?了解其工作原理、常见用例与学习资源。

在 Docker 中运行 PostgreSQL 的优势

Docker 为运行 PostgreSQL 数据库提供了一种优雅方式。与传统安装方法相比,它带来几项不言自明的好处:

  • 简化的安装与设置: 使用 Docker,您只需一条命令即可启动一个 PostgreSQL 实例。无需再处理软件包管理器、系统依赖或复杂的安装脚本。数据库带有合理的默认配置,开箱即用。
  • 团队环境一致性: 无论使用何种操作系统,团队里的每个人都能获得完全相同的 PostgreSQL 设置。这消除了开发团队中常见的“只在我电脑上能跑”的问题。
  • 与系统其他组件隔离: Docker 容器相互隔离,这意味着您的 PostgreSQL 实例不会干扰机器上的其他软件。您可以同时运行多个 PostgreSQL 版本而不发生冲突,移除 PostgreSQL 也只需停止并删除容器即可。
  • 数据库环境的版本可控: 您可以在配置文件中指定精确的 PostgreSQL 版本。这意味着开发环境可与生产环境完全一致,并且您可以在隔离环境中测试升级,然后再应用到生产系统。
  • 资源高效: 与虚拟机相比,Docker 容器更轻量。它们占用的系统资源更少,却能提供类似的隔离优势。这意味着您可以在不明显影响系统性能的情况下,将 PostgreSQL 与其他容器并行运行。

何时在 Docker 中使用 PostgreSQL

在容器化环境中与数据库打交道多年之后,我可以肯定地说,相较于传统安装方式,它带来了数不清的好处。

为简明起见,我只列举几点:

  • 本地开发环境: 对于使用 PostgreSQL 的应用开发者,Docker 提供了快速起步的方式,而无需更改本地系统。您可以轻松匹配生产环境中的数据库版本与配置,确保本地可运行的代码在部署后同样可用。
  • 微服务架构: 如果您在构建微服务应用,必要时每个服务都可以拥有自己的数据库实例。这为服务间提供更好的隔离,并允许各团队独立管理其数据库依赖。
  • CI/CD 流水线与自动化测试: Docker 让为测试创建全新数据库实例变得简单。每次测试都可以从干净的数据库状态开始,从而提升测试的可靠性。
  • 数据库迁移脚本开发: Docker 为测试数据库迁移提供了安全环境。您可以在与生产环境匹配的可丢弃数据库上验证迁移脚本,再将其应用到真实系统。
  • Kubernetes 部署: 如果您使用 Kubernetes 进行编排,在 Docker 中运行 PostgreSQL 是自然而然的选择。您的本地开发环境可与生产中的 Kubernetes 设置高度一致,使开发到生产的流程更加顺畅。

简而言之,容器化的 PostgreSQL 非常适合开发与测试,但同样需要注意,在生产环境中管理数据库部署还需额外考虑数据持久化、备份与高可用性等问题。

本文后面的章节将简单涉及这些考量。

在 Docker 中设置 PostgreSQL

在 Docker 中运行 Postgres 数据库,您唯一需要的就是 Docker 引擎本身。

本节将带您逐步完成前置条件,并在 Docker 容器中运行一个功能完整的 PostgreSQL 数据库。

前置条件

在开始在 Docker 中使用 PostgreSQL 之前,您需要在系统上安装 Docker。

安装方式因操作系统而异。Windows 和 macOS 用户可以直接安装Docker Desktop,这是一款用于管理容器的易用图形界面。请从 Docker 官方网站下载。

Linux 用户可以使用发行版的包管理器直接安装 Docker Engine。以 Ubuntu 为例:

sudo apt update
sudo apt install docker.io
sudo systemctl enable --now docker

除了安装 Docker,建议您熟悉基本的终端命令和 Docker 基本概念,例如镜像、容器和卷。以下来自 DataCamp 的实用指南可供参考:

拉取 PostgreSQL 的 Docker 镜像

在运行 PostgreSQL 之前,您需要从 Docker Hub 下载官方 PostgreSQL Docker 镜像。该镜像作为创建容器的模板。

要拉取最新的 PostgreSQL 镜像,请打开终端或命令提示符并运行:

docker pull postgres

该命令会下载最新的稳定版 PostgreSQL。如果您需要特定版本,可以通过标签指定:

docker pull postgres:17

Image 1 - Pulling the latest stable version of PostgreSQL database image

图 1 - 拉取最新稳定版 PostgreSQL 数据库镜像

一些常用的 PostgreSQL 镜像标签包括:

  • postgres:latest - 最新的稳定版 PostgreSQL
  • postgres:17 - PostgreSQL 17.x 版本(17 的最新补丁)
  • postgres:17.4 - 指定的某个版本(此处为 17.4)。
  • postgres:bookworm - 基于 Debian Bookworm 发行版构建的 PostgreSQL。

您可以在 官方 PostgreSQL Docker Hub 页面查看所有可用标签。

在 Docker 容器中运行 PostgreSQL

获取 PostgreSQL 镜像后,您可以通过一条命令创建并启动容器:

docker run --name postgres-db -e POSTGRES_PASSWORD=mypassword postgres

Image 2 - Starting a PostgreSQL container

图 2 - 启动一个 PostgreSQL 容器

该命令会创建一个名为 postgres-db 的新容器,并设置 PostgreSQL 密码的环境变量。

不过,这条基础命令有一些局限。我建议配合以下额外选项使用:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mypassword \
  -e POSTGRES_USER=myuser \
  -e POSTGRES_DB=mydatabase \
  -p 5432:5432 \
  -v postgres-data:/var/lib/postgresql/data \
  -d postgres

Image 3 - Starting a PostgreSQL container with env variables in detached mode

图 3 - 使用环境变量并以分离模式启动 PostgreSQL 容器

下面对这些附加选项逐一说明:

  • 环境变量:
    • POSTGRES_PASSWORD:为 PostgreSQL 超级用户设置密码(必需)。
    • POSTGRES_USER:创建一个具有该名称的超级用户(若未指定,默认为 "postgres")。
    • POSTGRES_DB: 创建一个具有该名称的数据库(若未指定,默认为用户名)。
  • 端口映射(-p 5432:5432)将容器内 PostgreSQL 端口(5432)映射到主机上的同一端口,您即可通过 localhost:5432 进行连接。
  • 卷挂载(-v postgres-data:/var/lib/postgresql/data)创建一个名为 postgres-data 的 Docker 卷,将数据库文件持久化到容器外部,确保容器停止或被删除时数据不会丢失。
  • -d 标志让容器以分离模式运行。通俗来说,就是让容器在后台运行。

您可以通过以下命令验证容器是否正在运行:

docker ps

Image 4 - Listing all running containers

图 4 - 列出所有正在运行的容器

下一节将演示如何根据特定用例进一步配置您的 PostgreSQL 容器。

在 Docker 中配置 PostgreSQL

上一节介绍的基础设置可以帮助您快速上手,但更高级的场景下,您很可能希望自定义 PostgreSQL 容器。

本节将专门介绍这些配置。

使用卷设置持久化存储

在 Docker 中运行数据库,最重要的一点是确保数据在容器生命周期之外仍然持久保存。默认情况下,容器内的数据在容器被删除后会丢失。对于数据库而言,这几乎从来不是您想要的结果。

Docker 卷通过将数据存储在容器文件系统之外来解决这个问题。

设置步骤首先从创建一个命名卷开始:

docker volume create postgres-data

您也可以选择通过以下命令查看该卷的详细信息:

docker volume inspect postgres-data

Image 5 - Listing volume details

图 5 - 列出卷的详细信息

接着,在启动 PostgreSQL 容器时,将该卷挂载到 PostgreSQL 的数据目录:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -v postgres-data:/var/lib/postgresql/data \
  -d postgres

-v postgres-data:/var/lib/postgresql/data 参数会将命名卷连接到容器的数据目录。

总而言之,在 PostgreSQL 中使用卷具有以下优势:

  • 即使删除容器,您的数据也会保留。
  • 可以在不丢失数据的情况下停止、启动或升级容器。
  • 可以通过备份卷来创建数据备份。
  • 与绑定挂载相比具有更好的性能(尤其在 macOS 和 Windows 上)。

暴露端口以连接 PostgreSQL

要从主机上运行的应用程序连接到 PostgreSQL 数据库,您需要将 PostgreSQL 端口(5432)暴露给本地系统。

最简单的方法是将容器的 5432 端口映射到主机上的同一端口:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5432:5432 \
  -d postgres

-p 5432:5432 参数将容器的 5432 端口映射到主机的 5432 端口。

如果您的主机上已有 PostgreSQL 或其他服务占用了 5432 端口,可以映射到另一个端口:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 5433:5432 \
  -d postgres

现在,容器内的 5432 端口映射到主机的 5433 端口。连接时,您需要指定 5433 而不是默认的 5432。

默认情况下,端口会在所有网络接口(0.0.0.0)上暴露。为了增强安全性,您也可以将其限制为 localhost:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 127.0.0.1:5432:5432 \
  -d postgres

这将仅允许来自本机的连接,而不接受来自网络中其他机器的连接。

配置 PostgreSQL 设置

在启动容器时,您可以更改许多 PostgreSQL 的默认设置。常见(但并非唯一)的方法是使用环境变量。

以下是可用于配置数据库的一些变量:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -e POSTGRES_USER=myuser \
  -e POSTGRES_DB=mydatabase \
  -e POSTGRES_INITDB_ARGS="--data-checksums" \
  -e POSTGRES_HOST_AUTH_METHOD=scram-sha-256 \
  -d postgres

每个变量的作用如下:

  • POSTGRES_PASSWORD:设置超级用户密码(必需)。
  • POSTGRES_USER:设置超级用户名(默认 "postgres")。
  • POSTGRES_DB:设置默认数据库名称(默认与用户名相同)。
  • POSTGRES_INITDB_ARGS:向 PostgreSQL 的 initdb 命令传递参数。
  • POSTGRES_HOST_AUTH_METHOD:设置认证方式。

除了环境变量,您还可以通过自定义 PostgreSQL 配置文件,对数据库进行更高级的配置更改。

一些常见的 PostgreSQL 可配置项包括:

  • max_connections:控制 PostgreSQL 可接受的连接数(默认 100)。
  • shared_buffers:设置用于缓存的内存(默认值在生产环境中通常偏低)。
  • work_mem:用于查询操作的内存。
  • maintenance_work_mem:用于维护操作的内存。

在实际操作中,先创建一个文件,命名为 my-postgres-conf:

max_connections = 200
shared_buffers = 1GB
work_mem = 16MB
maintenance_work_mem = 256MB

然后在运行容器时挂载该文件:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -v ./my-postgres.conf:/etc/postgresql/postgresql.conf \
  -v postgres-data:/var/lib/postgresql/data \
  -d postgres \
  -c 'config_file=/etc/postgresql/postgresql.conf'

简而言之,通过正确配置持久化、网络访问和 PostgreSQL 设置,您可以创建一个完全符合期望的基于 Docker 的 PostgreSQL 环境。postgres:latest 只是基础镜像——还有很多可以微调的空间。

下一节将介绍如何连接到在 Docker 中运行的 PostgreSQL 数据库。

连接在 Docker 中运行的 PostgreSQL

现在您的 PostgreSQL 容器已经启动,下一步就是连接它。毕竟,运行数据库就是为了使用它。

本节将演示两种连接容器化 PostgreSQL 数据库的方法:使用命令行工具 psql,以及使用图形界面。

作为参考,我的数据库容器是通过以下命令启动的:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -e POSTGRES_USER=myuser \
  -e POSTGRES_DB=mydatabase \
  -v postgres-data:/var/lib/postgresql/data \
  -p 5432:5432 \
  -d postgres

使用 psql 命令行工具连接

psql 命令行工具是官方 PostgreSQL 客户端,允许您使用 SQL 命令与数据库交互。

要从主机连接到容器中运行的 PostgreSQL 数据库,请运行以下命令,但记得更新用户名和数据库名:

docker exec -it postgres-db psql -U myuser -d mydatabase

Image 6 - Connecting to Postgres database using psql

图 6 - 使用 psql 连接 Postgres 数据库

就是这么简单!

如果您不确定该命令在做什么,下面是简要说明:

  • docker exec -it postgres-db:在名为 "postgres-db" 的容器内以交互方式运行命令。
  • psql -U myuser -d mydatabase:启动 psql,并以 "myuser" 用户连接到 "mydatabase" 数据库。

如果连接遇到问题,请检查以下常见原因:

  • 使用 docker ps 确认容器正在运行。
  • 使用 docker port postgres-db 验证端口映射。

使用图形界面工具连接

许多开发者更喜欢用图形工具而不是命令行——我也一样。pgAdmin 是 PostgreSQL 的一款流行且免费的选择,但在其他工具(如 DBeaver、DataGrip 或 TablePlus)中的连接流程也类似。

pgAdmin 的安装很简单,这里不再赘述。

假设您已经安装并打开它,在浏览器面板中右键点击 "Servers",选择 "Register > Server"。然后在 General 选项卡中,为连接起一个名称:

Image 7 - pgAdmin general tab

图 7 - pgAdmin General 选项卡

然后切换到 "Connection" 选项卡,填写以下信息:

  • Host name/address:localhost
  • Port:5432(或您映射的端口)
  • Maintenance database:mydatabase
  • Username:myuser
  • Password:您的 PostgreSQL 密码

Image 8 - pgAdmin connection tab

图 8 - pgAdmin Connection 选项卡

最后,点击 "Save" 进行连接:

Image 9 - Successful connection

图 9 - 连接成功

连接成功后,您就可以像使用本地安装或云上实例一样开始操作数据库。Docker 的妙处在于,从应用或客户端的角度看,两者没有区别——它就是一个可在指定地址访问的 PostgreSQL 数据库。

>需要以编程方式访问您的 PostgreSQL 数据库?了解如何通过 Python 进行访问。

下一节将介绍如何管理 PostgreSQL 容器,包括停止、启动和监控。

在 Docker 中管理 PostgreSQL

在容器中运行并连接到 PostgreSQL 是一回事,而管理又是另一回事。好在您可以用上一组简单的命令。

本节将介绍停止与启动容器、查看日志以及保持 PostgreSQL 版本最新等基本操作。

停止、重启和删除 PostgreSQL 容器

Docker 的命令行工具可用于管理 PostgreSQL 容器的生命周期。

要停止正在运行的 PostgreSQL 容器,请运行:

docker stop postgres-db

同样地,需要再次启动时,请运行:

docker start postgres-db

Image 10 - Stopping and starting the container

图 10 - 停止与启动容器

如果您想重启正在运行的容器(在修改某些配置后很有用),请运行:

docker restart postgres-db

当完全不再需要某个容器并希望删除它时,可使用以下两条命令:

docker stop postgres-db
docker rm postgres-db

请记住,删除容器不会删除您的数据,前提是您已正确设置卷。您的数据仍保存在之前创建的 postgres-data 卷中。

您可以通过以下命令验证容器是否已被删除:

docker ps -a

-a 标志会显示所有容器,包括已停止的。如果容器已成功删除,它将不会出现在列表中:

Image 11 - Listing all containers

图 11 - 列出所有容器

查看日志

当出现问题或需要监控数据库活动时,查看日志通常是第一步。

运行以下命令查看 PostgreSQL 容器的日志:

docker logs postgres-db

该命令会显示自容器启动以来的全部日志。若日志量很大,您可能希望限制输出,比如仅查看最近 50 条:

docker logs --tail 50 postgres-db

Image 12 - Viewing container logs

图 12 - 查看容器日志

另一方面,如果希望实时跟踪日志,可以运行:

docker logs -f postgres-db

Image 13 - Viewing container logs in real time

图 13 - 实时查看容器日志

在调试连接问题或在开发期间观察数据库活动时,这尤其有用。

按 Ctrl+C/CMD+C 停止跟踪日志。

在 Docker 中更新 PostgreSQL

随着时间推移,您会希望更新 PostgreSQL,以获得新功能、性能改进和安全补丁。

在撰写本文时,postgres:17.4 是最新版本,但我们假设 postgres:17.5 已发布。本节将展示如何在容器中更新数据库版本。

首先,拉取最新(或指定)版本的 PostgreSQL 镜像:

docker pull postgres:17.5

接着,停止并删除现有容器:

docker stop postgres-db
docker rm postgres-db

最后,使用相同的卷创建新容器:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -e POSTGRES_USER=myuser \
  -e POSTGRES_DB=mydatabase \
  -v postgres-data:/var/lib/postgresql/data \
  -p 5432:5432 \
  -d postgres:17.5

由于使用了相同的卷(postgres-data),您所有的现有数据都会被保留。

如果升级到新的主版本(例如从 17 到 18),PostgreSQL 启动时会自动执行必要的数据迁移。但请注意以下事项:

  • 主版本升级应先在非生产环境中进行测试。
  • 在进行主版本升级之前务必备份数据卷。
  • 查看 PostgreSQL 发布说明以了解潜在的不兼容变更。

要在升级前创建备份,请运行以下命令:

docker run --rm -v postgres-data:/data -v $(pwd):/backup postgres:17.4 \
  bash -c "pg_dumpall -U myuser > /backup/postgres_backup.sql"

该命令会在您当前目录创建一个 SQL 备份文件,若出现问题可用于还原数据。

>在 Docker 中工作时,您可能会觉得我们的 PostgreSQL 基础速查表很方便,可作为快速参考。

下一节将介绍在 Docker 中使用 PostgreSQL 的最佳实践,包括安全考虑和优化建议。

在 Docker 中使用 PostgreSQL 的最佳实践

Docker 的灵活性伴随着责任。本节将分享一些最佳实践,确保容器化的 PostgreSQL 设置可靠、安全并符合业界标准。

通过定期备份保护数据安全

无论以何种方式运行 PostgreSQL,定期备份都是必不可少的。先前章节已提及备份,这里再进一步展开。

在 Docker 中备份 PostgreSQL 数据库的最简单方法是使用 pg_dump:

docker exec -t postgres-db pg_dump -U myuser mydatabase > backup.sql

Image 14 - PostgreSQL backup

图 14 - PostgreSQL 备份

要对所有数据库(包括角色与表空间)进行完整备份,请使用 pg_dumpall:

docker exec -t postgres-db pg_dumpall -U myuser > full_backup.sql

Image 15 - Full PostgreSQL database backup

图 15 - PostgreSQL 数据库完整备份

图片中仅展示了几条备份命令,完整输出无法全部放入屏幕。

要自动化备份,您可以编写一个简单的 Shell 脚本,并通过 cron 定时运行:

#!/bin/bash
# backup.sh
TIMESTAMP=$(date +"%Y%m%d")
BACKUP_DIR="/Users/dradecic/Documents/pg-backups"

# 确保备份目录存在
mkdir -p $BACKUP_DIR

# 创建备份
docker exec postgres-db pg_dumpall -U myuser | gzip > $BACKUP_DIR/postgres_$TIMESTAMP.sql.gz

# 删除 30 天前的备份
find $BACKUP_DIR -name "postgres_*.sql.gz" -mtime +30 -delete

将脚本设为可执行并运行:

chmod +x backup.sh

bash backup.sh

Image 16 - Running a PostgreSQL database backup script

图 16 - 运行 PostgreSQL 数据库备份脚本

若要完全自动化备份,您可以将脚本添加到crontab 中每天定时执行:

0 3 * * * /path/to/backup.sh

该计划任务会在每天凌晨 3 点运行备份,当然您可按需调整时间与频率。

>查看我关于cron 作业的完整指南,进一步了解这一实用的自动化工具。

在生产环境中,建议将备份存放在异地或云存储中以用于灾难恢复。

使用命名卷实现数据持久化

虽然之前简要介绍过卷,但这里值得更深入地回顾。

通常情况下,您绝不应该在未正确配置卷的情况下在 Docker 中运行 PostgreSQL。否则,一旦容器被删除或 Docker 进行清理操作,数据将丢失。

使用命名卷(而非匿名卷)能让数据备份与管理更加方便:

# 创建命名卷
docker volume create postgres-data

# 运行容器时使用该卷
docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -v postgres-data:/var/lib/postgresql/data \
  -d postgres

这一点并不新鲜。

命名卷也更易于备份。要备份整个卷,请运行:

docker run --rm -v postgres-data:/data -v $(pwd):/backup alpine tar czf /backup/postgres-data-backup.tar.gz /data

这会在执行命令的同一文件夹下生成 postgres-data-backup.tar.gz 文件。

要还原该卷,请运行:

docker run --rm -v postgres-data:/data -v $(pwd):/backup alpine sh -c "cd /data && tar xzf /backup/postgres-data-backup.tar.gz --strip 1"

就这样!

在 Docker 中保护 PostgreSQL 安全

对于数据库而言,安全绝不能事后补救。本小节将介绍一些用于保护 PostgreSQL 容器的基本实践。

使用强且唯一的密码

避免使用默认或弱密码。为 PostgreSQL 超级用户生成一个强且随机的密码:

export POSTGRES_PASSWORD=$(openssl rand -base64 32)
echo "$POSTGRES_PASSWORD" > postgres-password.txt

docker run --name postgres-db \
  -e POSTGRES_PASSWORD="$POSTGRES_PASSWORD" \
  -v postgres-data:/var/lib/postgresql/data \
  -d postgres

Image 17 - Using a secure password

图 17 - 使用安全密码

请将此密码安全保存,例如存入密码管理器或未纳入版本控制的环境变量文件。

限制网络访问

默认情况下,Docker 会在所有接口上暴露 PostgreSQL 端口。为提高安全性,尤其在生产环境中,请将访问限制到本机:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -p 127.0.0.1:5432:5432 \
  -v postgres-data:/var/lib/postgresql/data \
  -d postgres

使用自定义 PostgreSQL 配置

通过修改如下参数来创建更安全的 PostgreSQL 配置:

# 要求启用 SSL
ssl = on
ssl_cert_file = '/etc/ssl/certs/ssl-cert-snakeoil.pem'
ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key'

# 限制连接尝试
max_connections = 100
authentication_timeout = 1min

# 限制访问
listen_addresses = 'localhost'

在启动容器时挂载该配置文件:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -v ./pg_hba.conf:/var/lib/postgresql/data/pg_hba.conf \
  -v ./postgresql.conf:/var/lib/postgresql/data/postgresql.conf \
  -v postgres-data:/var/lib/postgresql/data \
  -d postgres

定期更新 PostgreSQL 镜像

保持 PostgreSQL 版本为最新,以获取最新的安全修复:

docker pull postgres:latest
docker stop postgres-db
docker rm postgres-db
# 然后使用最新镜像重新创建

按照这些最佳实践,您可以在 Docker 中构建更可靠、更安全的 PostgreSQL 环境,适用于开发与生产场景。

下一节将介绍在 Docker 中运行 PostgreSQL 时的常见问题排查方法。

在 Docker 中排查 PostgreSQL 问题

在 Docker 中运行 PostgreSQL,迟早会遇到问题。本节将介绍常见问题及其解决方案,帮助您节省时间,避免不必要的挫败感。

PostgreSQL 容器的常见问题

许多用户常遇到的一个问题是容器启动后立即退出。若出现这种情况,请先查看日志以定位问题:

docker logs postgres-db

错误可能与挂载卷的权限问题有关。如果是这样,日志中会出现类似消息:

initdb: could not change permissions of directory "/var/lib/postgresql/data": Operation not permitted

要解决该问题,请检查卷的所有权和权限,并在需要时修复:

# 检查所有权
docker run --rm -v postgres-data:/data alpine ls -la /data

# 修复权限
docker run --rm -v postgres-data:/data alpine chmod 700 /data

另一类常见问题是缺少必需的环境变量。典型日志消息如下:

Database is uninitialized and superuser password is not specified

要解决,请确保设置了必需的 POSTGRES_PASSWORD 环境变量——以及其他必要的变量:

docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -v postgres-data:/var/lib/postgresql/data \
  -d postgres

“数据目录不为空但缺少 PostgreSQL 文件”的错误也很常见。您可能会看到如下日志消息:

PostgreSQL Database directory appears to contain a database; Skipping initialization

随后会出现有关缺少文件的报错。

这通常发生在您挂载了一个包含文件但不包含有效 PostgreSQL 数据库的卷时。您可能需要使用一个新卷重新初始化:

docker volume create postgres-data-new
docker run --name postgres-db \
  -e POSTGRES_PASSWORD=mysecretpassword \
  -v postgres-data-new:/var/lib/postgresql/data \
  -d postgres

排查连接问题

如果您无法连接到容器中运行的 PostgreSQL 数据库,先从确认容器正在运行开始:

docker ps | grep postgres-db

如果未列出,可能已崩溃。按前文所述检查日志。

如果已列出但仍无法连接,核对端口映射:

docker port postgres-db

您应看到类似如下的输出:

Image 18 - Container port mapping

图 18 - 容器端口映射

如果不是,说明端口映射可能有误。请使用正确的 -p 选项重新创建容器。

如果仍无法连接数据库,接下来需要检查连接设置。请核对以下参数:

  • 主机名: localhost 或 127.0.0.1(而非容器名)。
  • 端口: 端口映射中的主机端口(通常为 5432)。
  • 用户名: POSTGRES_USER 的值(默认是 "postgres")。
  • 密码: POSTGRES_PASSWORD 的值。
  • 数据库: POSTGRES_DB 的值(默认与 POSTGRES_USER 相同)。

逐一处理后重试。如果问题仍然存在,您应当在容器内测试连通性:

docker exec -it postgres-db psql -U postgres

如果可行,问题出在端口映射或外部网络。

最后,您可以检查防火墙问题。系统防火墙可能会阻止对 PostgreSQL 端口的连接,请检查:

# Linux
sudo iptables -L | grep 5432

# macOS
sudo pfctl -sr | grep 5432

通过检查这些常见问题,您应该能够识别并解决大多数在 Docker 中使用 PostgreSQL 时遇到的问题。若仍未解决,PostgreSQL 与 Docker 的文档及社区论坛是获取更具体排障建议的绝佳资源。

总结:Docker 中的 PostgreSQL 数据库

到这里就结束了——这是一份在 Docker 中配置并运行 PostgreSQL 数据库的终极指南!我们已覆盖从启动第一个容器到配置、连接与管理数据库所需的一切内容。

传统的 PostgreSQL 方案(本地安装或云端资源配置)对于开发用途往往不够理想或成本较高。Docker 填补了这一空白。无论用于本地开发、测试还是生产环境,容器化 PostgreSQL 都能提供难以匹敌的灵活性与一致性。

现在,您已经完全有能力将容器化的 Postgres 数据库集成到您的应用中了。

如果您想进一步深入学习,推荐这些来自 DataCamp 的课程:

常见问题解答

与传统安装相比,为什么要在 Docker 中运行 PostgreSQL?

在 Docker 中使用 PostgreSQL 可以简化安装、在不同机器间提供一致的环境,并与系统其他组件隔离。它允许您同时运行多个 PostgreSQL 版本且互不冲突,使升级与降级更容易,并能快速搭建与拆除用于开发和测试的环境。与虚拟机相比,Docker 容器还占用更少的系统资源。

如何连接运行在 Docker 中的 PostgreSQL 数据库?

您可以使用命令 docker exec -it postgres-db psql -U myuser -d mydatabase 直接在容器中访问 psql 命令行工具来连接运行在 Docker 中的 PostgreSQL 数据库。或者,您也可以使用 pgAdmin、DBeaver 或 TablePlus 等图形化工具,使用您映射的端口(通常为 5432)连接到 localhost(或 127.0.0.1),并输入配置的用户名和密码。

当我移除 Docker 容器时,PostgreSQL 数据会怎样?

当您移除一个 Docker 容器时,除非已设置卷,否则存储在容器内部的任何数据都会丢失。通过使用命名卷(如 docker volume create postgres-data),您的数据库数据会持久化在容器文件系统之外。这意味着只要在创建新容器时挂载相同的卷,您就可以安全地停止、移除或升级 PostgreSQL 容器而不会丢失数据。

如何备份运行在 Docker 中的 PostgreSQL 数据库?

要备份运行在 Docker 中的 PostgreSQL 数据库,您可以使用 pg_dump 命令,例如:docker exec -t postgres-db pg_dump -U myuser mydatabase > backup.sql。若要进行包含所有数据库与角色的完整备份,请改用 pg_dumpall。您可以通过结合 cron 定时任务的 shell 脚本实现备份自动化,并加入压缩与旧备份轮替等功能。

Dario Radečić

作者

Dario Radečić

常驻克罗地亚的高级数据科学家。顶级科技写作者,已发表 700 多篇文章,累计获得超过 1,000 万次阅读。著有《使用 TPOT 实现机器学习自动化》。

主题