Data Engineering Zoomcamp 教程:使用 Docker Compose 一键编排 PostgreSQL 与 pgAdmin 多容器数据管道
【免费下载链接】data-engineering-zoomcampData Engineering Zoomcamp is a free 9-week course on building production-ready data pipelines. Join the course here 👇🏼项目地址: https://gitcode.com/GitHub_Trending/da/data-engineering-zoomcamp
在 Data Engineering Zoomcamp 的 Docker 与 PostgreSQL 工作坊中,前几节分别讲解了如何用docker run启动 Postgres 容器(04-postgres-docker.md)、运行 pgAdmin 容器并手动创建共享网络(07-pgadmin.md),以及如何把数据摄取脚本打包成镜像(08-dockerizing-ingestion.md)。本节(09-docker-compose.md)引入 Docker Compose,用一份 YAML 配置文件同时管理 Postgres 与 pgAdmin 两个服务,免去逐条执行繁琐docker run命令的负担。读完本文,你将掌握docker-compose.yaml的完整编写与逐项参数含义、Compose 自动网络的工作原理、常用的启动/停止/日志/清理命令,以及如何让容器化的摄取脚本复用 Compose 创建的虚拟网络完成数据入库,为构建生产级多容器数据管道打下基础。
为什么需要 Docker Compose
回顾前几节的工作流,启动整套数据环境需要依次执行多条命令:
- 运行 Postgres 容器(见 04-postgres-docker.md):需要
-e设置环境变量、-v挂载卷、-p映射端口; - 运行 pgAdmin 容器(见 07-pgadmin.md):需要先
docker network create pg-network手动建网,再给两个容器分别加--network=pg-network与--name参数,才能让它们互相发现。
这些命令冗长、易错,且每次启动都要重复输入。docker compose的核心价值就在于:用单个配置文件描述一组容器及其网络、卷、端口等全部细节,一条命令同时启动(或停止)所有服务,从而替代多条复杂的docker run。
从仓库中的辅助脚本也能看到这种"命令越来越多"的趋势:docker-postgres.sh 单独封装了 Postgres 容器的启动参数,而 Compose 则是把这类分散脚本统一收敛为声明式配置。
docker-compose.yaml 配置逐项解析
Docker Compose 使用 YAML 语法。工作坊提供的完整配置文件位于仓库的 pipeline/docker-compose.yaml,内容如下:
services: pgdatabase: image: postgres:18 environment: POSTGRES_USER: "root" POSTGRES_PASSWORD: "root" POSTGRES_DB: "ny_taxi" volumes: - "ny_taxi_postgres_data:/var/lib/postgresql" ports: - "5432:5432" pgadmin: image: dpage/pgadmin4 environment: PGADMIN_DEFAULT_EMAIL: "admin@admin.com" PGADMIN_DEFAULT_PASSWORD: "root" volumes: - "pgadmin_data:/var/lib/pgadmin" ports: - "8085:80" volumes: ny_taxi_postgres_data: pgadmin_data:services:容器即服务
文件顶层用services声明要运行的容器(Compose 中称为"服务")。本例包含两个服务:
pgdatabase(PostgreSQL 数据库)
image: postgres:18:使用 PostgreSQL 18 官方镜像(课程文档注明该版本为 2025 年 12 月时的 latest,04-postgres-docker.md 中的docker run也使用同一镜像);environment:对应docker run -e,设置POSTGRES_USER="root"、POSTGRES_PASSWORD="root"、POSTGRES_DB="ny_taxi",即数据库超级用户、密码与默认数据库名;volumes:对应docker run -v,将命名卷ny_taxi_postgres_data挂载到容器内/var/lib/postgresql,使数据在容器删除后依然持久化;ports:对应docker run -p,"5432:5432"将容器内 5432 端口映射到宿主机 5432,供 pgcli、摄取脚本或本地工具连接。
pgadmin(Web 管理界面)
image: dpage/pgadmin4:官方 pgAdmin 镜像;environment:设置登录邮箱PGADMIN_DEFAULT_EMAIL="admin@admin.com"与密码PGADMIN_DEFAULT_PASSWORD="root",与 07-pgadmin.md 中的docker run -e参数完全一致;volumes:pgadmin_data:/var/lib/pgadmin保存 pgAdmin 的服务器连接配置与偏好设置,重启容器后无需重新配置;ports:"8085:80",pgAdmin 是 Web 应用、容器内默认端口 80,映射到宿主机 8085 以避免与本地常见 80 端口冲突。
volumes:命名卷声明
文件底部单独声明了ny_taxi_postgres_data与pgadmin_data两个命名卷。这样写的好处是让 Docker 知道这些卷属于本项目生命周期管理范围:docker-compose down不会删除它们,而docker-compose down -v会连同卷一起移除(见下文"其他常用命令")。
对比 docker run:一条命令 vs 一份配置
Compose 文件中的每一段都可以与前几节的docker run参数一一对应:
| Compose 配置项 | 对应 docker run 参数 | 本例值 |
|---|---|---|
image | 镜像名 | postgres:18/dpage/pgadmin4 |
environment | -e | 用户、密码、数据库名 / 邮箱、密码 |
volumes | -v | 数据持久化命名卷 |
ports | -p | 5432:5432/8085:80 |
唯一不需要在文件里指定的是网络——这正是 Compose 相比手动docker run的关键差异。
Compose 的自动网络:容器按服务名互访
在原文档的"Explanation"部分特别强调:使用 Compose 时无需手动创建网络。Compose 会自动为项目创建一个默认网络,所有服务都加入该网络,并可通过服务名(pgdatabase、pgadmin)互相解析。
这与 07-pgadmin.md 中手动执行docker network create pg-network的做法形成鲜明对比:那里需要显式建网、给容器命名、逐个加--network参数;而 Compose 把这一过程完全自动化——服务名天然成为容器在网络中的主机名。
因此,在 pgAdmin 中注册 Postgres 服务器时,Connection 标签页的 Host 依然填pgdatabase(服务名即容器名),端口 5432,用户名/密码root/root,访问地址为http://localhost:8085。这套连接流程在 Compose 编排下与手动建网时完全一致,只是省去了建网步骤。
启动服务:前台与分离模式
在docker-compose.yaml所在目录(仓库中为01-docker-terraform/docker-sql/pipeline/)下执行:
docker-compose up前台模式会持续占用终端并实时输出所有容器的日志。启动前请确保之前手动docker run的容器已全部停止,避免端口(5432/8085)冲突。
若希望容器在后台运行、释放终端,使用分离模式:
docker-compose up -d两种方式都会按配置同时拉起 Postgres 与 pgAdmin 两个服务。
停止服务与常用管理命令
前台模式下按Ctrl+C即可关闭容器;更规范的做法是使用:
docker-compose downdown会停止并移除 Compose 管理的容器与默认网络,但保留命名卷中的数据,下次up时数据仍在。
其他常用命令(原文档"Other Useful Commands"一节):
# 查看所有服务的日志 docker-compose logs # 停止服务并同时删除命名卷(数据将丢失,谨慎使用) docker-compose down -vlogs:集中查看各容器输出,便于排查启动错误;down -v:额外移除volumes段声明的命名卷,相当于把数据库数据一并清空,适合完全重置实验环境。
配合 11-cleanup.md 可进一步用docker container prune、docker image prune、docker volume prune等命令清理不再使用的资源。
在 Compose 网络中运行摄取脚本
前几节构建的摄取镜像taxi_ingest:v001(构建过程见 08-dockerizing-ingestion.md,Dockerfile 位于 pipeline/Dockerfile)并不属于 Compose 管理的服务,而是通过docker run独立运行的。要让脚本容器访问到 Compose 网络中的 Postgres,必须显式指定网络。
查找 Compose 自动创建的网络名
docker network lsCompose 创建的默认网络命名规则为<项目目录名>_default。由于配置文件位于pipeline/目录,网络名通常为pipeline_default(若目录名不同则相应变化)。
运行摄取脚本
docker run -it --rm \ --network=pipeline_default \ taxi_ingest:v001 \ --pg-user=root \ --pg-pass=root \ --pg-host=pgdatabase \ --pg-port=5432 \ --pg-db=ny_taxi \ --target-table=yellow_taxi_trips要点说明:
--network=pipeline_default:加入 Compose 创建的虚拟网络,使脚本容器能与pgdatabase服务互相通信;--pg-host=pgdatabase:Postgres 在独立容器中运行,主机参数必须填容器/服务名pgdatabase,而不是localhost(容器内localhost指向脚本容器自身);--pg-user/--pg-pass/--pg-db/--target-table:对应 ingest_data.py 中 click 定义的命令行参数,其默认值分别为root、root、ny_taxi、yellow_taxi_data;- 脚本内部以
postgresql+psycopg://连接串通过 SQLAlchemy 建引擎,并按 100,000 行一批(chunksize)流式读取纽约出租车 CSV 数据,首块以replace建表、后续块append追加(见 ingest_data.py),因此重复运行会自动替换已有表。
这些连接参数与前几节手动建网时完全一致,唯一区别是网络名从手动创建的pg-network换成了 Compose 生成的pipeline_default。
Docker Compose 的工程收益
原文档总结的收益包括:
- 单命令启动全部服务:一个
up同时拉起 Postgres 与 pgAdmin; - 自动网络创建:省去手动建网与命名,服务名即可互访;
- 配置集中管理:环境变量、卷、端口全部声明在 YAML 中,可读、可版本化、可复用;
- 声明式基础设施:配置即代码(infrastructure as code),新环境复现只需同一份文件。
从数据工程实践角度看,这标志着从"记忆一串docker run命令"迈向"用声明式清单描述多容器数据环境",是后续课程中编排更复杂管道(如 Kestra、Spark 等)的认知基础。课程其余 Docker 部分(SQL 复习、资源清理)可在此基础上继续深入。
【免费下载链接】data-engineering-zoomcampData Engineering Zoomcamp is a free 9-week course on building production-ready data pipelines. Join the course here 👇🏼项目地址: https://gitcode.com/GitHub_Trending/da/data-engineering-zoomcamp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考