介绍
Form & Field 正在准备下一批商店商品。你有一张陶瓷杯照片和一幅透明品牌图形。请制作较小的网页图片,同时保留原图和透明背景。处理容器消失后,普通用户仍须能够编辑成品文件。
Docker 和预先准备的 ImageMagick 工具镜像已就绪。你需要熟悉基本终端和路径;实验会在使用前介绍 Docker、绑定挂载、图像选项和 shell 语法。你无需在工作站安装软件或编写图像处理代码。商店是虚构的;照片采用 CC0,品牌图形是原创教学素材。
在 Workstation 中执行命令,在 Photo Desk 中查看和下载真实图片。本实验与课程挑战互相独立。请预留约 55 分钟,包括阅读和处理普通错误;这是作者估计。
处理一张小样图
本步骤将用短生命周期容器生成一张真实的缩小照片。先在 Photo Desk 打开 Source collection。打开照片,使用 Back to collection 返回,再打开品牌图形。图形背后的棋盘格表示透明像素,并非图片内容。返回素材集合。

切换到 Workstation。起始目录是 /home/labex/project/photo-studio。pwd 显示当前目录,ls 列出目录条目。如果离开这里,可用下面的 cd 命令返回;cd 会改变 shell 的当前目录。
cd /home/labex/project/photo-studio
ls
已准备好的 source、samples 和 web 目录分别保存原图、练习结果和最终交付物。保持 reference.jpg 不变;它是独立样例,并非你的输出。
镜像打包程序及其依赖,容器将镜像作为进程运行。这里的 dk01-photo-tools:1 包含 ImageMagick 的 convert 程序。:1 标识准备好的镜像版本,不是容器名。docker run 创建并启动容器。进程退出后,--rm 会移除容器。镜像名后面的参数传给 convert。
先查询工具版本。-version 是 ImageMagick 选项,不是 Docker 选项:
docker run --rm dk01-photo-tools:1 -version
输出中应包含 ImageMagick 6.9.11-60。程序在容器内运行,这不会在 Workstation 安装 convert。
连接输入和输出
容器有自己的文件系统路径。绑定挂载将工作站的一个目录映射到容器路径。本次小样连接如下目录:
| 工作站目录 | 容器路径 | 访问权限 |
|---|---|---|
当前目录中的 source |
/input |
只读 |
当前目录中的 samples |
/output |
读写 |
工作站目录是挂载的 src,容器路径是 dst。type=bind 选择这种挂载类型。readonly 防止通过该挂载写入输入。每个 --mount 描述一条连接。写入 /output 的结果会到达 samples,并在容器删除后保留。
文件也有数字形式的所有者。id -u 显示用户 ID,id -g 显示组 ID:
id -u
id -g
使用实际值,不要假定是 1000。下一条命令中的 $(...) 执行括号内的命令,并插入其输出。因此 --user "$(id -u):$(id -g)" 以你的数字用户和组运行工具。$PWD 展开为当前目录的完整路径。双引号让挂载描述保持为一个参数,即使路径含空格也如此。
ImageMagick 的 -resize '320x320>' 将照片按比例缩放到 320 × 320 像素范围内。> 表示只缩小。单引号将它传给 ImageMagick,避免 shell 将其解释成输出重定向。行末反斜杠表示同一条命令延续到下一行;请复制整个代码块。
docker run --rm --user "$(id -u):$(id -g)" \
--mount "type=bind,src=$PWD/source,dst=/input,readonly" \
--mount "type=bind,src=$PWD/samples,dst=/output" \
dk01-photo-tools:1 /input/cups.jpg -resize '320x320>' /output/sample.jpg
成功时通常没有输出。ls -l 显示生成的文件及其所有者:
ls -l samples/sample.jpg
属于 labex 的普通文件才是可用结果。--rm 已移除容器,但挂载输出仍在。源目录拼写错误时,Docker 会报告无效挂载,而不会生成有效照片。查看 pwd 和 ls source,修正路径,再执行同一代码块。不要用 sudo 或修改目录权限来掩盖路径错误。
交付照片和透明图形
本步骤将生成最终的两张网页图片。先在 Photo Desk 选择 Your delivery。页面列出格式和尺寸要求,但起初没有图片。缺失结果会保持缺失:页面绝不借用原图填补空缺。
杯子照片须为保持比例、尺寸不超过 640 × 640 的 JPEG。品牌图形须为不超过 256 × 256、保留透明度的 PNG。在边界内使用最大的等比尺寸,不放大已经较小的输入。边界框是上限,不是方形裁剪。竖向照片变为 480 × 640,横向图形变为 256 × 128。
切换到 Workstation。复用同一输入挂载、用户身份和工具,只将输出挂载改为 web,并改变缩放上限和输出名:
docker run --rm --user "$(id -u):$(id -g)" \
--mount "type=bind,src=$PWD/source,dst=/input,readonly" \
--mount "type=bind,src=$PWD/web,dst=/output" \
dk01-photo-tools:1 /input/cups.jpg -resize '640x640>' /output/cups.jpg
现在处理透明图形。PNG 支持透明度,JPEG 不支持。如果图像已经被铺到背景上,仅保留 PNG 扩展名并不足够。下面的命令会保留原有透明像素:
docker run --rm --user "$(id -u):$(id -g)" \
--mount "type=bind,src=$PWD/source,dst=/input,readonly" \
--mount "type=bind,src=$PWD/web,dst=/output" \
dk01-photo-tools:1 /input/brand.png -resize '256x256>' /output/brand.png
切换到 Photo Desk,重新加载 Your delivery,打开每个结果。阅读显示的尺寸,查看照片比例。品牌图形背后的棋盘格仍应透出来。对每个结果使用 Download file,然后使用 Back to collection 返回。下载的就是 web 目录中的文件。

