使用限定范围的计划恢复预览站

DockerIntermediate
立即练习

介绍

TIDE 在一天内向访客开放两间艺术家工作室。网站提供日程、交通指引和可下载指南。City 正式站点正常,Riverside 参考预览站也仍可使用,但 Courtyard 预览容器已消失。请恢复该场地,同时不替换任何相邻站点或共享网络。

你需要基本终端能力,以及 Docker 镜像、容器和发布端口的使用经验。本实验从头介绍 Terraform:你将学习 HCL 配置、provider、resource、data source、plan 和 state。工具和完整网站镜像已经提供。这是在单个训练实例上管理本地 Docker,不需要云账号或编写应用。

使用 Live Studios、Reference Preview、Venue Preview 和 Workstation。恢复前 Venue Preview 不可用。本环境独立初始化。本练习固定使用 Terraform 1.14.3 和社区 kreuzwerker/docker provider 3.0.2。本地 provider 镜像使学习时的初始化不依赖公共 registry。

声明预览站及其所有权边界

本步骤中,你将先体验正常访客流程,再仅声明缺失的场地容器。从 Live Studios 开始。首页显示 LIVE PROGRAMME / City。选择 Meet the two studios,阅读 Form & Field 和 Small Editions 的活动,再选择 Find directions and the programme。选择 Download the day programme 并打开下载的文本:其中应包含 City 和两间工作室的日程。展开 **Do I need to book?**;入场免费,无需预约。

切换到 Reference Preview。同样的流程显示 REFERENCE PREVIEW / Riverside。必须保留此容器:它属于当前 Terraform 配置,而且仍有用途。Venue Preview 目前无法连接,因为它的容器缺失。服务器缺失与 HTTP 404 不同:404 是正在运行的服务器找不到特定页面时的响应。

阅读根配置和状态

切换到 Workstation。Terraform 根目录是一起计算其中所有 .tf 文件的目录。在另一个目录运行 Terraform 会选择另一个根,不会自动扫描相邻目录。pwd 输出当前位置:

pwd
/home/labex/project/preview/courtyard

ls 列出文件,cat 显示文本文件。阅读已准备的配置:

ls
cat main.tf

.tf 文件使用配置语言 HCL。花括号中的块组织设置;name = value 为设置赋值。引号中的文字是字符串,端口则是不加引号的数值。terraform 块固定核心程序和所需 provider。provider 是把 Terraform 操作转换为 Docker API 请求的插件。provider "docker" {} 使用当前实例的 Docker daemon,不连接公有云。

两个 data "docker_network" 块读取已有网络。数据源查询对象,但不取得创建或删除对象的所有权。city 和 venue 是引用时使用的本地标签,网络名称则标识实际 Docker 对象。镜像数据源同样读取已准备镜像的 ID。使用实际镜像 ID,可避免反复把标签与解析后的 ID 视为不同镜像。

cat reference.tf

资源声明由此根配置管理的对象。docker_container.reference 是 Terraform 地址,由资源类型和本地标签组成;其 Docker 名称是 tide-reference。参考容器内部在端口 80 提供服务,发布到实例的端口 8083。表达式 data.docker_image.reference.id 读取镜像数据源的 id 属性。它是表达式,因此不加引号。

保持 main.tf 和 reference.tf 不变。两个网络、所有镜像记录和正式容器都不属于此根的受管所有权。此根管理两个容器:参考站和缺失的预览站。

状态把 Terraform 地址映射到实际对象 ID。已准备的 terraform.tfstate 记住两个容器,包括如今缺失的那个。状态既不是配置,也不是网站备份。不要编辑或删除它。后面的 plan 会向 Docker 查询实际存在的对象,而不会只相信记录中的 ID。

编写缺失资源的声明

创建 preview.tf。Terraform 将它与同一根中的其他 .tf 文件一起处理;文件名本身不会创建独立环境。cat > preview.tf 只替换该文件。带引号的 HCL 开始一个 here-document:粘贴整个代码块,包括单独一行的结尾 HCL。引号让内容保持字面值。

cat > preview.tf <<'HCL'
resource "docker_container" "preview" {
  name  = "tide-preview"
  image = data.docker_image.site.id
  ports {
    internal = 80
    external = 8082
  }
  networks_advanced {
    name = data.docker_network.venue.name
  }
}
HCL

该声明从完整 Courtyard 镜像创建一个容器。嵌套的 ports 块发布 HTTP 服务;networks_advanced 把容器连接到已有场地网络。正式服务使用 8081,参考站使用 8083,因此 8082 避免了冲突。引用网络不会使它变成受管资源。

初始化此根。init 准备 provider 插件,并不创建基础设施:

terraform init

