打包并运行咖啡馆菜单

DockerBeginner
立即练习

介绍

LITTLE HOUR 已有一套完整的咖啡馆菜单,周末快闪店也需要使用这套网站。只有首页还不够:顾客还需要饮品详情、价格、本地插画和营业时间。你的任务是用 Docker 镜像交付完整体验。

你将打包提供的文件,运行自己的镜像,然后从中启动一个新容器,检查真实的网站。无需编写应用代码或安装 Docker。只需熟悉基本终端操作;Docker、路径、端口和命令都会在使用时讲解。咖啡馆、商品、价格和地址均为虚构。

在 Workstation 中执行终端命令,在 Reference Menu 中查看设计参考,在 Your Menu 中浏览自己的运行容器,在 Topology 中查看环境关系图。Your Menu 在第 2 步启动容器后才能使用,之前可能无法访问。每个实验都有独立的初始环境。

构建完整的菜单镜像

本步骤先了解咖啡馆的需求,再构建包含完整顾客网站的镜像。请从 Reference Menu 开始。

了解顾客体验

首页介绍 LITTLE HOUR。在 A few good favourites 下打开 Flat white。详情页包含 $4.00 的价格、份量和过敏原信息。点击 Find us 查看营业时间,然后点击 LITTLE HOUR 返回首页。这些链接和插画都是交付内容,不是可有可无的装饰。

完整的 LITTLE HOUR 菜单参考

参考网站已在端口 8082 准备好。即使你的容器停止,它仍然可以访问,因此不能用它证明你已完成交付。

找到需要交付的文件

切换到 Workstation。终端初始目录为 /home/labex/project/cafe-menu。pwd 输出当前目录;ls 列出其中的名称:

pwd
/home/labex/project/cafe-menu
ls

你应看到 menu、brand 和 notes。menu/ 包含顾客页面;brand/ 包含样式表和插画。notes/ 是作者资料,不应出现在公开菜单中。不要修改提供的文件。

网站上的地址是 URL 路径。服务器把 /menu/flat-white.html 映射到公开目录下的文件。外层 menu/ 源目录里还有一个 menu/ 子目录,用于存放这些详情页。检查两组源文件:

ls menu
ls brand

页面包括 index.html、visit.html、404.html 和详情目录。品牌文件包括 site.css 和三张 .svg 插画。SVG 是一种图像格式。页面要求运行网站上的所有品牌文件都位于 /assets/ 下。

编写打包配方

Docker 在容器中运行程序。镜像是用于创建容器的已保存软件包;容器是该镜像的运行中或已停止实例。这里已经安装 Docker。准备好的 menu-base:1 镜像包含 Web 服务器 Nginx 及其页面缺失配置,公开目录为 /usr/share/nginx/html/,其中还没有你的咖啡馆菜单。

Dockerfile 描述如何构建镜像。FROM 选择基础镜像。COPY 把提供的文件复制到镜像中:第一个路径是相对于构建目录的源路径,第二个路径是镜像中的目标路径。把目录内容复制到正确位置,可以保留页面原有链接;这不会把运行容器连接到你的源目录。

你将明确复制两次:页面复制到公开目录,品牌文件复制到其中的 assets/ 目录。这样就不会包含作者笔记。Nginx 基础镜像已定义服务器启动命令,无需额外添加。

cat > Dockerfile 会用后续文本替换这个文件。带引号的 DOCKERFILE 开始一个 here-document:请粘贴整个代码块,包括最后单独占一行的 DOCKERFILE。引号让内容保持字面值。在 Workstation 中执行:

cat > Dockerfile <<'DOCKERFILE'
FROM menu-base:1
COPY menu/ /usr/share/nginx/html/
COPY brand/ /usr/share/nginx/html/assets/
DOCKERFILE

cat 也能输出文件。构建前读取保存的配方,核对两个目标路径:

cat Dockerfile

构建并保存镜像

docker build 读取配方并创建镜像。-t 指定名称和标签;这里 little-hour-menu 是名称,1 是我们选择的版本标签。最后的点表示当前目录是构建上下文,即 Docker 构建时可使用的文件范围。标签只是便于识别的名称,不能证明内容完整。

docker build -t little-hour-menu:1 .

构建输出随 Docker 版本变化。命令应成功结束,并标识 little-hour-menu:1。如果 COPY 失败,请检查 pwd、源文件名称和保存的 Dockerfile,修正配方后再次执行相同构建命令。不要通过替换提供的页面或复制整个项目来掩盖路径错误。

现在你已有保存好的交付镜像,但还没有运行菜单容器。

将镜像发布为运行中的菜单

本步骤将创建自己的运行容器并打开网站。请从 Workstation 开始。

将容器连接到网站端口

Nginx 在容器内部监听端口 80。端口用来标识网络服务。我们将它发布到实验实例的端口 8081,以便 Your Menu 标签页访问。这不会改变端口 8082 上的参考网站。

