一、环境准备
Terraform 和 Docker
在正式开始例子之前,我们必须保证环境中已经安装了Terraform
、docker
,前者参照专栏内部的上篇文章,docker
的安装参照这篇文章《文章TODO》。
Provider
插件缓存配置
在Terraform
的整个执行流程中,我们在使用到Terraform init
命令时,该工具会分析我们代码中使用到的Provider
,并尝试下载Provider
插件到本地,如果我们不进行特殊的设置,每次执行init
都会尝试去下载插件,并且每个项目都回保存自己独立的插件,相当浪费空间。这怎么办呢?
这时我们可以使用插件缓存,基本的原理只要插件下载成功一次,就会保存在指定的插件缓存目录,其它项目再次下载,就会拷贝缓存内容到项目目录,甚至在系统支持上,Terraform
还会使用符号连接这个缓存路径,并不直接拷贝插件内容。
有两种方式,第一种方式是配置TF_PLUGIN_CACHE_DIR
环境变量:
#务必确保这个目录下已经创建好plugin-cache这个文件夹
export TF_PLUGIN_CACHE_DIR="$HOME/.terraform.d/plugin-cache"
第二种方式是使用CLI
配置文件,基于Linux
环境,在用户的/home
目录下创建名为 ".terraformrc" 的文件:
plugin_cache_dir = "$HOME/.terraform.d/plugin-cache"
需要注意的是:有必要关注缓存路径的空间增长,择机选择性地手工清理不必要的Provider
插件。
二、实战
这次实战的目的是通过Terraform
部署基于Docker的Nginx
环境,并能成功访问到Nginx
的欢迎主页。
2.1 定义资源
在这里我们使用到Github
上的项目
[terraform-provider-docker] https://github.com/kreuzwerker/terraform-provider-docker
提供的Provider
插件,编写资源文件main.tf
。
terraform {
#定义所需的Provider
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 2.13.0"
}
}
}
# 配置docker provider
provider "docker" {}
#创建一个docker镜像资源
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = false
}
#创建一个docker容器资源
#这部分的资源定义,类似"docker run --name nginx -p8080:80 -d nginx:latest"
resource "docker_container" "nginx" {
image = docker_image.nginx.latest
name = "tutorial"
ports {
internal = 80
external = 8000
}
}
#接下来还可以继续定义服务资源
2.2 执行创建
关于基础设施的资源已经定义完成,接下来就是在安装好Terraform
和docker
的服务器上执行部署。
首先,为了区分项目,达到隔离资源的目的,我们先在工程目录创建一个新文件夹:
#创建目录
$mkdir learn-terraform-docker-container
#进入目录
$cd learn-terraform-docker-container
然后上传main.tf
到当前文件夹。接着在当前目录执行Terraform init
初始化环境。
$Terraform init
小提示:环境初始过程花费的时间会与你的服务器网络环境密切相关,请耐心等待,如果失败,请多尝试几次!
如图上所示,环境初始化成功,观察本地目录,多了一些文件和文件夹。
.terraform
隐藏文件夹中存储着我们下载的Provider
插件内容,.terraform.lock.hcl
记录了provider
插件的一些依赖信息。如果进入我们前面设置的缓存插件目录,会多了这个插件的内容。
接下来,我们预览资源部署情况terraform plan
。
$terraform plan
执行结果输出如下:
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# docker_container.nginx will be created
+ resource "docker_container" "nginx" {
+ attach = false
+ bridge = (known after apply)
+ command = (known after apply)
+ container_logs = (known after apply)
+ entrypoint = (known after apply)
+ env = (known after apply)
+ exit_code = (known after apply)
+ gateway = (known after apply)
+ hostname = (known after apply)
+ id = (known after apply)
+ image = (known after apply)
+ init = (known after apply)
+ ip_address = (known after apply)
+ ip_prefix_length = (known after apply)
+ ipc_mode = (known after apply)
+ log_driver = "json-file"
+ logs = false
+ must_run = true
+ name = "tutorial"
+ network_data = (known after apply)
+ read_only = false
+ remove_volumes = true
+ restart = "no"
+ rm = false
+ security_opts = (known after apply)
+ shm_size = (known after apply)
+ start = true
+ stdin_open = false
+ tty = false
+ healthcheck {
+ interval = (known after apply)
+ retries = (known after apply)
+ start_period = (known after apply)
+ test = (known after apply)
+ timeout = (known after apply)
}
+ labels {
+ label = (known after apply)
+ value = (known after apply)
}
+ ports {
+ external = 8000
+ internal = 80
+ ip = "0.0.0.0"
+ protocol = "tcp"
}
}
# docker_image.nginx will be created
+ resource "docker_image" "nginx" {
+ id = (known after apply)
+ keep_locally = false
+ latest = (known after apply)
+ name = "nginx:latest"
+ output = (known after apply)
+ repo_digest = (known after apply)
}
Plan: 2 to add, 0 to change, 0 to destroy.
根据输出内容可以看到增加了两个资源,包括镜像和容器。无更改和销毁项。
接下来执行部署资源terraform apply
。
$terraform apply
执行结果输出如下:
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# docker_container.nginx will be created
+ resource "docker_container" "nginx" {
+ attach = false
+ bridge = (known after apply)
+ command = (known after apply)
+ container_logs = (known after apply)
+ entrypoint = (known after apply)
+ env = (known after apply)
+ exit_code = (known after apply)
+ gateway = (known after apply)
+ hostname = (known after apply)
+ id = (known after apply)
+ image = (known after apply)
+ init = (known after apply)
+ ip_address = (known after apply)
+ ip_prefix_length = (known after apply)
+ ipc_mode = (known after apply)
+ log_driver = "json-file"
+ logs = false
+ must_run = true
+ name = "tutorial"
+ network_data = (known after apply)
+ read_only = false
+ remove_volumes = true
+ restart = "no"
+ rm = false
+ security_opts = (known after apply)
+ shm_size = (known after apply)
+ start = true
+ stdin_open = false
+ tty = false
+ healthcheck {
+ interval = (known after apply)
+ retries = (known after apply)
+ start_period = (known after apply)
+ test = (known after apply)
+ timeout = (known after apply)
}
+ labels {
+ label = (known after apply)
+ value = (known after apply)
}
+ ports {
+ external = 8000
+ internal = 80
+ ip = "0.0.0.0"
+ protocol = "tcp"
}
}
# docker_image.nginx will be created
+ resource "docker_image" "nginx" {
+ id = (known after apply)
+ keep_locally = false
+ latest = (known after apply)
+ name = "nginx:latest"
+ output = (known after apply)
+ repo_digest = (known after apply)
}
Plan: 2 to add, 0 to change, 0 to destroy.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value:yes
输入yes
明确要执行部署。
部署完成!未出现错误。
然后查看docker容器中是否已经创建了nginx
。
$docker ps
有了,创建成功了,然后curl
访问一下,也能获取到欢迎主页!
至此,部署创建成功,我们观察项目目录,多了一个terraform.tfstate
文件,这个就是状态文件,相当重要,切记不要尝试去手动修改它!
2.3 执行销毁
执行销毁那是相当简单了,用项目目录下执行terraform destroy
命令即可。
$terraform destroy