1. 概要
この記事では、以下の内容を解説します。
localsブロックの基本構文と使いどころvariableとの違いと使い分けの判断基準for式との組み合わせ(リスト変換・map生成)- タグのDRY化など実務でよく使うパターン
- 初心者がつまずくポイント
locals(ローカル値)は、コード内で繰り返し使う式や計算結果に名前をつけるための仕組みです。variableが「外から値を受け取る」のに対し、localsは「コード内で計算した値を再利用する」ために使います。
2. localsブロックとは
locals {
# 名前をつけて再利用したい式を定義
app_name = "${var.project}-${var.environment}"
is_production = var.environment == "prd"
}
# local.<名前> で参照する
resource "aws_instance" "web" {
tags = {
Name = local.app_name # ← local. で参照(locals. ではない)
}
}
💡 ブロック名 vs 参照名: ブロックは
locals(複数形)、参照するときはlocal(単数形)です。locals.app_nameは誤りで、正しくはlocal.app_nameです。
3. variableとの違い
| 比較項目 | variable | locals |
|---|---|---|
| 外部から値を変えられるか | ✅ tfvarsや-varで変更可能 | ❌ コード内で固定 |
| Terraformの外部から渡すか | ✅ ユーザーやCIが渡す | ❌ コード内で計算 |
| 動的な式を定義できるか | ❌ 式は書けない(値のみ) | ✅ 任意の式・計算結果 |
| 主な用途 | 環境・設定値の切り替え | 繰り返しの式に名前をつける |
判断フローチャート
値を定義したい
│
▼
「terraform apply -var で外から変えたい?」
│
Yes ─┤ No
│ │
▼ ▼
variable 「コード内で式や計算をしたい?」
│
Yes ─┤ No
│ │
▼ ▼
locals (定数ならvariableのdefaultで可)
詳細な比較は「locals vs variable — 違いと使い分けの完全ガイド」を参照してください。
4. 基本的な使いどころ
長い式に名前をつける
terraform {
required_version = ">= 1.9"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
variable "project" {
type = string
}
variable "environment" {
type = string
}
locals {
# 繰り返し使うプレフィックスを1か所で定義
name_prefix = "${var.project}-${var.environment}"
# 条件式の結果に名前をつける(可読性向上)
is_production = var.environment == "prd"
# 複雑な計算結果に名前をつける
retention_days = local.is_production ? 90 : 7
}
resource "aws_cloudwatch_log_group" "app" {
name = "/aws/${local.name_prefix}/app" # 毎回書かなくて済む
retention_in_days = local.retention_days
tags = {
Name = "${local.name_prefix}-log-group"
Environment = var.environment
ManagedBy = "terraform"
}
}
共通のタグをまとめる(DRY化)
locals {
# 全リソースに付けるタグを一元管理
common_tags = {
Project = var.project
Environment = var.environment
ManagedBy = "terraform"
Owner = "infra-team"
}
}
resource "aws_vpc" "main" {
cidr_block = "10.0.0.0/16"
# merge()で共通タグ + 個別タグを結合
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-vpc"
})
}
resource "aws_instance" "web" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = "t3.micro"
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-web"
Role = "web-server"
})
}
環境名から派生する値を計算する
locals {
# 環境ごとの設定をmapで定義
env_config = {
dev = { instance_type = "t3.micro", min_capacity = 1, max_capacity = 2 }
stg = { instance_type = "t3.small", min_capacity = 1, max_capacity = 4 }
prd = { instance_type = "t3.medium", min_capacity = 2, max_capacity = 10 }
}
# 現在の環境の設定を取得(lookupより安全)
current_config = local.env_config[var.environment]
}
resource "aws_instance" "app" {
ami = data.aws_ami.amazon_linux_2023.id
instance_type = local.current_config.instance_type # 環境に応じて自動選択
tags = merge(local.common_tags, {
Name = "${local.name_prefix}-app"
})
}
5. for式との組み合わせ
localsとfor式を組み合わせると、データを柔軟に変換できます。
リストを変換してlocalsに格納する
variable "availability_zones" {
type = list(string)
default = ["ap-northeast-1a", "ap-northeast-1c", "ap-northeast-1d"]
}
locals {
# AZリストから末尾1文字(a/c/d)を抽出したリスト
az_suffixes = [for az in var.availability_zones : substr(az, -1, 1)]
# サブネット名のリストを生成
private_subnet_names = [
for az in var.availability_zones : "${local.name_prefix}-private-${az}"
]
}
mapを生成してfor_eachに渡す
variable "subnet_configs" {
type = list(object({
name = string
cidr = string
az = string
}))
default = [
{ name = "public-1a", cidr = "10.0.1.0/24", az = "ap-northeast-1a" },
{ name = "public-1c", cidr = "10.0.2.0/24", az = "ap-northeast-1c" },
{ name = "private-1a", cidr = "10.0.11.0/24", az = "ap-northeast-1a" },
{ name = "private-1c", cidr = "10.0.12.0/24", az = "ap-northeast-1c" },
]
}
locals {
# listをfor_eachに渡せるmap(name → object)に変換
subnets_map = { for s in var.subnet_configs : s.name => s }
}
resource "aws_subnet" "main" {
for_each = local.subnets_map # localsを経由してfor_eachに渡す
vpc_id = aws_vpc.main.id
cidr_block = each.value.cidr
availability_zone = each.value.az
tags = merge(local.common_tags, {
Name = each.key
})
}
6. 初心者がつまずくポイント
localsは再代入できない
localsブロックで一度定義した値は変更できません。
locals {
name = "web"
}
# ❌ エラー: localsは再代入不可
locals {
name = "app" # Duplicate local name
}
複数のlocalsブロックを書くこと自体は可能ですが、同じ名前は使えません。
循環参照は作れない
# ❌ エラー: 循環参照
locals {
a = local.b + 1
b = local.a + 1 # 互いに依存しているため評価できない
}
local は参照するとき単数形
locals {
prefix = "web" # 定義はlocals(複数形)
}
resource "aws_instance" "web" {
# ❌ 間違い
# tags = { Name = locals.prefix }
# ✅ 正しい: 参照はlocal(単数形)
tags = { Name = local.prefix }
}
7. 関連記事
- variable(入力変数)の使い方 — localsと対になる「外部から渡す値」
- locals vs variable — 違いと使い分けの完全ガイド — 判断基準の詳細
- for式の使い方 — localsと組み合わせるfor式
- merge / concat / flatten — タグのmergeパターン
- tfvarsファイル — 変数値の管理と読み込み順序
- 型システム入門 — string/number/bool/list/map/object
8. まとめ
localsはコード内で繰り返し使う式や計算結果に名前をつける仕組み- 参照するときは
local.<名前>(単数形)。ブロック定義はlocals(複数形) variableとの違い: 外から変えられる→variable、コード内で計算→locals- タグの共通化(
merge(local.common_tags, {...}))が最もよく使われるパターン for式と組み合わせてlistをmapに変換し、for_eachに渡すのが実務の定番localsは再代入不可・循環参照不可
動作確認バージョン: Terraform >= 1.9 / AWS Provider ~> 5.0 対象リージョン: ap-northeast-1(東京) 公式ドキュメント: https://developer.hashicorp.com/terraform/language/values/locals