等待档案馆数据库就绪

DockerBeginner
立即练习

介绍

The Common Archive 在 PostgreSQL 中保存四条社区记录。参考站点可正常使用,但新档案馆在数据库能够接受连接之前就尝试导入目录。你将区分容器已运行与数据库可用,让首次启动可靠完成。

你应了解基本 Docker、容器日志、发布端口和终端路径。本实验讲解 YAML 关系、简短的 Compose 文件、数据库健康检查及依赖条件。无需 SQL、PostgreSQL 管理或应用编程知识。完整数据库镜像、导入器、网站和数据均已提供。

使用 Workstation、Reference Archive、Your Archive 和 Collection Notes。所有素材都是合成教学记录。刻意设置的数据库与导入延迟用于展示启动状态,不代表生产环境耗时。包含阅读和普通错误在内,预计约 45 分钟;这是作者估计。

等待数据库可用

本步骤将修复一个小型完整应用中的依赖。替换配置前,请先完成观察。

使用正常档案馆

从 Reference Archive 开始。在 Search the collection 中输入 Market morning 并点击 Search。两条记录具有相同标题,却讲述不同故事。分别打开,查看 ID、年份和类别,并使用 Download transcript。通过 Back to collection 返回,清空搜索,查看 Ferry voices。下载的是真实数据库记录文本,而非完成标记。

切换到 Your Archive。它说明目录尚未运行,不会借用参考服务。Collection Notes 已经可用,因为欢迎服务不读取数据库行。容器处于 Up 状态,不能证明目录完整。

阅读真实失败的启动过程

参考集合包含四条记录;两个 Market morning 条目有各自的身份:

完整的参考目录

切换到 Workstation,其起始目录是 /home/labex/project/archive-startup。需要时用 cd 返回。cat 显示文件:

cd /home/labex/project/archive-startup
cat compose.yaml

Compose 读取 YAML。缩进将每个服务的属性归为一组;使用空格,不要使用制表符。services: 下有四个条目:

服务 实际工作 成功状态
db PostgreSQL 存储记录 运行且接受 TCP 连接
importer 通过单个事务导入提供的 CSV 以状态 0 退出
catalog 搜索并提供记录与文字稿 导入成功后运行
welcome 无需读取数据库即可提供 Collection Notes 可在导入前运行

image 选择已准备的镜像。entrypoint 启动提供的程序;你不编辑它。environment 将具名设置传给程序。PGHOST、PGUSER、PGPASSWORD 和 PGDATABASE 告诉客户端使用哪个数据库和训练账号。这些作用域内的凭据已为本实验提供。POSTGRES_* 在新数据存储中准备该账号。不要更改认证或替换数据库。

data 卷保留本项目的数据库文件。相对路径 ./scenario 将提供的输入文件夹只读绑定到导入器,以 :ro 表示。数据库也会读取所提供的首次启动训练延迟脚本。发布端口 8090:8080 将 Your Archive 连接到目录服务。欢迎页使用独立端口。Compose 项目将资源归组;下面的 -p archive 始终指向你的学员档案馆,参考服务使用不同项目和卷。

ps -a 包含已停止和从未启动的容器。logs 读取其真实输出:

docker compose -p archive ps -a
docker compose -p archive logs db importer

数据库最终会报告就绪,但导入器已经连接失败。数据库稍后就绪,不会自动重新执行失败的导入。目录保持未启动,因为提供的依赖已经要求等待导入器成功。

PostgreSQL 在启动最终 TCP 监听器之前,会短暂使用临时初始化服务器。只检查本地 Unix socket,可能会早于其他容器实际可连接的时间变为就绪。pg_isready 报告服务器是否接受连接,不证明凭据或目录内容正确。

以下只读探测刻意使用错误 TCP 端口。exec 在 db 中执行探测,-T 禁止分配终端,-h 选择地址,-p 选择端口,-U/-d 指定提供的用户/数据库。端口 6543 没有服务器,因此预期得到 no response 和原生退出状态 2:

docker compose -p archive exec -T db pg_isready -h 127.0.0.1 -p 6543 -U archivist -d archive

这是探测失败,不是目录数据丢失。最终数据库监听正常 TCP 端口 5432。健康检查必须针对这个实际服务。

表达就绪条件并用新数据启动

保持应用设置与提供的文件不变。给 db 添加真实的 healthcheck,将导入器的数据库条件从 service_started 改为 service_healthy。test 是 Docker 在数据库容器内执行的命令。类似 JSON 的数组使用 CMD 直接运行指定程序,不经过 shell。-h 127.0.0.1 选择最终 TCP 监听器;默认端口为 5432。interval: 1s、timeout: 2s 和 retries: 40 提供反复且有时间限制的探测,而不是用固定等待假装数据库已就绪。

