Managing Applications and Infrastructure with Terraform-Deploying Infrastructure with Terraform-(1)Terraform Basics and a Docker Deployment-(7)Breaking Out Our Variables and Outputs
Managing Applications and Infrastructure with Terraform-Deploying Infrastructure with Terraform
1. Terraform Basics and a Docker Deployment
7. Breaking Out Our Variables and Outputs
In the last post, we have separated the variables from the "resource" configuration blocks into the "variable" blocks, so that the script is more readable and well arranged. But they still stayed in the "main.tf" file.
In this post, we will move the "variable" and "output" configuration blocks outside of the "main.tf" file into two new files.
The standard Terraform module structure expects the layout documented below. Everything is optional except for the root module.
- Root module. This is the only required element for the standard module structure. Terraform files must exist in the root directory of the repository. This should be the primary entrypoint for the module and is expected to be opinionated. For the Consul module the root module sets up a complete Consul cluster. It makes a lot of assumptions however, and we expect that advanced users will use specific nested modules to more carefully control what they want.
- main.tf, variables.tf, outputs.tf. These are the recommended filenames for a minimal module, even if they're empty. main.tf should be the primary entrypoint. For a simple module, this may be where all the resources are created. For a complex module, resource creation may be split into multiple files but any nested module calls should be in the main file. variables.tf and outputs.tf should contain the declarations for variables and outputs, respectively.
- ...
Move below content from "main.tf" to a new "variables.tf" file.
~/docker# vim variables.tf
variable "image" { description = "image for container" default = "ghost:latest" } variable "container_name" { description = "Name of Container" default = "blog" } variable "int_port" { description = "Internal port for container" default = "2368" } variable "ext_port" { description = "External port for container" default = "80" }
Move below content in "main.tf" to "outputs.tf" file.
~/docker# vim outputs.tf
# Output name and ip address output "IP_Address" { value = docker_container.container_id.ip_address } output "container_name" { value = docker_container.container_id.name }
PS: Because we have moved the "variable" and "output" configuration blocks outside of the "main.tf" file, here is what the "main.tf" file now looks like.
terraform { required_providers { aws = { source = "hashicorp/aws" } docker = { source = "terraform-providers/docker" } } required_version = ">= 0.13" } # Start the container, reference the above "docker_image" and "image_id" resource "docker_container" "container_id" { name = var.container_name image = docker_image.image_id.latest ports { internal = var.int_port external = var.ext_port } } # Download the latest Ghost image resource "docker_image" "image_id" { name = var.image }
~/docker# ls
main.tf outputs.tf terraform.tfstate terraform.tfstate.backup variables.tf
~/docker# terraform plan
Refreshing Terraform state in-memory prior to plan... The refreshed state will be used to calculate this plan, but will not be persisted to local or remote state storage. ------------------------------------------------------------------------ An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # docker_container.container_id will be created + resource "docker_container" "container_id" { + attach = false + bridge = (known after apply) + command = (known after apply) + container_logs = (known after apply) + dns = (known after apply) + dns_opts = (known after apply) + entrypoint = (known after apply) + exit_code = (known after apply) + gateway = (known after apply) + hostname = (known after apply) + id = (known after apply) + image = (known after apply) + ip_address = (known after apply) + ip_prefix_length = (known after apply) + ipc_mode = (known after apply) + log_driver = (known after apply) + log_opts = (known after apply) + logs = false + must_run = true + name = "blog" + network_data = (known after apply) + read_only = false + restart = "no" + rm = false + shm_size = (known after apply) + start = true + user = (known after apply) + working_dir = (known after apply) + ports { + external = 80 + internal = 2368 + ip = "0.0.0.0" + protocol = "tcp" } } # docker_image.image_id will be created + resource "docker_image" "image_id" { + id = (known after apply) + latest = (known after apply) + name = "ghost:latest" } Plan: 2 to add, 0 to change, 0 to destroy. Changes to Outputs: + IP_Address = (known after apply) + container_name = "blog" ------------------------------------------------------------------------ Note: You didn't specify an "-out" parameter to save this plan, so Terraform can't guarantee that exactly these actions will be performed if "terraform apply" is subsequently run.
~/docker# terraform apply
An execution plan has been generated and is shown below. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # docker_container.container_id will be created + resource "docker_container" "container_id" { + attach = false + bridge = (known after apply) + command = (known after apply) + container_logs = (known after apply) + dns = (known after apply) + dns_opts = (known after apply) + entrypoint = (known after apply) + exit_code = (known after apply) + gateway = (known after apply) + hostname = (known after apply) + id = (known after apply) + image = (known after apply) + ip_address = (known after apply) + ip_prefix_length = (known after apply) + ipc_mode = (known after apply) + log_driver = (known after apply) + log_opts = (known after apply) + logs = false + must_run = true + name = "blog" + network_data = (known after apply) + read_only = false + restart = "no" + rm = false + shm_size = (known after apply) + start = true + user = (known after apply) + working_dir = (known after apply) + ports { + external = 80 + internal = 2368 + ip = "0.0.0.0" + protocol = "tcp" } } # docker_image.image_id will be created + resource "docker_image" "image_id" { + id = (known after apply) + latest = (known after apply) + name = "ghost:latest" } Plan: 2 to add, 0 to change, 0 to destroy. Changes to Outputs: + IP_Address = (known after apply) + container_name = "blog" 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 docker_image.image_id: Creating... docker_image.image_id: Still creating... [10s elapsed] docker_image.image_id: Still creating... [20s elapsed] docker_image.image_id: Creation complete after 28s [id=sha256:98c65d66926b2da9fbb696d43aadfaf3fee847b7185e132e199532bc549aeba5ghost:latest] docker_container.container_id: Creating... docker_container.container_id: Creation complete after 2s [id=ffb0afe6004c7ecb4b205a5b7bcc903debf22aa654b5381f22180b06ad357206] Apply complete! Resources: 2 added, 0 changed, 0 destroyed. Outputs: IP_Address = 172.17.0.2 container_name = blog
References
Creating Modules