docker run 创建并启动容器。-d 让它在后台运行,终端仍可继续使用。--name cafe-menu 指定后续操作所用的名称。-p 8081:80 将实验实例的端口 8081 映射到容器的端口 80。最后一个参数选择你构建的镜像。这里没有挂载源目录或卷:

docker run -d --name cafe-menu -p 8081:80 little-hour-menu:1

输出的长字符串是新容器的 ID,每次运行都会变化。仅有 ID 不能证明应用持续运行。docker ps 列出运行中的容器:

docker ps

找到 cafe-menu、镜像 little-hour-menu:1,以及包含 8081->80/tcp 的映射。可能还会出现其他训练容器,请不要操作它们。

如果名称已被使用,不要换名称启动许多副本。先用 docker ps 找到自己的运行容器;如果它正确,就继续。如果它已退出或映射错误,docker logs cafe-menu 可以显示服务器消息。若只需替换你的静态菜单容器,docker rm -f cafe-menu 会停止并删除这个指定容器,保留镜像和源文件。

修正配方或端口错误后,按需重新构建,再执行原来的 docker run 命令。只有需要替换时才执行删除命令,不要在每次成功启动后都删除容器。

打开自己的交付网站

切换到 Your Menu。如果启动容器前打开过它,现在请重新加载。你应看到布局和插画完整的 LITTLE HOUR。这一页来自端口 8081,而非提供的 Reference Menu。

由学习者容器提供的菜单

在 A few good favourites 下打开 Flat white。详情页应有插画、价格、份量和过敏原信息。点击 Find us 核对营业时间,然后在同一标签页中点击 LITTLE HOUR 返回首页。只有文字的首页或损坏的插画不算完整交付。

切换到 Topology。现在可能显示 Menu homepage reachable。这只是一项有限观察,并非所有页面都已通过验收。接下来你将检查交付的独立性及其他顾客路径。

检查新容器和完整网站

本步骤将从镜像启动一个新实例,不依赖作者目录,验证完整顾客体验。请从 Workstation 开始。

区分镜像与容器

删除容器后,镜像仍会保存。这个网站没有顾客提交内容或数据库,因此替换此容器不会丢失业务数据。对于有状态应用,这个区别很重要。

使用第 2 步介绍的替换命令,只删除 cafe-menu:

docker rm -f cafe-menu

使用相同的发布端口启动一个新实例:

docker run -d --name cafe-menu -p 8081:80 little-hour-menu:1

它会输出不同的容器 ID。你没有重新构建,也没有挂载作者目录:新实例使用的是已打包进镜像的文件。

docker inspect 显示容器的实际配置。--format 只选择一个字段,而不是输出完整对象。下面带引号的模板将挂载列表转换为 JSON:

docker inspect cafe-menu --format '{{json .Mounts}}'
[]

空列表表示没有主机目录或卷挂载。这正是本练习需要的证据:源文件没有暗中填补交付缺失。挂载在其他场景有合理用途;本任务要求的是自包含的静态菜单。

测试真实顾客路径

切换到 Your Menu 并重新加载。依次选择三个推荐商品。Flat white 价格为 $4.00,Espresso 为 $3.00,Iced oat latte 为 $4.75。每个详情页都必须显示正确图片和信息。每次查看后点击 LITTLE HOUR 返回首页。点击 Find us,确认工作日营业时间为 08:00–17:00。始终在 Your Menu 内检查;Reference Menu 测试的是另一台服务器。

交付菜单中完整的饮品详情

切换到 Workstation。HTTP 是浏览器使用的请求与响应协议。成功响应的状态码是 200;404 表示请求的资源未找到。连接失败则不同:它没有收到正常服务器响应。

curl 发送请求。-sS 隐藏进度,但显示连接错误。-o /dev/null 丢弃响应正文。-w 输出引号内指定的格式:%{http_code} 是状态码,\n 表示换行。在 Workstation 中,127.0.0.1 指当前实验实例;不要从自己电脑的终端执行这些请求。

curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8081/menu/flat-white.html

它应输出 200。此前的浏览器检查也确认了内容和插画正确;返回错误页面的 200 并不足够。

作者笔记不应公开。请求它们可能对应的 URL:

curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8081/notes/launch-notes.txt

预期为 404。对打包边界而言,这是预期的成功结果。由于没有要求 curl 在 HTTP 错误响应时失败,它仍会正常退出。停止整个网站无法满足菜单正常工作的要求。

切回 Your Menu,点击 LITTLE HOUR 返回首页。拒绝笔记请求后,正常菜单仍应可用。你已经检查了完整顾客内容,也验证了网站如何恰当响应不属于交付内容的资源请求。

总结

你构建了完整的静态菜单镜像,发布了服务器端口,并在没有源目录挂载的情况下启动新容器。你检查了真实顾客页面、图片和到店信息,同时把作者笔记留在公开网站之外。接下来的独立挑战将把这些打包决策应用到源目录布局不同的面包店。