ディレクトリ構成ベストプラクティス — 規模別の3パターン

1. 概要

  • シングルモジュール構成(小規模プロジェクト向け)
  • 環境別ディレクトリ構成(中規模向け)
  • モジュール分割構成(大規模向け)
  • ファイルの命名規則と役割分担
  • .gitignoreで管理すべきファイル

Terraformのディレクトリ構成に「唯一の正解」はありませんが、プロジェクトの規模や運用スタイルに応じたベストプラクティスが存在します。この記事では実務でよく使われる3つのパターンを解説します。


2. 基本ファイルの役割

どの構成でも共通する基本ファイルを理解しておきましょう。

ファイル名役割必須か
main.tfリソース定義のメインファイル
variables.tfvariableブロックの定義推奨
outputs.tfoutputブロックの定義推奨
providers.tfterraformproviderブロック
locals.tflocalsブロック(大きい場合)任意
terraform.tfvars変数のデフォルト値任意
*.auto.tfvars自動読み込まれるtfvars任意

3. パターン1: シングルモジュール構成(小規模)

個人プロジェクトや数十リソース程度の小規模な構成に適しています。

project/
├── main.tf          # リソース定義(EC2, S3, RDSなど)
├── variables.tf     # 変数定義
├── outputs.tf       # アウトプット定義
├── providers.tf     # providerとterraformブロック
├── locals.tf        # ローカル値定義
├── terraform.tfvars # 変数の値(開発環境デフォルト)
└── .gitignore

providers.tf の例:

terraform {
  required_version = ">= 1.9"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }

  backend "s3" {
    bucket         = "myapp-terraform-state"
    key            = "terraform.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "myapp-terraform-locks"
    encrypt        = true
  }
}

provider "aws" {
  region = "ap-northeast-1"
}

variables.tf の例:

variable "environment" {
  description = "環境名(dev/stg/prd)"
  type        = string
  default     = "dev"
}

variable "project_name" {
  description = "プロジェクト名"
  type        = string
}

terraform.tfvars の例:

environment  = "dev"
project_name = "myapp"

4. パターン2: 環境別ディレクトリ構成(中規模)

dev / stg / prd のようにディレクトリを分けるパターンです。環境間の設定が大きく異なる場合に適しています。

project/
├── modules/
│   └── ec2/
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
├── environments/
│   ├── dev/
│   │   ├── main.tf      # dev環境のリソース定義
│   │   ├── providers.tf
│   │   ├── variables.tf
│   │   └── terraform.tfvars
│   ├── stg/
│   │   ├── main.tf
│   │   ├── providers.tf
│   │   ├── variables.tf
│   │   └── terraform.tfvars
│   └── prd/
│       ├── main.tf
│       ├── providers.tf
│       ├── variables.tf
│       └── terraform.tfvars
└── .gitignore

environments/prd/terraform.tfvars の例:

environment   = "prd"
project_name  = "myapp"
instance_type = "t3.medium"

コマンド実行時は環境ディレクトリに移動:

cd environments/dev
terraform init
terraform plan -var-file=terraform.tfvars
terraform apply -var-file=terraform.tfvars

5. パターン3: モジュール分割構成(大規模)

複数チームで管理する大規模なプロジェクトでは、機能ごとにモジュールを分けます。

project/
├── modules/
│   ├── networking/      # VPC, subnet, security group
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   ├── compute/         # EC2, Auto Scaling
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   ├── database/        # RDS, ElastiCache
│   │   ├── main.tf
│   │   ├── variables.tf
│   │   └── outputs.tf
│   └── storage/         # S3, CloudFront
│       ├── main.tf
│       ├── variables.tf
│       └── outputs.tf
├── environments/
│   ├── dev/
│   │   └── main.tf     # moduleを呼び出すだけ
│   └── prd/
│       └── main.tf
└── .gitignore

environments/prd/main.tf の例:

module "networking" {
  source      = "../../modules/networking"
  environment = "prd"
  vpc_cidr    = "10.1.0.0/16"
}

module "compute" {
  source        = "../../modules/compute"
  environment   = "prd"
  subnet_ids    = module.networking.private_subnet_ids
  instance_type = "t3.medium"
}

6. .gitignoreで管理すべきファイル

# Terraformが生成するファイル(コミット不要)
.terraform/
*.tfstate
*.tfstate.backup
.terraform.tfstate.lock.info
crash.log
crash.*.log
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# 秘密情報(絶対にコミットしない)
*.pem
*.key
secrets.tfvars
*secrets*.tfvars

# ロックファイルはコミットする(プロバイダーバージョン固定のため)
# !.terraform.lock.hcl  ← 削除しないこと

⚠️ 重要: .terraform.lock.hclコミットしてください.gitignoreで除外しないこと)。プロバイダーバージョンをチームで統一するために必要です。


7. 命名規則のベストプラクティス

# リソース名: <role>または<function>を使う(env/projectはtagsで管理)
resource "aws_instance" "web" { ... }
resource "aws_instance" "app" { ... }
resource "aws_s3_bucket" "assets" { ... }

# 変数名: スネークケース(小文字とアンダースコア)
variable "instance_type" { ... }
variable "vpc_cidr_block" { ... }

# ローカル値: スネークケース
locals {
  common_tags = { ... }
  az_list     = [ ... ]
}

8. 関連記事


9. まとめ

  • 小規模: フラットなシングルモジュール構成(main.tf, variables.tf, outputs.tf, providers.tf)
  • 中規模: environments/dev / environments/prd のディレクトリ分割
  • 大規模: modules/networking / modules/compute などの機能別モジュール分割
  • どの構成でもproviders.tfterraformブロックとproviderブロックをまとめる
  • .terraform.lock.hclはコミット必須。.terraform/はgitignore必須

動作確認バージョン: Terraform >= 1.9 / AWS Provider ~> 5.0 公式ドキュメント: https://developer.hashicorp.com/terraform/language/modules/develop/structure