Intro and Credits

So, I have to thank one of my friends Mr. Jamie Bowman, because he did an initial blog post that helped me get my head around the concept of doing this. Also, he included helpful debugging enviornment variables right there in his blog. So I didn't have to go and look them up in the terraform docs (which I feel like I live in all of the HashiCorp product's docs... 😅️).

Hackery...

Docker first...

Extra info

So, in the normal context of a long running container I would definitely recommend against doing what is called a bind mount -v (especially of the docker socket) without taking the proper precautions...checkout why here: /resources/#dockerexploits.

Also, apparently you can't specify a bind mount on the root of the docker container (i.e. -v "$(pwd)":/)...this make sense after I thought about it, because you replace the dircetory of whatever you bind to, but just thought I would throw that info out there 🙃️.

Environment variables

This kind of will include some terraform knowledge, but you will need to use the -e flag to pass in environment variables to terraform through docker's cli flags. (i.e. -e TF_VAR_auth_token)

Terraform

Dumb stuff...

So, to begin this section...there are some dumb things about terraform's application of it's different actions.

  1. You can't pass in a .tf file to specify you only want a specific file to get applied, I am sure there is a legit reason for that but I think that is silly...
  2. When you do the init command and pass in the folder as to where it should init off of (i.e. the location of your terraform file(s)), it won't use that as the folder to place your .terraform folder which holds all the plugin information (and more, but that is the only thing that affected me in this situation)

Together now...

So, as you can probably see from the video above I did eventually get everything to run properly and output things as I wanted them to. So, the trick to get them to work together was to specify a bind mount for both the location of your terraform files (i.e. -v "$(pwd)":/terraform) and the .terraform folder that is located in /bin (i.e. -v "$(pwd)/.terrform":/.terraform/. This allows you to continually run the official hashicorp docker container without having to already pre-stage the plugins from the host operating system.

Background

So, the reason why I was doing this was because I am migrating my packer automation project to using terraform, and I didn't want to use my script that I created as a hack around downloading and installing terraform to the OS. I wanted to use a more clean was of handling terraform and thought why not docker. So, now I can install docker though snap and then run terraform and packer with docker.

Also, this allows me to run containers asyncryonsly to perform multiple terraform tasks at the same time, which only will gain me a few second but it is the thought that counts 😁️

Example cmds

Project specific

Here is a logical chain of commands that you could probably run to do everything I discussed about in this blog for my project (I will put general command below this section):

# first do an init to pull down plugins
docker run -it --rm -v "$(pwd)/.terrform":/.terraform/ -v "$(pwd)":/terraform hashicorp/terraform:light init /terraform/

# then do a plan out to a file
docker run -it --rm -e TF_VAR_project_id -e TF_VAR_auth_token -v "$(pwd)/.terrform":/.terraform/ -v "$(pwd)":/terraform hashicorp/terraform:light plan -out /terraform/main.plan /terraform/

# apply the plan
docker run -it --rm -e TF_VAR_project_id -e TF_VAR_auth_token -v "$(pwd)/.terrform":/.terraform/ -v "$(pwd)":/terraform hashicorp/terraform:light apply -state /terraform/main.tfstate /terraform/main.plan

# lastly destroy everything
docker run -it --rm -e TF_VAR_project_id -e TF_VAR_auth_token -v "$(pwd)/.terrform":/.terraform/ -v "$(pwd)":/terraform hashicorp/terraform:light destroy -auto-approve -state /terraform/main.tfstate /terraform/

General commands

# first do an init to pull down plugins
docker run -it --rm -v "$(pwd)/.terrform":/.terraform/ -v "$(pwd)":/terraform hashicorp/terraform:light init /terraform/

# then do a plan out to a file
docker run -it --rm -v "$(pwd)/.terrform":/.terraform/ -v "$(pwd)":/terraform hashicorp/terraform:light plan -out /terraform/main.plan /terraform/

# apply the plan
docker run -it --rm -v "$(pwd)/.terrform":/.terraform/ -v "$(pwd)":/terraform hashicorp/terraform:light apply -state /terraform/main.tfstate /terraform/main.plan

# lastly destroy everything
docker run -it --rm -v "$(pwd)/.terrform":/.terraform/ -v "$(pwd)":/terraform hashicorp/terraform:light destroy -auto-approve -state /terraform/main.tfstate /terraform/

Video (asciinema)