预期看到 Terraform has been successfully initialized!。已提供的本地镜像提供版本 3.0.2。.terraform 保存已初始化的 provider,.terraform.lock.hcl 记录选中的 provider 和校验和。锁文件应与配置一起保留。terraform state list 输出记住的地址:

terraform state list

输出包含 docker_container.preview、docker_container.reference,以及镜像和网络数据源。预览地址出现在列表中,并不能证明容器仍然存在。

fmt 整理 HCL 的空格格式;validate 检查配置语法和 provider 参数类型。两者都不能证明网站正在运行:

terraform fmt
terraform validate

预期看到 Success! The configuration is valid.。若遇到语法错误,阅读文件名和行号,将 preview.tf 与上面的完整块对照,修正后再次运行 fmt 和 validate。不要为了消除错误而删除状态或重写共享配置。现在,这份声明可以重建目标并保持参考站不变。

审阅并应用精确恢复计划

本步骤中,你将区分记录状态与实时基础设施,恢复完整 Courtyard 流程,并确认其他对象没有变化。从同一根中的 Workstation 开始。

在变更前预览计划

terraform plan 通过读取 Docker 更新其认识,将实际情况与声明比较并提出变更。-out=recovery.tfplan 把建议保存到二进制计划文件,使 apply 可以执行已经审阅的计划。保存的计划可能含敏感配置;本练习没有凭据。将它留在项目目录中。

terraform plan -out=recovery.tfplan

先观察记录中预览 ID 的刷新,再查找:

## docker_container.preview will be created
...
Plan: 1 to add, 0 to change, 0 to destroy.

资源前的 + 表示创建;~ 表示原地更新;- 表示销毁;-/+ 表示替换。缺失的预览站只需一次创建。参考站不应有任何拟议变更。不得创建、替换或销毁网络:它们是已有共享数据源,不是此处拥有的资源。

若出现销毁、替换或其他资源,先停止,不要 apply。检查 pwd、preview.tf,以及是否误改了 reference.tf。根据已提供示例只修正自己的误改,再生成新计划。错误网络名可能导致 network not found;应对照已有 data 块,不要创建替代共享网络。不要按名称前缀移除容器,也不要把 terraform destroy 当作恢复捷径。

执行已审阅的计划

terraform apply recovery.tfplan 执行保存的变更。与不带计划文件名的 apply 不同,它不会再次要求输入 yes;保存计划本身不代表批准执行,因此必须在此命令前审阅:

terraform apply recovery.tfplan
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

若 Terraform 提示计划已过期,说明其他操作在计划后改变了状态。应重新生成并审阅计划,然后再 apply。若端口 8082 被占用,应检查具体冲突容器,不要删除全部容器。准备好的实验中该端口应空闲;请重新检查外部端口配置,并保留 8081 和 8083。

切换到 Venue Preview,容器启动后重新加载。应显示 VENUE PREVIEW / Courtyard。依次进入 Meet the two studios → Find directions and the programme → Download the day programme。打开下载文件,确认 Courtyard 和两间工作室的演示时间。完整页面、样式、插画和下载来自提供的镜像,而不是新的空 Nginx 欢迎页。

切换到 Live Studios 和 Reference Preview。原始访客流程都应正常,分别显示 City 和 Riverside。只看首页名称不同并不足以证明保留成功;底层对象必须仍是原来的对象。

确认收敛与保留结果

返回 Workstation。第二次 plan 会重新观察当前声明和 Docker 实际情况:

terraform plan
No changes. Your infrastructure matches the configuration.

这就是收敛:所需资源已按声明设置存在。Terraform 不会持续监视和修复容器;后续发生变化时,需要由人或自动化重新执行流程。本次恢复重建可替换基础设施和提供的网站内容,不恢复丢失的用户数据或整台主机。

terraform state show 显示一个资源记录的属性。将其中 id 与 Docker 实际 ID 比较。Docker 的 --format 选项选择字段;单引号保持模板字面值:

terraform state show docker_container.preview
docker inspect --format '{{.Id}}' tide-preview

两者应标识同一个新容器。ID 可能不同,不要把示例 ID 复制进状态。只读查看原始相邻站点和两个已有网络:

docker inspect --format '{{.Name}} {{.Id}} {{.State.StartedAt}}' tide-live tide-reference
docker network inspect --format '{{.Name}} {{.Id}}' tide-city tide-courtyard

课程会将这些身份与原始值比较。正式容器在此根范围之外,参考站则是此根中刻意保留的受管资源。两种边界都重要。你已经恢复一个缺失预览站,同时保留其他站点和共享基础设施。

总结

你使用 HCL 和固定版本的 Docker provider 声明了缺失的场地容器。数据源让共享网络和镜像保持在此根的受管所有权之外。你比较了配置、状态和实时 Docker 对象,应用一次审阅后的创建,检查完整访客流程,并在保留正式站和参考站的同时得到无变更计划。