PostgreSQL Docker Compose 配置文件 (docker-compose.yml) 详解 – wiki词典

我将把文章保存在一个名为 postgres_docker_compose_guide.md 的 Markdown 文件中。

好的,这是一篇关于 PostgreSQL Docker Compose 配置文件 (docker-compose.yml) 的详细解析文章。


PostgreSQL Docker Compose 配置文件 (docker-compose.yml) 详解

在现代软件开发中,容器化技术已成为不可或缺的一部分。Docker 使得打包、分发和运行应用程序变得前所未有的简单。而当我们面对需要协同工作的多个容器(例如,一个 web 应用和一个数据库)时,Docker Compose 就成了管理这些多容器应用的首选工具。

PostgreSQL,作为一款功能强大且广受欢迎的开源对象-关系数据库系统,经常与各类应用服务一同部署。本文将详细探讨如何使用 Docker Compose 来定义和管理一个 PostgreSQL 服务,从基础配置到高级应用,帮助你完全掌握 docker-compose.yml 的使用。

1. 什么是 Docker Compose?

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过一个单独的 YAML 文件 (docker-compose.yml),你可以配置应用所需的所有服务(如数据库、后端 API、前端应用等)。然后,只需一个简单的命令,就可以根据配置创建并启动所有服务。

使用 Docker Compose 的核心优势:
* 简化管理:用一个文件定义整个应用栈,告别冗长的 docker run 命令。
* 环境一致性:确保在开发、测试和生产环境中拥有一致的运行环境。
* 服务编排:轻松定义服务间的依赖关系、网络和数据卷。

2. 基础的 PostgreSQL 配置

让我们从一个最简单的 docker-compose.yml 文件开始,这个配置足以启动一个可用的 PostgreSQL 实例。

docker-compose.yml
“`yaml

指定 docker-compose.yml 文件格式的版本

version: ‘3.8’

定义一系列服务

services:
# 服务名称,可以自定义,例如 ‘db’, ‘postgres’, ‘database’
postgres:
# 指定要使用的 Docker 镜像
# 格式为 ‘镜像名:标签’,这里使用官方的 postgres 镜像,版本为 13
image: postgres:13

# 设置容器的环境变量,用于初始化 PostgreSQL
environment:
  - POSTGRES_USER=myuser         # 设置超级用户的用户名
  - POSTGRES_PASSWORD=mypassword # 设置超级用户的密码
  - POSTGRES_DB=mydatabase       # 创建一个默认的数据库

# 将主机的端口映射到容器的端口
# 格式:'主机端口:容器端口'
# 这样我们就可以通过主机的 5432 端口访问容器内的 PostgreSQL 服务
ports:
  - "5432:5432"

“`

配置项解析

  • version: 定义了 docker-compose.yml 文件的版本。这很重要,因为它决定了你可以使用哪些语法和指令。推荐使用 '3.8' 或更高版本。
  • services: 这是文件的核心部分,用于定义应用包含的各个独立容器。
  • postgres: 这是我们为 PostgreSQL 服务指定的名称。在同一个 Docker Compose 网络中,其他服务可以通过这个名称来访问它。
  • image: postgres:13: 指定了 Docker 将从 Docker Hub 拉取的镜像。postgres 是官方镜像的名称,13 是其版本标签。你可以根据需要选择不同的版本(如 latest, 14-alpine 等)。
  • environment: 用于设置容器内的环境变量。对于官方 postgres 镜像,以下三个变量至关重要:
    • POSTGRES_USER: PostgreSQL 数据库的管理员用户名。
    • POSTGRES_PASSWORD: 对应用户的密码。注意:在生产环境中,切勿将密码硬编码在此文件中,后续会介绍更安全的方法。
    • POSTGRES_DB: 当容器首次启动时,会自动创建这个指定的数据库。
  • ports: 定义端口映射规则。"5432:5432" 的意思是将你宿主机器的 5432 端口映射到容器内部的 5432 端口(PostgreSQL 默认监听此端口)。这样,任何能访问你宿主机 IP 的数据库客户端(如 DBeaver, pgAdmin)都可以连接到这个数据库实例。

3. 数据持久化:使用 Volumes

上面的配置有一个严重的问题:当容器被删除时(例如执行 docker-compose down),所有存储在数据库中的数据都会丢失。这是因为数据默认存储在容器的可写层中。为了解决这个问题,我们需要将数据持久化到主机上,这就要用到 Docker Volumes

“`yaml
version: ‘3.8’

services:
postgres:
image: postgres:13
environment:
– POSTGRES_USER=myuser
– POSTGRES_PASSWORD=mypassword
– POSTGRES_DB=mydatabase
ports:
– “5432:5432”
# 将命名卷 ‘pgdata’ 挂载到容器内的 ‘/var/lib/postgresql/data’ 目录
volumes:
– pgdata:/var/lib/postgresql/data

在顶层定义 Docker 命名卷

volumes:
pgdata:
“`

