Introduction

In the realm of infrastructure as code, Terraform stands as a pivotal tool, enabling IT professionals to manage and provision infrastructure through code. A critical aspect of this lifecycle management is the ability to safely and effectively destroy resources that are no longer needed, ensuring cost-efficiency and alignment with organizational needs. This article delves into a practical example of using Terraform to destroy resources, specifically focusing on a Docker Nginx container and image.

Scenario Overview

In our case, Terraform is employed to manage Docker resources, namely a Docker container and image of Nginx, a popular web server. The output provided illustrates the process of destroying these resources using Terraform’s terraform destroy command. This command is a crucial aspect of infrastructure management, allowing for the removal of resources that were previously created using Terraform.

Execution Plan

Before any action is taken, Terraform generates an execution plan. This plan is essential for understanding what Terraform will do before making any changes. In our scenario, the plan indicates two actions:

  1. Destruction of docker_container.nginx: This resource represents a Docker container running Nginx. The plan lists various attributes of the container, such as its command, environment variables, network settings, and more, all of which will be set to null, indicating their removal.
  2. Destruction of docker_image.nginx: This resource is the Docker image of Nginx. Attributes like the image ID and name are also slated for removal.

Confirmation and Destruction

Terraform requires explicit confirmation (yes) from the user to proceed with the destruction. This is a safety mechanism to prevent accidental deletion of resources. Upon confirmation, Terraform proceeds to destroy the specified resources. The process, as indicated in the output, is swift:

  • Destruction of Docker Container: The container is terminated and removed. This step involves stopping the container and deleting its instance from the host system.
  • Destruction of Docker Image: The image of Nginx is also removed. This step frees up space and ensures that unused images are not left consuming resources.
$ terraform destroy
docker_image.nginx: Refreshing state... [id=sha256:6c7be49d2a11cfab9a87362ad27d447b45931e43dfa6919a8e1398ec09c1e353nginx]
docker_container.nginx: Refreshing state... [id=4362cd19c6160af538a1522f9069c314ccd5ddbed702b123f6b9abc0ebf08c50]

Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
  - destroy

Terraform will perform the following actions:

  # docker_container.nginx will be destroyed
  - resource "docker_container" "nginx" {
      - attach                                      = false -> null
      - command                                     = [
          - "nginx",
          - "-g",
          - "daemon off;",
        ] -> null
      - container_read_refresh_timeout_milliseconds = 15000 -> null
      - cpu_shares                                  = 0 -> null
      - dns                                         = [] -> null
      - dns_opts                                    = [] -> null
      - dns_search                                  = [] -> null
      - entrypoint                                  = [
          - "/docker-entrypoint.sh",
        ] -> null
      - env                                         = [] -> null
      - group_add                                   = [] -> null
      - hostname                                    = "4362cd19c616" -> null
      - id                                          = "4362cd19c6160af538a1522f9069c314ccd5ddbed702b123f6b9abc0ebf08c50" -> null
      - image                                       = "sha256:6c7be49d2a11cfab9a87362ad27d447b45931e43dfa6919a8e1398ec09c1e353" -> null
      - init                                        = false -> null
      - ipc_mode                                    = "private" -> null
      - log_driver                                  = "json-file" -> null
      - log_opts                                    = {} -> null
      - logs                                        = false -> null
      - max_retry_count                             = 0 -> null
      - memory                                      = 0 -> null
      - memory_swap                                 = 0 -> null
      - must_run                                    = true -> null
      - name                                        = "tutorial" -> null
      - network_data                                = [
          - {
              - gateway                   = "172.17.0.1"
              - global_ipv6_address       = ""
              - global_ipv6_prefix_length = 0
              - ip_address                = "172.17.0.2"
              - ip_prefix_length          = 16
              - ipv6_gateway              = ""
              - mac_address               = "02:42:ac:11:00:02"
              - network_name              = "bridge"
            },
        ] -> null
      - network_mode                                = "default" -> null
      - privileged                                  = false -> null
      - publish_all_ports                           = false -> null
      - read_only                                   = false -> null
      - remove_volumes                              = true -> null
      - restart                                     = "no" -> null
      - rm                                          = false -> null
      - runtime                                     = "runc" -> null
      - security_opts                               = [] -> null
      - shm_size                                    = 64 -> null
      - start                                       = true -> null
      - stdin_open                                  = false -> null
      - stop_signal                                 = "SIGQUIT" -> null
      - stop_timeout                                = 0 -> null
      - storage_opts                                = {} -> null
      - sysctls                                     = {} -> null
      - tmpfs                                       = {} -> null
      - tty                                         = false -> null
      - wait                                        = false -> null
      - wait_timeout                                = 60 -> null

      - ports {
          - external = 8000 -> null
          - internal = 80 -> null
          - ip       = "0.0.0.0" -> null
          - protocol = "tcp" -> null
        }
    }

  # docker_image.nginx will be destroyed
  - resource "docker_image" "nginx" {
      - id           = "sha256:6c7be49d2a11cfab9a87362ad27d447b45931e43dfa6919a8e1398ec09c1e353nginx" -> null
      - image_id     = "sha256:6c7be49d2a11cfab9a87362ad27d447b45931e43dfa6919a8e1398ec09c1e353" -> null
      - keep_locally = false -> null
      - name         = "nginx" -> null
      - repo_digest  = "nginx@sha256:4c0fdaa8b6341bfdeca5f18f7837462c80cff90527ee35ef185571e1c327beac" -> null
    }

Plan: 0 to add, 0 to change, 2 to destroy.
Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes
docker_container.nginx: Destroying... [id=4362cd19c6160af538a1522f9069c314ccd5ddbed702b123f6b9abc0ebf08c50]
docker_container.nginx: Destruction complete after 0s
docker_image.nginx: Destroying... [id=sha256:6c7be49d2a11cfab9a87362ad27d447b45931e43dfa6919a8e1398ec09c1e353nginx]
docker_image.nginx: Destruction complete after 0s

Destroy complete! Resources: 2 destroyed.

Post-Destruction

Upon completion, Terraform reports that the resources have been destroyed. This is a confirmation that the state of Terraform now reflects the absence of these resources. It’s important to note that Terraform’s state management ensures a consistent view of what the infrastructure looks like before and after any changes.

Key Takeaways

  1. Safety and Confirmation: Terraform’s requirement for explicit confirmation to destroy resources minimizes the risk of accidental deletion.
  2. State Management: Terraform’s state file is crucial in tracking the lifecycle of resources, ensuring that the actual infrastructure matches the defined state.
  3. Efficiency: The ability to destroy resources easily allows for better resource management and cost-efficiency.
  4. Visibility: The execution plan provides transparency and control over the changes being applied to the infrastructure.

Conclusion

In conclusion, Terraform’s ability to manage the entire lifecycle of infrastructure resources, including safe destruction, is invaluable for modern infrastructure management. This case study with Docker Nginx illustrates how Terraform can be used to maintain a clean, efficient, and well-documented infrastructure environment.