保持目录的 service_completed_successfully 条件:一次性导入成功后以 0 退出,无需一直保持 Running。导入失败必须阻止目录启动。欢迎页不依赖导入,因为它不需要已导入数据。

以下按字面保存的 here-document 写出完整配置,便于准确复现缩进。cat 提供各行,> 只替换 compose.yaml,加引号的 COMPOSE 标记在结束行之前阻止 shell 展开。其余应用设置全部保留:

cat > compose.yaml <<'COMPOSE'
services:
  db:
    image: dk04-postgres:16
    environment:
      POSTGRES_USER: archivist
      POSTGRES_PASSWORD: training-archive
      POSTGRES_DB: archive
      TRAINING_DB_DELAY: "8"
    volumes:
      - data:/var/lib/postgresql/data
      - ./scenario/slow-init.sh:/docker-entrypoint-initdb.d/10-training-delay.sh:ro
    healthcheck:
      test: ["CMD", "pg_isready", "-h", "127.0.0.1", "-U", "archivist", "-d", "archive"]
      interval: 1s
      timeout: 2s
      retries: 40
  importer:
    image: dk04-archive:1
    entrypoint: ["python3", "-B", "/app/importer.py"]
    environment:
      PGHOST: db
      PGUSER: archivist
      PGPASSWORD: training-archive
      PGDATABASE: archive
      TRAINING_IMPORT_DELAY: "6"
    volumes:
      - ./scenario:/scenario:ro
    depends_on:
      db:
        condition: service_healthy
  catalog:
    image: dk04-archive:1
    entrypoint: ["python3", "-B", "/app/archive.py", "catalog"]
    environment:
      PGHOST: db
      PGUSER: archivist
      PGPASSWORD: training-archive
      PGDATABASE: archive
      ARCHIVE_TITLE: "The Common Archive"
    ports:
      - "8090:8080"
    depends_on:
      importer:
        condition: service_completed_successfully
  welcome:
    image: dk04-archive:1
    entrypoint: ["python3", "-B", "/app/archive.py", "notes"]
    environment:
      ARCHIVE_TITLE: "The Common Archive"
    ports:
      - "8091:8080"
volumes:
  data:
    labels:
      labex.course: dk04
COMPOSE

更改运行资源前,先解析配置:

docker compose -p archive config

如果 YAML 解析失败,阅读报告的行,用空格恢复所示文本块,再次解析。不要反复重启格式错误的文件。

现在使用空的课程数据存储测试首次启动。这会刻意删除你的一次性训练数据库,不删除源 CSV 或参考档案馆。先检查实际卷标签:

docker volume inspect archive_data --format '{{json .Labels}}'

确认 com.docker.compose.project 为 archive,labex.course 为 dk04。任一不符时,应停止并检查项目,不要删除其他资源。down --volumes 只移除此具名 Compose 项目的容器、网络及声明的数据卷:

docker compose -p archive down --volumes

up -d 在后台启动服务。--pull never 使用已准备的镜像;--no-build 防止通过新构建替换它们:

docker compose -p archive up -d --pull never --no-build
docker compose -p archive ps -a
docker compose -p archive logs importer

预期数据库健康,导入器 Exited 0,目录与欢迎页 Running。提供的首次启动延迟和导入延迟明确用于训练。Compose 文件中的固定 sleep 无法替代真实就绪或成功导入。如果之前尝试留下失败容器,检查日志、修正配置、核验课程卷标签,再重复这个限定范围的全新数据启动。

使用完成的目录

切换到 Your Archive 并刷新。搜索 Market morning:应显示两个具有不同 ID、年份、类别和故事的记录。分别打开并使用 Download transcript,再通过 Back to collection 返回。搜索 Ferry,打开 Ferry voices 并下载文字稿。清空搜索,显示全部四条记录。也要检查 The shared garden 及其下载。未知记录 URL 应显示 Record not found,与连接失败或目录不可用区分开。

切换到 Collection Notes:独立欢迎页必须仍可使用。Reference Archive 应继续提供原始完整集合。保持最终档案馆运行。检查先观察实时数据库、已完成导入和完整业务结果,再将未修改的健康/依赖配置用于独立、一次性的全新数据存储,配合不同的已披露训练延迟及无效导入样本。这些 fixture 绝不会初始化或修复你的实时档案馆。另一个隔离测试会在没有数据库服务器的情况下运行未修改的健康命令;它必须拒绝该不可用端点。

总结

你区分了数据库容器启动与最终 TCP 就绪,配置真实健康检查,并要求导入器等待检查通过。随后,全新数据存储先接收完整目录,再开放使用它的服务;独立的说明页始终可用。