介绍
报告服务需要读取配置并写出文档,但当前的配置挂载也允许写入。你负责维护该服务,需要在保持报告生成功能的同时减少这种不必要的访问。
你会先生成正常报告,然后保护输入挂载,只重建报告容器。具备基本终端操作经验即可;Docker、挂载语法和编辑操作都会在使用前介绍。
生成正常报告
在这一步中,先运行报告服务的正常业务任务,再修改权限。Harbor Books 使用一个小型服务汇总订单并生成文档。客户与数字都是合成的训练数据。
使用 Maintenance 终端。这是具有 Docker 管理权限的 Linux 宿主机维护角色。Docker 在容器中启动应用进程:各容器看到各自的文件系统和进程列表,但共享宿主机内核。容器不是另一台 VM。你只管理 report-renderer 和 /home/labex/project/report-desk 中的文件。
终端从该目录开始。pwd 显示当前目录:
pwd
应显示 /home/labex/project/report-desk。如果切换过目录,用 cd /home/labex/project/report-desk 返回。
应用监听端口 8090。端口用来标识服务;这里的 localhost 指维护宿主机,Docker 将其端口转发给容器。curl 发送 HTTP 请求,-X POST 选择执行操作的请求,-fsS 显示错误并简化成功输出。请求基准文档:
curl -fsS -X POST http://localhost:8090/render/baseline
{"saved": "/output/baseline.json", "total": 37, "uid": 0}
服务读取了输入并保存了真实文件。cat 显示文件;宿主机通过本地 output 目录看到容器的 /output:
cat output/baseline.json
找到 Report for Harbor Books: 37 orders。其他字段记录输入标识和运行中的服务实例。打开 Document Desk 并刷新:Stored documents 下出现 baseline.json。该页面列出实际文件,并不代表权限已安全。
保护输入的启动声明
在这一步中,对应输入与输出路径,演示不必要的写入,然后编辑启动声明。绑定挂载将宿主机目录连接到容器内的路径;没有明确限制时默认可写。
cat launch.sh 显示准备好的 Bash 启动脚本:
cat launch.sh
反斜杠将命令延续到下一行。sudo 以宿主机管理员权限执行 Docker 管理操作,并不决定应用用户。docker run -d 在后台启动容器,--name 指定名称,--user 0:0 选择用户/组 ID,-p 8090:8090 将宿主机端口转发到容器端口。最后一个参数是预置应用镜像 c12-renderer:1。
每个 --mount 包含逗号分隔的字段:type=bind 连接宿主机路径,src 是宿主机路径,dst 是容器路径。
| 宿主机目录 | 容器目录 | 所需访问 |
|---|---|---|
report-desk/config |
/config |
读取批次与模板 |
report-desk/output |
/output |
写出生成的文档 |
配置中有一个不含业务数据的可丢弃样本 probe.txt。docker exec 在指定的运行中容器内执行命令。touch 更新样本时间戳;这是刻意演示的不必要应用访问:
sudo docker exec report-renderer touch /config/probe.txt
没有输出表示成功。这证明配置挂载可写,同时不会破坏批次或模板。修改宿主机启动声明会影响 Docker 下次创建的容器;编辑当前容器内部的文件不能改变挂载模式。
使用终端编辑器 nano 修改声明:
nano launch.sh
用方向键移动。在包含 dst=/config 的行中,紧接 /config 添加 ,readonly,位置在空格和反斜杠之前。保持 /output 挂载可写。按 Ctrl+O、Enter 保存,再按 Ctrl+X 退出。配置挂载行应为:
--mount type=bind,src=/home/labex/project/report-desk/config,dst=/config,readonly \
再次运行 cat launch.sh,检查是否遗漏逗号或反斜杠。可重新打开 nano launch.sh 修正输入错误。运行中的容器仍使用旧挂载,下一步才会替换它。
应用并测试挂载边界
在这一步中,只替换报告容器,证明禁止输入写入的同时输出仍然可用。修改启动脚本不会自动更新已有容器。
docker rm -f 停止并删除指定容器;绑定挂载的宿主机目录会保留。bash launch.sh 执行你编辑的声明:
sudo docker rm -f report-renderer
bash launch.sh
第二条命令打印新的容器 ID。稍等片刻让服务启动。如果出现语法或挂载错误,用 nano launch.sh 修正对应行,使用同一删除命令移除新建的 report-renderer,然后再次运行脚本。不要删除宿主机数据目录。
docker inspect 读取实际容器配置。--format 选择字段;保留单引号,让 shell 原样传递花括号:
sudo docker inspect report-renderer --format '{{json .Mounts}}'
找到 "Destination":"/config" 对应的 "RW":false,以及 /output 对应的 "RW":true。RW 表示读写。用同一个可丢弃样本确认真实边界:
sudo docker exec report-renderer touch /config/probe.txt
touch: /config/probe.txt: Read-only file system
非零退出是预期结果。终端仍可用,继续下一条命令。连接错误或容器不存在则不同,表示需要修正或重新运行启动脚本。
向重建的服务请求新文档:
curl -fsS -X POST http://localhost:8090/render/final
{"saved": "/output/final.json", "total": 37, "uid": 0}
cat output/final.json
文档仍包含 Report for Harbor Books: 37 orders。刷新 Document Desk 查看 final.json。服务可读输入、可写输出,而配置挂载拒绝写入。它仍以 root 运行,下一独立实验会处理这项不同的权限。
总结
你生成了真实报告,对应了宿主机与容器路径,将输入挂载改为只读,并重建了服务。实际挂载检查和写入拒绝证明保护生效,新报告则证明正常输出仍然可用。



