Terraform で User Data を使い、EC2 起動直後に自動設定する
目次
1. はじめに
検証のためにLinux環境が必要な場合、EC2は有力な選択肢です。
検証のたびにEC2をつくって、「Docker を入れて Node.js を入れて…」と毎回同じ作業をするのは大変です。TerraformのUser Data機能を使えば、インスタンス起動と同時にシェルスクリプトを走らせて環境構築を自動化できます。
この記事では、基本の書き方から実践的なサンプル、他の手段(カスタム AMI・Ansible)との使い分けまでをまとめました。
2. User Data とは
以下の特徴があります。
- 初回ブート時に 1 度だけ実行
- root 権限で実行:システム設定まで変更可
- バックグラウンド実行:ログイン前に処理を開始
- ログが残る:
/var/log/cloud-init-output.logなどで確認
Amazon Linux は cloud-init が裏側でスクリプトを読み取り、処理します。
3. User Data の基本形
resource "aws_instance" "example" {
ami = "ami-xxxxxxxx"
instance_type = "t3.micro"
user_data = <<-EOF
#!/bin/bash
yum -y update
yum -y install httpd
systemctl enable --now httpd
EOF
}
4. 実践例:開発サーバーを丸ごと自動構築
Amazon Linux 2023 で Docker / Node.js / タイムゾーン を一括セットアップします。
resource "aws_instance" "dev_server" {
ami = data.aws_ssm_parameter.amzn2_latest_ami.value
instance_type = "t3.nano"
key_name = "my-keypair"
user_data = <<-EOF
#!/bin/bash
set -euxo pipefail # エラー即停止 & コマンド表示
exec > >(tee /var/log/user-data.log) 2>&1
echo "[UserData] Start: $(date '+%F %T')"
# -------- 基本設定 --------
dnf -y update # Amazon Linux 2023 は dnf
timedatectl set-timezone Asia/Tokyo # JST へ変更
# -------- Docker --------
dnf -y install docker
systemctl enable --now docker
usermod -aG docker ec2-user # 非 root でも docker 実行
# -------- Node.js --------
curl -fsSL https://rpm.nodesource.com/setup_22.x | bash -
dnf -y install nodejs
# -------- Docker Compose --------
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" \
-o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
# -------- 確認 --------
docker --version
node --version
npm --version
timedatectl
echo "[UserData] Done : $(date '+%F %T')"
EOF
}
ポイント
| 行 | 役割 |
|---|---|
set -euxo pipefail | エラーで即終了し、実行コマンドも出力 |
exec > >(tee ...) 2>&1 | 標準出力・エラーを /var/log/user-data.log に保存 |
dnf | Amazon Linux 2023 では yum ではなく dnf |
5. User Data 以外の選択肢
UserData以外に別途AMIを作ったり、Ansibleという方法もあります。比較した結果を以下に示します。
| User Data | カスタム AMI | Ansible | |
|---|---|---|---|
| 起動速度 | 遅め(毎回インストール) | 最速 | 中 |
| 柔軟性 | 高 | 低 | 最高 |
| 学習コスト | 低(Shell) | 中 | 高 |
| 管理手間 | 低 | AMI 更新が面倒 | yml & inventory 管理 |
| 主な用途 | 開発 / POC | 本番・大量展開 | 複雑な設定 / 既存環境 |
5.1. カスタム AMI が向くケース
- 本番で大量起動、起動 1 秒でも速くしたい
- パッケージ・パッチレベルを固定し、毎回まったく同じ環境 にしたい
5.2. Ansible が向くケース
- 条件分岐やループ、タグ管理など 複雑な構成管理 が必要
- 既存サーバーをまとめて横並びに設定したい
6. まとめ
Terraform の User Data を活用すると、
- 手作業ゼロ でソフトウェアをインストール
- Terraform コードに設定が載るため 再現性・レビュー性◎
- cloud-init がログを残し トラブル解析も容易
6.1. User Dataの活用に適したケース
✅ 開発環境 の素早い構築
✅ POC・検証 での手軽な自動化
✅ 軽量なミドルウェア のインストール

