将试用预约与正式预约分离

DockerBeginner
立即练习

介绍

STILL STUDIO 举办小型陶艺工作坊。宾客选择课程、预订名额,并在名单中看到自己的名字。团队希望试用 Garden Room 场次,但不能占用 Riverside Room 正式名单中的名额。你将为同一个应用建立独立的 staging 环境:带有清晰试用标识、预约数据独立的试用网站。

只需熟悉基本终端操作。本实验会介绍 Docker Compose、配置、路径、端口和数据卷。应用及镜像已提供,不要求编写应用代码或安装工具。所有预约均为模拟数据,不使用邮件、支付、外部账号或真实个人信息。

在 Live Bookings 使用端口 8081 上准备好的网站,在 Preview Bookings 使用端口 8082 上的试用网站,在 Workstation 执行命令。第 2 步启动之前,Preview Bookings 无法访问。本单元从独立环境开始。

认识业务并配置试用环境

本步骤将先体验正常预约流程,再准备一组独立配置。从 Live Bookings 开始。

在正常服务中预约名额

正式陶艺工作坊

首页介绍陶艺工作坊,并显示 LIVE BOOKINGS、Riverside Room 和 4 of 6 places left。选择 Explore the clay workshop。课程页介绍场次,并提供 Guest name 输入框。输入虚构姓名 Live guest,选择 Reserve a place。

浏览器打开 Guest list,显示 Maria、Jun 和 Live guest。剩余数量变为 3 of 6 places left。这是真实的数据库写入,不是装饰性的成功消息。选择 STILL STUDIO 返回首页,保留三条预约。

如果意外重复提交相同姓名,网站会说明已经预约,不会新增第二条。如果自己的姓名输错,打开 Guest list,只选择错误预约旁的 Cancel,再用 Live guest 预约。不要取消 Maria 或 Jun,也不要为了一个拼写错误清空整张名单。

理解配置边界

切换到 Workstation,终端已位于 /home/labex/project/booking。路径标识文件或目录。pwd 打印当前目录,ls 列出其中内容:

pwd
/home/labex/project/booking
ls

应看到 compose.yaml 和 live.env。cat 打印文本文件:

cat live.env
PORT=8081
APP_ENV=live
VENUE=Riverside Room
CAPACITY=6
DATA_VOLUME=still-live-data

配置让应用在不修改代码的情况下选择行为。这些 KEY=value 行选择对外端口、环境标识、场地、容量和数据卷。VENUE 改变全站显示的实际场地。CAPACITY 限制可接受的预约数量,而不只是改变标签。

Docker 用保存的镜像创建容器,在容器中运行应用。两个网站都使用提供的 still-booking:1 镜像。创建时,每个容器接收自己的环境变量。命名卷把数据库保存在可替换容器之外。不同容器可以共享数据卷,因此仅有不同容器名称并不能隔离记录。

准备好的资源如下:

资源 用途
still-live-data 正式数据库,包含 Maria 和 Jun 的原始预约
still-trial-data 为本次试用预留的空数据库资源

卷名称选择真实存储。试用预约绝不能选择正式数据卷。

理解简短的 Compose 文件

Docker Compose 用 YAML 文件描述相关容器。YAML 通过缩进组织设置;保留现有间距,使用空格而非制表符。读取提供的文件:

cat compose.yaml

在 services 下,booking 使用 still-booking:1。environment 部分把值传给应用。${VENUE} 表示 Compose 在创建容器前替换名为 VENUE 的值。环境文件是该替换操作的输入,不会自动改变已经运行的进程。

ports 映射 ${PORT}:8000:冒号前是实验实例对外提供的端口;8000 是应用在容器内监听的端口。两个网站必须使用不同的对外端口。

服务把 booking-data 挂载到 /data,应用在这里存储数据库。顶层的卷条目把该别名解析为 ${DATA_VOLUME}。external: true 表示卷已存在,Compose 必须使用这一确切资源。项目名称用于组织 Compose 容器,不会重命名明确选定的外部数据卷。

写入并解析试用配置

保持 live.env 不变。用下面的值创建 preview.env。cat > preview.env 会替换该文件。带引号的 ENV 开始一个 here-document:粘贴整个代码块,包括最后独占一行的 ENV。引号确保内容按字面保留。

cat > preview.env <<'ENV'
PORT=8082
APP_ENV=staging
VENUE=Garden Room
CAPACITY=3
DATA_VOLUME=still-trial-data
ENV

端口标识网络服务。这里 8082 属于 Preview Bookings,8081 仍属于 Live Bookings。APP_ENV=staging 启用醒目的试用标识,但不会自行选择独立存储;这是 DATA_VOLUME 的作用。

--env-file preview.env 告诉 Compose 使用哪组替换值。-p still-preview 选择项目。config 输出解析后的配置,不启动或修改容器:

docker compose --env-file preview.env -p still-preview config

找到 APP_ENV: staging、VENUE: Garden Room、容量 3、对外端口 8082 和卷名称 still-trial-data。不同 Compose 版本的输出格式可能不同。解析后的值才是证据,不能仅凭命令正常退出判断。

如果 Compose 报告缺少变量或文件,检查 pwd 和 cat preview.env,重新执行完整 here-document 修正拼写,再执行 config。如果 shell 已导出 VENUE 等变量,其值可能覆盖文件。unset VENUE 移除该 shell 覆盖值;仅对自己确实导出且发生冲突的键使用同样方法。解析值正确之前,不要启动试用环境。

启动试用环境并测试真实容量

本步骤将启动 staging 副本,并证明它使用独立名单。从 Workstation 开始。

启动已配置的应用

