Manage Cross team terraform and azure-cli versions with docker

One of the issues with having multiple teams, and pushing for autonomy to choose everything from infrastructure to languages, is making sure that you have the right versions of everything installed.

As developers, we want to be on the bleeding edge, playing with new things, new versions, etc. However, that can have an impact beyond our machine, and can introduce weird issues with cross-team work and even within the team.

I’ve been working on an approach to isolate that, and streamline the workflow with getting new team members up to speed quickly. Essentially, this boils down to using docker for just about everything. In this post, I’ll walk through doing this for Terraform and the Azure-CLI.

Caveat: I will admit that there are generally images in wild, already built with this combination. However, this approach allows for you to customise the image at a repository level. It allows the primary team to provide the other team’s developers an isolated environment for them to enact change in their team in a frictionless way.

Dockerfile

FROM mcr.microsoft.com/azure-cli

ENV TERRAFORM_VERSION 0.12.28

RUN apk add --update wget ca-certificates unzip git bash && \
    wget -q -O /terraform.zip "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" && \
    unzip /terraform.zip -d /bin && \
    apk del --purge wget ca-certificates unzip && \
    rm -rf /var/cache/apk/* /terraform.zip

VOLUME ["/data"]
WORKDIR /data

RUN printf "\\nalias tf='terraform'" >> /root/.bashrc

ENTRYPOINT ["/bin/bash"]

Lets have a look at what it’s doing.

FROM mcr.microsoft.com/azure-cli

This means we’re going to pull the latest version of the Azure CLI (or use the version we’ve already pulled). If we want to be a little more specific, you could add a “:” tag to the end.

ENV TERRAFORM_VERSION 0.12.28

RUN apk add --update wget ca-certificates unzip git bash && \
    wget -q -O /terraform.zip "https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip" && \
    unzip /terraform.zip -d /bin && \
    apk del --purge wget ca-certificates unzip && \
    rm -rf /var/cache/apk/* /terraform.zip

This will install the specific version of terraform, then clean itself up afterwards.

VOLUME ["/data"]
WORKDIR /data

RUN printf "\\nalias tf='terraform'" >> /root/.bashrc

ENTRYPOINT ["/bin/bash"]

Finally, we add a volume tag, which is where our terraform code will be mounted and add an alias as typing “terraform” is way too many keystrokes when you can just right “tf”.

We can then build the image

docker build . local/tf:12-28

The additional “:12-28” means that we’re keeping it versioned.

Running

Then run the image

docker run -it --rm -v ${PWD}:/data -v azure-cli:/root/.azure --name tf-inf local/tf:12-28

The secret sauce here is the name and the volumes. The adding of ${PWD} means you’re mounting your current directory as the source for the container.

The azure-cli volume is what allows for persisting your validation, so it’s not lost when you/if you kill the container, and also allows it to be shared with other containers.

Note: the --rm flag will remove the container afterwards. This is very useful due to a bug with WSL2/Docker that deletes the contents of the mount after a restart occasionally.

Conclusion

Managing cross-team work is hard, and when it comes to being an infrastructure consultant, or someone who is working in anyway across multiple autonomous teams, docker is definitely your friend!

27