ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

90DaysOfDevOps 第 60 天:用 Terraform 管理 Docker 容器、Provisioners 与 Modules

90DaysOfDevOps 第 60 天:用 Terraform 管理 Docker 容器、Provisioners 与 Modules 文档/教程【免费下载链接】90DaysOfDevOpsThis repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.项目地址https://gitcode.com/gh_mirrors/90/90DaysOfDevOps点击查看免费下载本文是 90DaysOfDevOps 开源学习路线图中「IaC基础设施即代码」阶段的实战篇在 Day 59 用 Terraform VirtualBox 创建虚拟机之后本篇将把同样的声明式思路迁移到本地 Docker 环境——先用kreuzwerker/docker社区 Provider 部署一个对外暴露的 NGINX 容器再进一步把 docker-compose 风格的 WordPress MySQL 架构完整改写为 Terraform 配置并梳理 Provisioners 与 Modules 两大组织机制。读完本文你将掌握用 Terraform 声明 Docker 镜像、容器、网络与卷资源通过terraform init/apply/destroy管理容器生命周期以及何时用local-exec、remote-exec等 Provisioner 兜底非声明式逻辑、如何用 Modules 拆分可复用基础设施组件。前置回顾从 VirtualBox 虚拟机到 Docker 容器Day 60 是 IaC 系列的第 3 站。在 Day 59 中我们已经使用terra-farm/virtualbox社区 Provider 在本地 VirtualBox 中声明式地创建了 2 台 Ubuntu 虚拟机对应源码 virtualbox.tf并体验了terraform init、terraform plan、terraform apply与terraform destroy的完整生命周期还引入了变量与输出的概念。本节的核心思路不变写一份描述「期望状态」的.tf配置交给 Terraform 去执行差异比对drift与资源编排。区别仅在于这次的目标不是虚拟机而是本地 Docker 守护进程——Terraform 通过 Docker Provider 与dockersocket 通信把镜像拉取、容器创建、端口映射、网络与卷挂载全部纳入 Terraform 状态terraform.tfstate管理。定位说明在真实生产环境中Terraform 管理 Docker 并不常见Kubernetes 才是更合适的容器编排层但作为学习 IaC 抽象模型、体验 Provider 与资源声明的过渡实验它是成本最低、反馈最快的演练环境。第一个实验用 Terraform 部署 NGINX 容器并暴露到 8000 端口1. 编写配置镜像资源 容器资源在项目里新建一个目录例如Docker/创建docker.tf内容如下。仓库中已有完整可用的示例文件 docker.tf建议直接对照阅读terraform { required_providers { docker { source kreuzwerker/docker version 2.16.0 } } } provider docker {} resource docker_image nginx { name nginx:latest keep_locally false } resource docker_container nginx { image docker_image.nginx.latest name tutorial ports { internal 80 external 8000 } }逐段解读这份配置terraform块声明 Provider 来源与版本。这里用的是社区维护的kreuzwerker/dockerProvider非 HashiCorp 官方固定版本2.16.0可保证行为可复现避免上游更新带来的隐性变更。provider docker {}无参实例化 Provider。默认情况下它直接使用本机的 Docker 守护进程与dockerCLI 同一 socket。docker_image.nginx声明期望存在的镜像。name nginx:latest指定镜像标签keep_locally false表示当资源被销毁时不保留本地镜像副本若设为true则terraform destroy不会删除已拉取的镜像。docker_container.nginx声明期望运行的容器。image docker_image.nginx.latest引用了上方镜像资源的latest属性形成资源间依赖Terraform 会先创建镜像再创建容器name tutorial指定容器名ports块把容器内部 80 端口映射到宿主机的 8000 端口。2. 初始化terraform init 拉取 Provider首次执行前必须先初始化下载kreuzwerker/dockerProvider 插件并生成.terraform目录与锁定文件terraform init执行成功后的终端输出如图来自 Day60_IAC1.pngTerraform 初始化后端、安装 docker Provider 插件并提示初始化完成。3. 应用与验证terraform apply docker ps执行应用命令Terraform 会先拉取nginx:latest镜像、再创建容器terraform apply从源码与运行截屏Day60_IAC2.png可以看到apply完成后立即执行docker ps即出现名为tutorial的 nginx 容器处于运行状态。此时打开浏览器访问http://localhost:8000/即可看到 NGINX 默认欢迎页Day60_IAC3.png说明容器内部 80 端口已通过宿主 8000 端口对外提供服务4. 清理不需要时执行terraform destroyTerraform 会按依赖逆序移除容器与镜像keep_locally false时镜像一并删除。小结这个最小实验证明了「镜像 容器」这两个资源类型以及terraform state对容器生命周期的接管能力——这正是 docker-compose 与 Terraform 的交叉地带。进阶实验把 docker-compose 的 WordPress MySQL 改写为 Terraform为了让演示更有说服力接下来把容器章节中用 docker-compose 编排的 WordPress MySQL 架构完整改写为 Terraform 配置。仓库中的对应文件为 docker-wordpress.tf。完整配置terraform { required_providers { docker { source kreuzwerker/docker version 2.16.0 } } } provider docker {} variable wordpress_port { default 8080 } resource docker_volume db_data { name db_data } resource docker_network wordpress_net { name wordpress_net } resource docker_container db { name db image mysql:5.7 restart always network_mode wordpress_net env [ MYSQL_ROOT_PASSWORDwordpress, MYSQL_PASSWORDwordpress, MYSQL_USERwordpress, MYSQL_DATABASEwordpress ] mounts { type volume target /var/lib/mysql source db_data } } resource docker_container wordpress { name wordpress image wordpress:latest restart always network_mode wordpress_net env [ WORDPRESS_DB_HOSTdb:3306, WORDPRESS_DB_USERwordpress, WORDPRESS_DB_NAMEwordpress, WORDPRESS_DB_PASSWORDwordpress ] ports { internal 80 external ${var.wordpress_port} } }这份配置引入了比上一示例更丰富的资源类型逐个说明variable wordpress_port声明输入变量default 8080提供默认值。WordPress 容器把 80 端口映射到external ${var.wordpress_port}意味着可以通过变量或-var、TF_VAR_*、terraform.tfvars等方式见 Day 59 的变量章节灵活调整对外端口。docker_volume db_data声明命名卷对应 compose 中的db_datavolume。它是 MySQL 数据持久化的载体。docker_network wordpress_net声明自定义网络对应 compose 中的网络定义用于让db与wordpress两个容器通过容器名互相解析。docker_container dbMySQL镜像mysql:5.7restart always让守护进程在容器退出后自动重启network_mode wordpress_net加入自定义网络env数组等价于 compose 的environment注入MYSQL_ROOT_PASSWORD、MYSQL_PASSWORD、MYSQL_USER、MYSQL_DATABASEmounts块把db_data卷挂载到容器内/var/lib/mysqlMySQL 数据目录实现数据持久化。docker_container wordpress镜像wordpress:latestenv中WORDPRESS_DB_HOSTdb:3306让 WordPress 通过容器名db访问 MySQL 服务依赖wordpress_net网络的 DNS 解析其余变量对应数据库账号、库名与密码与db容器的env保持一致。执行流程与验证把配置放入新目录后依次执行terraform init # 拉取 docker Provider terraform apply # 创建卷、网络、两个容器 docker ps # 查看运行中的容器apply完成后执行docker ps可以看到mysql:5.7镜像的db容器与wordpress:latest镜像的wordpress容器均处于运行状态如图 Day60_IAC5.png随后在浏览器打开http://localhost:8080/即可进入 WordPress 安装向导。整个初始化流程与之前用 docker-compose 走通的过程完全一致完成安装后文章、页面等数据都写入 MySQL 的db_data卷中数据随容器重建而保留。与 docker-compose 的对照能力docker-composeTerraform Docker Provider镜像image:docker_image资源容器services:docker_container资源网络networks:docker_network资源卷volumes:docker_volume资源环境变量environment:env [...]端口映射ports:ports { internal / external }重启策略restart:restart always状态管理无状态文件terraform.tfstate记录全部资源两者的声明式思想一致但 Terraform 会把资源生命周期纳入统一的 state 管理并能与其他云资源VPC、VM、K8s 集群编排在同一个配置中。生产环境提示原文档明确指出容器直接运行方式的验证价值大于生产价值。若真的要对外提供网站服务应优先考虑 Kubernetes 编排下一篇将演示 kubernetes.tf 用 Terraform 声明 Namespace、Deployment 与 Service容器方案只适合测试与本地演练。Provisioners声明式之外的命令执行兜底为什么需要 ProvisionersTerraform 的核心哲学是声明式配置只描述「最终状态」Terraform 负责计算执行计划。但现实总有些动作无法被任何资源类型表达例如初始化应用配置、执行系统级脚本、注册外部服务。此时引入Provisioners——它们在资源创建或销毁后执行命令是「把命令式逻辑塞进声明式配置」的兜底通道。原文档也给出明确的取舍建议只有当你没有其他替代方案时才使用因为它会把无法追踪的副作用带进配置降低可预测性。local-exec 与 remote-exec原文档给出的local-exec示例——在本地机器上执行命令可用于打印信息、调用本地脚本、触发后续工具链resource docker_container db { # ... provisioner local-exec { command echo The servers IP address is ${self.private_ip} } }其中${self.private_ip}引用当前资源自身的属性local-exec会在本地 shell 中执行这条 echo 命令。remote-exec则是在远程资源创建完成后通过 SSH/WinRM 等通道在目标机器上执行脚本。它适合处理操作系统特定的初始化或作为包装器把 Ansible、Chef、Puppet 等配置管理工具串进资源创建流程。Provisioner 类型总览原文档列举的常用 Provisioner 及使用场景file把文件或目录复制到远程资源常配合remote-exec使用。local-exec在 Terraform 运行的本地机器上执行命令无远程访问要求。remote-exec在远程资源上执行脚本需先打通 SSH/WinRM 连接。vendor 类集成通过封装调用外部配置管理工具完成更复杂的配置下发AnsibleChefPuppetModules把基础设施拆成可复用组件什么是 ModulesModules 是多个资源共同组成的容器一个模块就是同一目录下的一组.tf文件的集合通常包含main.tf、variables.tf、outputs.tf。Terraform 默认把当前工作目录视为根模块而你可以在根模块中通过module块引用其他模块本地目录或第三方注册中心。为什么要用 Modules原文档给出了两个核心动机职责分离当同一个项目需要同时构建 VMs、VPC、Security Groups 和 Kubernetes 集群时把不同类型的资源拆进各自模块可以更清晰地定义资源边界与组织方式避免单个目录堆积大量互不相关的资源声明。复用与共享模块可以跨项目复用也可以发布到公开注册中心供社区使用——不用重新发明轮子。团队把通用组件如网络、安全组、集群封装成模块后新项目只需声明模块引用并传参即可。结合仓库结构可以直观理解模块化思想IaC 目录下 Docker/、Docker-Wordpress/、Virtualbox/、Kubernetes/ 各自独立成目录每个目录就是一个自包含的模块——每个模块只负责一类基础设施可单独init/apply也可被上层模块引用。这正是「把基础设施分解为组件组件即模块」的落地形态。本篇小结与下一步用kreuzwerker/dockerProvider 声明镜像与容器资源terraform init/apply/destroy即可完成 NGINX 的部署、验证与清理通过 volume、network、env、mounts、restart 等参数可将 docker-compose 的 WordPress MySQL 架构 1:1 改写为 Terraform 配置并纳入 state 管理Provisionersfile / local-exec / remote-exec以及 Ansible、Chef、Puppet 等 vendor 集成是声明式模型的兜底手段仅在无替代方案时使用Modules 是资源分组的复用单元帮助拆分复杂基础设施并支持跨项目共享。下一篇将进入「Terraform Kubernetes」使用 kubernetes.tf 示例声明 Namespace、Deployment含 replicas、selector、容器端口与 NodePort Service把同样的声明式能力延伸到集群编排层。赞分享文档/教程【免费下载链接】90DaysOfDevOpsThis repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.项目地址https://gitcode.com/gh_mirrors/90/90DaysOfDevOps点击查看免费下载相关推荐90DaysOfDevOps 第 60 天用 Terraform 管理 Docker 容器、Provisioners 与 Modules90DaysOfDevOps 第 60 天用 Terraform 管理 Docker 容器、Provisioners 与 Modules 本篇指南以 90Da文档/教程90DaysOfDevOps 第 60 天用 Terraform 管理 Docker 容器、Provisioners 与 Modules 实战指南90DaysOfDevOps 第 60 天用 Terraform 管理 Docker 容器、Provisioners 与 Modules 实战指南 本篇技术指文档/教程90DaysOfDevOps使用 Terraform 管理 Docker 容器、Provisioners 与 ModulesDay 6090DaysOfDevOps使用 Terraform 管理 Docker 容器、Provisioners 与 ModulesDay 60 本文是 90Da文档/教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表