up 创建或更新项目容器。-d 让容器在后台运行,终端仍可继续使用:

docker compose --env-file preview.env -p still-preview up -d

输出显示创建的容器名称。ps 显示项目的实际状态和对外端口:

docker compose --env-file preview.env -p still-preview ps

找到运行中的 booking 服务,以及连接到 8000 的 8082 端口。如果启动失败,logs 打印应用消息:

docker compose --env-file preview.env -p still-preview logs

外部卷不可用通常说明资源名称拼错。修正 preview.env,重新执行 config,再执行 up -d。不要通过创建替代卷掩盖目标错误。端口冲突通常意味着选择了正式端口;保留 8081,本次试用使用 8082。

进行试用预约

切换到 Preview Bookings,必要时刷新。首页必须显示 STAGING · TEST BOOKINGS ONLY、Garden Room 和 3 of 3 places left。选择 Explore the clay workshop,输入 Trial guest,选择 Reserve a place。Guest list 现在仅显示 Trial guest,剩余 2 of 3 places left。

切换到 Live Bookings,选择 Guest list 并刷新。它必须仍显示 Maria、Jun 和 Live guest,剩余 3 of 6 places left。如果试用数据出现在这里,停止新增试用预约。在 Workstation 修正试用卷并执行 up -d,再从正式名单中仅取消明确属于自己的试用记录。保留所有合法正式预约。隔离修正后,在 Preview Bookings 中创建 Trial guest。

独立的试用名单

这种对比比标识更重要。带 staging 标签却共享数据库,仍会消耗正式名额。

测试更小的容量

留在 Preview Bookings。选择 Back to the workshop,预约 Capacity A。再次返回课程页,预约 Capacity B。名单现有三位宾客,剩余 0 of 3 places left。

再尝试预约 Overflow guest。页面应显示 Every place is taken. 和 **No booking was added.**。选择 View the guest list:Overflow guest 必须不存在。较小容量确实改变了应用行为。

仅取消 Capacity A 和 Capacity B,保留 Trial guest。试用环境恢复为 2 of 3 places left。姓名输错时,只取消对应测试记录再重试,无需清空数据库。返回 Live Bookings,确认正式名单和剩余名额未改变。

对比机器可读的结果

切换到 Workstation。HTTP 是浏览器使用的请求与响应协议。curl 发送请求;-sS 隐藏进度但显示连接错误。在 Workstation 中,127.0.0.1 指本实验实例。URL 由协议、地址、端口和资源路径组成。/api/info 用 JSON 这种结构化文本格式返回实际配置和数据库名单。不需要学习数据库查询语言。

curl -sS http://127.0.0.1:8081/api/info

查看 live、Riverside Room、容量 6、剩余 3 和三位正式宾客姓名。ID 可能不同。

curl -sS http://127.0.0.1:8082/api/info

查看 staging、Garden Room、容量 3、剩余 2 和唯一的 Trial guest。这是两个不同端点,不是同一张名单的两个标签。

更换试用容器并保留预约

本步骤将替换试用容器,并确认独立数据仍然存在。从 Workstation 开始。

检查实际存储挂载

ps -q 只打印项目容器的 ID。docker inspect 读取容器实际设置。--format 选择一个字段,带引号的模板把挂载列表转换为 JSON。$(...) 是 shell 表达式,运行内部命令,并把输出用作容器参数:

docker inspect $(docker compose --env-file preview.env -p still-preview ps -q booking) --format '{{json .Mounts}}'

找到类型为 volume、名称为 still-trial-data、目标为 /data 的挂载。如果实际挂载名为 still-live-data,不同项目名称也无法保护正式数据。

仅重建试用容器

--force-recreate 让 up 即使在配置未变化时也替换容器。已挂载的命名卷会保留。这也展示了配置如何进入新进程:仅修改环境文件不会更新运行中的容器。

docker compose --env-file preview.env -p still-preview up -d --force-recreate

等待 ps 显示服务运行:

docker compose --env-file preview.env -p still-preview ps

切换到 Preview Bookings,刷新 Guest list。Trial guest 必须仍在 Garden Room,剩余 2 of 3 places left。切换到 Live Bookings 并刷新名单。Maria、Jun 和 Live guest 必须仍在 Riverside Room,剩余 3 of 6 places left。替换容器或试用预约都不应清空另一环境。

不要把删除卷或 down -v 当作恢复方法。如果试用环境无法启动,使用同一项目的 logs,修正值,再执行 up -d。准备好的正式环境不在你的修改范围内。

同时检查页面与响应

在 Preview Bookings 选择 STILL STUDIO,打开课程,再打开 Guest list。本地插画、详情和导航必须仍正常。仅首页成功不代表完整预约服务正常。

切换到 Workstation。HTTP 状态 200 表示成功响应,404 表示请求路径不存在。-o /dev/null 丢弃响应正文;-w 打印带引号的格式。%{http_code} 是 HTTP 状态,\n 结束输出行:

curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8082/bookings

应为 200,并在浏览器中确认名单正确。返回错误页面内容的 200 也不算成功。

curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8081/workshop

应为 200,表示正式课程仍可访问。连接失败与 HTTP 错误响应不同;没有服务器响应时,检查 ps 和 logs。现在你有一个应用镜像、两个独立配置的进程,以及两份独立持久的宾客名单。这是单实例训练中的隔离,不是针对拥有 Docker 管理权限者的安全边界。

总结

你配置并启动了同一个预约应用的 staging 副本,选择独立命名卷,测试真实容量,并对比两边名单。重建试用容器保留了预约,正式服务也保留原有宾客。不同标识和 Compose 项目便于组织;实际数据目标才建立了隔离。