Great Expectations 是一款开源的数据质量校验框架,能够通过声明式的 expectation suite 对数据管道中的表、文件进行自动化测试。将它与容器技术结合,可以让数据团队在不污染本地环境的前提下,快速获得可复现的校验运行环境。本文从镜像构建、配置与数据持久化、以及容器编排三个层面,说明如何把 Great Expectations 稳妥地跑在 Docker 中。

一、基于 Dockerfile 构建专用校验镜像
很多团队一开始尝试用 docker run python:3.9 然后进容器手动 pip 安装 great_expectations,这种做法在临时调试时可行,却不利于持续交付。更好的方式是写一份固定的 Dockerfile,把依赖锁死,保证每次构建出的镜像行为一致。Great Expectations 对 pandas、numpy 和 sqlalchemy 的版本较为敏感,建议在 requirements 中明确写出经过验证的版本号,避免自动拉取不兼容的新版。
下面给出一份精简但实用的 Dockerfile 示例。我们以 python:3.9-slim 为基础镜像,安装必要系统库以支持部分数据库驱动,随后用非 root 用户运行,提升安全性。注意在容器中创建专用工作目录,并把 great_expectations 目录初始化留到运行时挂载,而不是 baked 进镜像,这样 expectation suite 的变更不需要重新构建镜像。
FROM python:3.9-slim
RUN apt-get update && apt-get install -y
build-essential
libpq-dev
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
RUN useradd -m geuser
USER geuser
ENTRYPOINT ["great_expectations"]
对应的 requirements.txt 可参考如下内容,其中 great_expectations 版本按实际选用。把数据库驱动如 psycopg2-binary 或 pymysql 也写进去,容器就能直接连源库做校验,而不必在宿主机装驱动。
great_expectations==0.17.13 pandas==1.5.3 sqlalchemy==1.4.47 psycopg2-binary==2.9.6
构建命令很简单:docker build -t ge-ci:0.17 .。之后在 CI 里直接使用这个标签,就能确保开发、测试、生产跑的是同一套二进制环境。如果团队使用私有 PyPI,可在 pip 前用 pip config set global.index-url 指向内部源,避免外网不通导致构建失败。
二、配置目录与校验结果的持久化方案
Great Expectations 的核心资产包括 expectation_suite、checkpoint 配置、validation_results 以及用于存储指标的 sqlite 库。若这些文件写在容器内部可读写层,容器删除后全部丢失,也无法在宿主机查看报告。因此必须用 volume 或 bind mount 把 great_expectations 目录挂出来。一般建议把整个项目目录挂到 /app/great_expectations,并在镜像外维护 suite 的版本控制。
权限是常见陷阱。上面 Dockerfile 用了非 root 的 geuser,若宿主机挂载目录属主是 root 且权限为 755,容器用户可能无权写入 validation_results。解决办法是在宿主机提前 chown 1000:1000(若 geuser 的 uid 是 1000)或在 compose 中指定 user: "1000:1000"。另一种做法是运行时用命名卷,由容器首次启动生成结构,再配合 docker cp 把初始化的目录拿出来编辑。
docker run --rm -v $(pwd)/gx:/app/great_expectations -e GE_TMP_DIR=/app/great_expectations/tmp ge-ci:0.17 checkpoint run my_checkpoint
上面的命令把当前目录下的 gx 挂进容器。执行 checkpoint 后,结果会写在 gx/validation_results 中,团队成员可直接用 great_expectations docs build 在本地生成 HTML 报告,或把结果目录交给前端展示系统。对于需要跨容器共享结果的场景,可使用 NFS 或对象存储挂载,但要注意 sqlite 在多写者下会锁表,生产建议接 PostgreSQL 作为 metadata store。
时区问题也值得提一句。容器默认 UTC,若数据源带本地时区的时间字段,校验窗口可能算错。可在 Dockerfile 加 ENV TZ=Asia/Shanghai 并安装 tzdata,或在运行参数传 -e TZ=Asia/Shanghai,确保时间相关 expectation 如 expect_column_values_to_be_between 对日期边界的判断符合业务预期。
三、在编排环境中调度校验任务
当数据管道日均运行多次,手动起容器显然不够。在 Kubernetes 或 Docker Compose 中把 Great Expectations 作为批处理任务,是更成熟的用法。Compose 里可定义 service 为 profiles: [validate],平时不起,需要时 docker compose run validate 即可。K8s 则常用 CronJob,镜像填上面构建的 ge-ci,args 写 ["checkpoint","run","daily_etl_check"],配合 secret 挂载数据库密码。
下面是一段 Docker Compose 片段,展示如何把校验服务与结果可视化分离。validate 服务跑完退出,docs 服务用轻量 HTTP 服务器暴露报告,二者共享同一个卷。
version: "3.8"
services:
validate:
image: ge-ci:0.17
volumes:
- ./gx:/app/great_expectations
command: ["checkpoint","run","daily_etl_check"]
profiles: ["validate"]
docs:
image: nginx:alpine
volumes:
- ./gx/uncommitted/data_docs:/usr/share/nginx/html
ports:
- "8080:80"
在 K8s 环境,还要注意资源限制。Great Expectations 加载大表抽样时会占内存,若 limit 设太小会被 OOMKilled。可通过 expect_column_values_to_be_in_set 等轻量 expectation 代替全量统计,或在数据源侧先用 SQL 做聚合再校验。另外把失败告警接进 Slack 或邮件,需要在 expectation 的 action 里配置,而相关 webhook 地址应以环境变量注入容器,不要硬编码进 suite 文件。
容器化不仅解决了环境一致性,还让数据质量校验变成可审计的工件。每一次 checkpoint 运行都有对应镜像版本、挂载配置和输出结果,方便回溯某天数据异常是否由校验逻辑变更引起。随着数据规模增长,也可将单容器改为横向拆分:一个容器负责拉取元数据,另一个专门跑重计算校验,通过共享卷或消息队列传递 suite,进一步提升流水线的稳定性。
Great_Expectations容器化Docker修改时间:2026-08-17 18:00:16