🌏

Terraformをインストールする前に読んでほしい話

2022/09/03に公開

はじめに

Terraform をチーム開発で使用する場合は、メンバーごとに使用する Terraform のバージョンの違いによって環境やコードに差分が出ないようにするため、使用する Terraform のバージョンをメンバー間で統一する必要があります。
また、Terraform を使用する複数のプロジェクトを 1 人で掛け持ちする場合には、プロジェクトごとに使用する Terraform のバージョンが異なるため、プロジェクトごとに使用する Terraform のバージョンを適宜切り替える必要があります。
上記を実現する方法はいくつかありますが、当記事では Docker Compose を使用する方法をご紹介します。

環境

当記事の作成時点で私が使用している環境を記載します。
OS に依存する内容はないはずですが、Docker と Docker Compose は必須です。

・OS: macOS Monterey 12.4
・Docker Desktop: 4.11.0
(Docker Engine: 20.10.17, Docker Compose: 1.29.2)

準備

まだの方は以下を参考に Docker Desktop をインストールしてください。
https://matsuand.github.io/docs.docker.jp.onthefly/desktop/#download-and-install

その後、以下の docker-compose.yml を Terraform コマンドを実行したいディレクトリに配置してください。

docker-compose.yml
version: "3.7"

services:
  terraform:
    image: hashicorp/terraform:1.2.4
    volumes:
      - .:/infra
    working_dir: /infra
    environment:
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
      - TF_CLI_ARGS_plan="--parallelism=20"
      - TF_CLI_ARGS_apply="--parallelism=20"
      - TF_CLI_ARGS_destroy="--parallelism=20"

docker-compose.yml  解説

一応説明しておくと Docker Compose は複数のコンテナをまとめて起動・削除・管理したい場合に使用する機能です。
今回は使用するコンテナは1つですが、コンテナ使用時のコマンドで各種パラメータ設定を省略するために使用しています。

コンテナは Hashicorp が提供する公式イメージ(hashicorp/terraform)を使用しています。
このイメージには docker-compose.yml ファイル内の image で指定しているタグに対応するバージョンの Terraform が含まれています。
このイメージを使用して毎回コンテナを立ち上げてこのコンテナ内で Terraform コマンドを実行することでイメージタグで指定した Terraform のバージョンを使用することができます。
使用したい Terraform のバージョンに合わせて image: hashicorp/terraform:以降の数字を任意のバージョンに変更してください。

volumes で指定している通り、カレントディレクトリの内容をコンテナ内のディレクトリ(/infra)にマウントしています。

なお、environment に指定している AWS_*** の環境変数は Terraform を使用して AWS リソースを作成する際の Credential を環境変数経由で指定している場合に必要です。
Credential を Terraform の provider に直接記載したり、tfvars ファイル に記載して参照させている場合は不要です。
TF_CLI_***の環境変数は Terraform の処理を高速にするために指定しているものなので設定は任意です。

Terraform 実行

実行する tf ファイルも作成し、準備ができたら以下のコマンドを実行します。

$ docker compose run --rm terraform  ***

***の部分は任意の Terraform コマンドを入れます。
--rm オプションをつけているのでコマンド実行時にコンテナが実行され、実行後には自動で削除されます。

コマンド例

$ docker compose run --rm terraform validate
$ docker compose run --rm terraform plan
$ docker compose run --rm terraform apply
$ docker compose run --rm terraform destroy

tfenv との比較

当記事で紹介している方法以外に、複数の Terraform のバージョンを切り替えて使用するための機能としてよく例に上がるのはtfenvという機能です。
もちろん tfenv を使用しても目的は達成できますが、Docker Compose を使う方法と比較すると以下の点がイマイチだと思います。

  • tfenv をインストールする必要がある
    ※Docker Desktop はたいていの開発者は元々使っているだろうという前提(私の思い込み)があります。
  • 使用前に必要な Terraform のバージョンをインストールする必要がある
  • 適切な Terraform バージョンへの切り替え忘れのリスクがある

Docker Compose を使う場合であれば各プロジェクトの Git リポジトリに docker-compose.yml を置いておくだけで簡単にメンバー間で共有ができますし、プロジェクトごとにバージョンを切り替え忘れるリスクもありません。

欠点を強いてあげるのであれば以下の点くらいかと思います。

  • 毎回コンテナを立ち上げるのでちょっと遅い(実行が始まるまでに数秒かかる)

ただそこまで頻繁に Terraform コマンドを実行するわけでなければ気にならないですし、
高速化したい場合は docker compose up でコンテナを立ち上げっぱなしにしておき、
毎回 docker exec で Terraform コマンドを実行するという対策もあります。

加えて、この方法が最も適していて効果を発揮するのは、複数の AWS 環境(例:開発/ステージング/本番等)があり、それぞれの AWS 環境で Credential を使い分ける必要があるプロジェクトです。
当記事には詳しくは書きませんが、詳細は以下の記事をご参照ください。
*記事:AWS の IaC で Terraform を使う際の環境設定ベストプラクティス(AWS マルチアカウント対応)

まとめ

今回は Docker Compose を使用して、Terraform をローカルにインストールせずに複数のバージョンを使い分ける方法をご紹介しました。
個人開発でしか使わない場合は気にせずに直接ローカルに Terraform をインストールしてもいいですが、簡単な方法でローカル環境を汚さずに済むのでぜひ試してみてください。

付録:複数環境あるディレクトリ構成で使用する場合

以前下記の記事で紹介したような複数の環境(例:開発/ステージング/本番等)を前提としたディレクトリ構成を使用する場合は、
各環境のディレクトリの配下に docker-compose.yml を配置します。
*記事:Terraform の最適(≠ 最強)なディレクトリ構成を考えてみた

・ディレクトリ構造

.
├── env1
│   ├── backend.tf
│   ├── outputs.tf
│   ├── terraform.tfvars
│   ├── variables.tf
│   └── docker-compose.yml
│   ・・・
├── env2
│   ├── backend.tf
│   ├── outputs.tf
│   ├── terraform.tfvars
│   ├── variables.tf
│   └── docker-compose.yml
│   ・・・
├── modules
│   └── example1
│       ├── main.tf
│       ├── outputs.tf
│       └── variables.tf
└── shared
    └── provider.tf
    ・・・

その際、modules や shared フォルダを参照するために docker-compose.yml の内容を以下のように変更する必要があります。

・env1 ディレクトリに配置する場合

env1/docker-compose.yml
version: "3.7"

services:
  terraform:
    image: hashicorp/terraform:1.2.4
    volumes:
      - ..:/infra
    working_dir: /infra/env1
    environment:
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}
      - TF_CLI_ARGS_plan="--parallelism=20"
      - TF_CLI_ARGS_apply="--parallelism=20"
      - TF_CLI_ARGS_destroy="--parallelism=20"

これで各環境のディレクトリで docker compose コマンドを実行すると、modules や shared フォルダを参照する tf ファイルも実行できるようになります。

Discussion