页面只是读取器,并非处理器或评分器。能看见图片并不能单独证明原图未改动,也不能证明脚本能在另一目录工作。图片缺失时,返回 Workstation,检查输入/输出路径,重新运行对应命令。缺失文件页面与整个 Photo Desk 连接失败是不同情况。
保存可移植处理脚本
本步骤将保存两条已成功的 Docker 命令,让另一份工作室目录能够处理自己的原图。先进入 Workstation 的 /home/labex/project/photo-studio。
Shell 脚本是包含命令的文本文件。bash run-photos.sh 让 Bash 顺序执行这些命令。下面的 here-document 将两个 RECIPE 标记之间的行写入文件:cat 提供文本,> 保存文本,<<'RECIPE' 标记字面文本块。为第一个标记加引号,可防止保存文件时展开 $PWD 和 $(id ...)。它们须在别人从自己的目录运行脚本时才展开。结束标记独占一行。
set -e 在工具命令失败时停止脚本,避免后面的命令掩盖前面的失败。保存完整脚本:
cat > run-photos.sh <<'RECIPE'
#!/bin/bash
set -e
docker run --rm --user "$(id -u):$(id -g)" \
--mount "type=bind,src=$PWD/source,dst=/input,readonly" \
--mount "type=bind,src=$PWD/web,dst=/output" \
dk01-photo-tools:1 /input/cups.jpg -resize '640x640>' /output/cups.jpg
docker run --rm --user "$(id -u):$(id -g)" \
--mount "type=bind,src=$PWD/source,dst=/input,readonly" \
--mount "type=bind,src=$PWD/web,dst=/output" \
dk01-photo-tools:1 /input/brand.png -resize '256x256>' /output/brand.png
RECIPE
不带重定向的 cat 显示文件。阅读保存的脚本;其中应仍含字面形式的 $PWD 和 id 替换:
cat run-photos.sh
从工作室目录运行它。它会有意更新同样的两份派生文件,绝不能重写原图:
bash run-photos.sh
复用契约是一个包含 source、web 和该脚本的目录。将目录复制到其他位置后,包括名称含空格的位置,它也须能处理具有相同文件名的另一组兼容图片。较小原图应保持原尺寸,不能被放大。使用 PATH 中普通的 docker run;不得使用 sudo、固定数字 UID、绝对工作站路径、源文件编辑或额外主机挂载。只要同样安全的输入/输出关系有效,容器内目标路径可以不同。通过 Bash 调用文件,因此不需要可执行权限。
最后演示普通文件操作。cp 复制文件,mv 重命名或移动文件。下面两条命令仅作用于派生样图副本:
cp web/cups.jpg samples/shop-preview.jpg
mv samples/shop-preview.jpg samples/ready.jpg
ls -l samples/ready.jpg
这些命令不需要管理员权限。web 仅保留要求的两个文件;练习文件放在 samples。只有看似合理的文件名并不足够:检查会解码真实图片,并用独立兼容输入运行不变的脚本。检查不会重新生成你的交付物。
切换到 Photo Desk,重新加载 Your delivery,再次打开两个结果并返回集合。每个处理容器消失后,文件仍然存在。保留提供的 source 文件和 reference.jpg。
总结
你将 Docker 镜像用作一次性照片工具,映射了独立的输入和输出目录,以只读挂载保护原图,并用自己的实际 UID/GID 运行工具。容器移除后,真实 JPEG 和透明 PNG 仍可编辑。保存的处理脚本能在移动后的工作室目录中处理兼容输入,无需在工作站安装该工具。



