Skip to main content

[Terraform] 3 - Destroy Infrastructure

Closing out the series that started in terraform lab 1 and continued in terraform lab 2: tearing down everything Terraform built, and actually verifying the teardown was clean instead of just trusting the command exited without error.

Destroy

terraform destroy is the inverse of apply — it terminates every resource currently tracked in state. Scoped strictly to this state file: anything running outside it, managed by a different project or created by hand, is left alone.

terraform destroy

Screenshot: terraform destroy plan showing docker_image.nginx marked for destruction, the confirmation prompt, and all three resources being destroyed in sequence.

Same confirmation flow as apply — a plan first (3 to destroy: both containers from lab 2 plus the image itself), then yes to confirm. Terraform tears down in dependency order: both containers first, then the image they depended on, since a container can’t outlive the image it was built from.

Verify

The exit message says Destroy complete! Resources: 3 destroyed, but I wanted to actually confirm nothing was left behind rather than take that on faith — checking both Terraform’s own state and Docker directly, since Terraform can only report on what it tracks:

terraform show
terraform state list
docker ps -a
docker image ls

Screenshot: terraform show reporting an empty state, terraform state list returning nothing, docker ps -a showing no containers, and docker image ls showing only unrelated images from other projects.

Four confirmations stacked here:

  • terraform show — “The state file is empty. No resources are represented.” Terraform’s own bookkeeping is clean.
  • terraform state list — no output at all, same conclusion from a different angle.
  • docker ps -a — no containers, including stopped ones (-a matters here — a plain docker ps only shows running containers, and wouldn’t catch a container that failed to destroy cleanly and got left in a stopped state).
  • docker image ls — the nginx:latest image is gone too, since keep_locally = false told Terraform to remove it along with the containers. What’s left — chamilo_web, mysql, php, an unrelated nginx:alpine — are all images from other, unrelated projects on this machine. Exactly the scoping the intro paragraph promised: destroy only touches what the project’s state file actually tracks.

That closes the loop on the basic lifecycle: init → plan → apply → modify → plan → apply again → destroy → verify. The same shape scales up to configs with dozens of resources across multiple providers — the commands don’t change, just the size of the plan output.