新增配置项解析

  • volumes (服务层级): pgdata:/var/lib/postgresql/data 这行配置告诉 Docker:
    • 将一个名为 pgdata 的卷…
    • …挂载到容器的 /var/lib/postgresql/data 路径下。
    • postgres 镜像默认将其所有数据文件(如表、索引等)存储在 /var/lib/postgresql/data 目录。通过挂载,我们实际上是将这些数据重定向到了由 Docker 管理的 pgdata 卷中。
  • volumes (顶层): pgdata: 这部分声明了一个 命名卷 (Named Volume)。由 Docker 负责创建和管理这个卷,确保了即使容器被删除,卷中的数据依然存在。当你下次启动同一个服务并挂载此卷时,所有历史数据都会被恢复。

4. 高级配置与最佳实践

为了让我们的 PostgreSQL 服务更加健壮和安全,可以引入一些高级配置。

使用 .env 文件管理敏感信息

将密码等敏感信息直接写在 docker-compose.yml 中是危险的,因为它可能会被意外提交到版本控制系统(如 Git)。最佳实践是使用 .env 文件。

  1. docker-compose.yml 同级目录下创建一个名为 .env 的文件:

    .env
    POSTGRES_USER=myuser
    POSTGRES_PASSWORD=supersecretpassword
    POSTGRES_DB=mydatabase

  2. 修改 docker-compose.yml 来引用这些变量:

    “`yaml
    version: ‘3.8’

    services:
    postgres:
    image: postgres:13
    # Docker Compose 会自动加载 .env 文件并替换 ${…} 里的变量
    environment:
    – POSTGRES_USER=${POSTGRES_USER}
    – POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
    – POSTGRES_DB=${POSTGRES_DB}
    ports:
    – “5432:5432”
    volumes:
    – pgdata:/var/lib/postgresql/data
    # 添加重启策略
    restart: always

    volumes:
    pgdata:
    ``
    现在,你只需要将
    .env文件添加到.gitignore` 中,就能避免将密码泄露。

重启策略 (restart)

  • restart: always: 无论容器因何种原因退出(错误、手动停止),Docker 都会自动尝试重启它。这对于数据库这类需要持续运行的服务非常有用。
  • restart: on-failure: 只有在容器以非零状态码退出(即发生错误)时才重启。

服务间通信与网络

假设你还有一个 web 应用(例如一个 Node.js 服务)需要连接到这个数据库。你可以这样定义它们:

“`yaml
version: ‘3.8’

services:
webapp:
build: . # 假设 Dockerfile 在当前目录
ports:
– “3000:3000”
environment:
# 在应用代码中,使用服务名 ‘postgres’ 作为数据库主机地址
– DATABASE_HOST=postgres
– DATABASE_USER=${POSTGRES_USER}
– DATABASE_PASSWORD=${POSTGRES_PASSWORD}
– DATABASE_NAME=${POSTGRES_DB}
# 确保 postgres 服务先于 webapp 启动
depends_on:
– postgres
networks:
– app-net

postgres:
image: postgres:13
environment:
– POSTGRES_USER=${POSTGRES_USER}
– POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
– POSTGRES_DB=${POSTGRES_DB}
# 注意:这里不再需要 ports 映射,因为 webapp 和 postgres 在同一个内部网络中
# 只有当你需要从主机直接访问数据库时才需要 ports
volumes:
– pgdata:/var/lib/postgresql/data
restart: always
networks:
– app-net

定义自定义网络

networks:
app-net:
driver: bridge

volumes:
pgdata:
“`

  • networks: 我们创建了一个名为 app-net 的自定义桥接网络。将 webapppostgres 都加入这个网络后,它们就可以通过服务名直接通信。在 webapp 的配置中,数据库主机地址就是 postgres,而不是 localhost 或 IP 地址。
  • depends_on: webapp 依赖于 postgres,这保证了 Docker Compose 会先启动 postgres 容器,再启动 webapp 容器。但这仅仅是启动顺序,不保证 postgres 数据库服务在 webapp 启动时已经完全就绪。对于需要严格等待数据库可用的场景,通常需要配合 healthcheck 或在应用启动脚本中加入等待逻辑。

5. 常用命令

  • 启动服务(后台运行):
    bash
    docker-compose up -d
  • 停止并删除容器、网络:
    bash
    docker-compose down
  • 停止并删除容器、网络及数据卷危险操作,会删除所有数据):
    bash
    docker-compose down -v
  • 查看服务日志:
    bash
    docker-compose logs -f postgres
  • 执行一次性命令 (例如,进入 psql 命令行):
    bash
    docker-compose exec postgres psql -U myuser -d mydatabase

总结

通过 docker-compose.yml 文件,我们可以清晰、高效地定义和管理 PostgreSQL 服务。从一个满足基本开发需求的配置,到考虑了数据持久化、安全性和服务间通信的生产级配置,Docker Compose 都提供了强大的支持。

掌握这些知识,你就能轻松地将 PostgreSQL 集成到你的容器化开发流程中,极大地提升开发和部署效率。

滚动至顶部