LocalStackとTerraformでAWSをローカルテストする方法|アカウント不要の開発・デバッグ環境設計

運営:リナックスマスター.JP(代表 宮崎智広)
HOME > Linux技術 リナックスマスター.JP(Linuxマスター.JP) > Terraform > LocalStackとTerraformでAWSをローカルテストする方法|アカウント不要の開発・デバッグ環境設計
「Terraformのコードを書くたびにテスト用リソースが増えて、請求が気になってきた。」
「チームメンバーがAWSアカウントを持っていないため、ローカルで確認できない。」

Terraform開発では、コードを書く段階でも`terraform apply`を繰り返して結果を確認することが多くなります。本番のAWSに毎回アクセスすると、テストリソースの削除忘れが積み重なったり、ネットワークが使えない環境では作業が止まったりします。

この記事では、RHEL 9系(Rocky Linux 9 / AlmaLinux 9)を想定環境として、LocalStackを使ったTerraformのローカルテスト環境を構築する方法を解説します。S3バケット作成の確認から、本番AWSとの切り替え設計まで、実際のAWSアカウントなしでTerraformコードを開発・確認するパターンを紹介します。

この記事のポイント

・LocalStackはDockerで起動できるAWSモックサーバーで、S3・EC2・IAM・SQSなどに対応
・TerraformのproviderにLocalStack用のエンドポイントを設定することで接続できる
・ダミー認証情報(access_key / secret_key = "test")を使えば本物のAWSクレデンシャルは不要
・variable + tfvarsで本番AWSとLocalStackを環境ごとに切り替える設計が実用的


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Terraform開発で「毎回本番AWSを使う」と起きやすい問題

Terraformのコードを書いている段階では、HCLの書き方を試したり、モジュール設計を検証したりするために`apply`を何度も繰り返すことがあります。

本番のAWSに対して毎回`apply`すると、いくつかの問題が起きやすいです。

・テスト用リソースを作るたびに少額でも料金が発生する
・`terraform destroy`し忘れたリソースが積み重なる
・開発環境のAWSクレデンシャルをメンバー全員に払い出す必要が生じる
・ネットワーク接続のない環境や、オフサイトでの作業では手が止まる

特にTerraformを学び始めるフェーズや、HCL構文の確認・モジュール設計の試行を繰り返す場面では、LocalStackをモック環境として使うと開発が速くなります。

LocalStackとは何か

LocalStackは、Dockerコンテナとしてローカルで起動できるAWSモックサーバーです。S3・EC2・IAM・SQS・SNS・DynamoDB・Lambdaなど、主要なAWSサービスのAPIをエミュレートします。

TerraformはAWSプロバイダー経由でAPIを呼び出しています。そのため、providerの向き先をLocalStackのURLに変えるだけで、コード自体を書き直さずにローカルで動かせます。

無償版(Community)でもS3・SQS・SNS・DynamoDB・IAM・Lambdaなどが使えます。有償版(Pro)になるとEKS・RDS・Cognitoなどカバー範囲が広がりますが、HCLの文法確認やモジュール設計の検証には無償版で十分な場面が多いです。

Terraformを使ったインフラ設計をより体系的に学びたい場合は、terraform.linuxmaster.jpもあわせて参照してください。

LocalStackのセットアップ

1. Dockerの確認

LocalStackはDockerコンテナで動くため、事前にDockerが起動している状態にしておきます。

# Dockerの動作確認 docker --version docker info | head -5

RHEL 9系ではDockerの代わりにPodmanを採用している環境も多いですが、LocalStackはDocker互換の`docker compose`コマンドで起動する方法が確認例が多いため、ここではDockerを前提に進めます。

2. docker-compose.ymlの作成とコンテナ起動

作業用ディレクトリを作り、`docker-compose.yml`を用意します。

# 作業ディレクトリを作成 mkdir ~/localstack-tf && cd ~/localstack-tf # docker-compose.yml を作成 cat > docker-compose.yml << 'EOF' version: "3.8" services: localstack: container_name: localstack-main image: localstack/localstack:latest ports: - "127.0.0.1:4566:4566" environment: - SERVICES=s3,ec2,iam,sts - DEFAULT_REGION=ap-northeast-1 volumes: - "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack" - "/var/run/docker.sock:/var/run/docker.sock" EOF # コンテナを起動 docker compose up -d

`SERVICES`に必要なサービスを列挙しておくと、起動にかかる時間を短縮できます。全サービスを有効にする場合は`SERVICES`を省略します。

3. 起動確認

起動後にヘルスチェックのエンドポイントを確認します。

curl -s http://localhost:4566/_localstack/health | python3 -m json.tool

出力例(環境により異なります):

{ "services": { "ec2": "available", "iam": "available", "s3": "running", "sts": "available" }, "version": "3.8.0" }

対象サービスが`"running"`または`"available"`になっていれば準備完了です。

TerraformからLocalStackに接続するprovider設定

1. provider設定とエンドポイントの向け先

通常のAWSプロバイダー設定に、LocalStackのエンドポイント(`http://localhost:4566`)を追加します。

# provider.tf terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } } provider "aws" { region = "ap-northeast-1" access_key = "test" secret_key = "test" skip_credentials_validation = true skip_requesting_account_id = true skip_metadata_api_check = true endpoints { s3 = "http://localhost:4566" ec2 = "http://localhost:4566" iam = "http://localhost:4566" sts = "http://localhost:4566" } }

2. ダミー認証情報とskipフラグの意味

LocalStackはAPIの認証チェックをしないため、`access_key`と`secret_key`は任意の文字列で構いません。`"test"`を使うのが慣例です。

`skip_credentials_validation = true`と`skip_requesting_account_id = true`を設定しないと、プロバイダーが実際のAWS STSエンドポイントに接続を試みてエラーになります。LocalStack用のprovider設定では、この2つのフラグを忘れずに設定してください。

LocalStack上でS3バケットを作成して確認する

provider設定ができたら、S3バケットを作るシンプルなコードで動作確認をします。

# main.tf resource "aws_s3_bucket" "example" { bucket = "my-test-bucket-localstack" }

`terraform init`と`terraform apply`を実行します。

terraform init terraform apply -auto-approve

出力例(環境により異なります):

aws_s3_bucket.example: Creating... aws_s3_bucket.example: Creation complete after 0s [id=my-test-bucket-localstack] Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

AWS CLIでLocalStackのS3に実際にバケットが作られているかを確認します。

aws --endpoint-url=http://localhost:4566 s3 ls

出力例(環境により異なります):

2026-01-01 00:00:00 my-test-bucket-localstack

`terraform apply`が正常に終わり、バケット一覧に表示されれば成功です。

本番AWSとLocalStackを切り替える設計

LocalStackで確認したコードを本番AWSで動かすには、切り替えの仕組みを最初から設計しておくと手間が省けます。

1. variableでエンドポイントを受け取る

# variables.tf variable "localstack_endpoint" { description = "LocalStackのエンドポイント。空文字列にすると本番AWSを使用する" type = string default = "http://localhost:4566" }

# provider.tf(切り替え対応版) provider "aws" { region = "ap-northeast-1" # LocalStack用ダミー認証(本番ではIAMロールや環境変数を使用) access_key = var.localstack_endpoint != "" ? "test" : null secret_key = var.localstack_endpoint != "" ? "test" : null skip_credentials_validation = var.localstack_endpoint != "" ? true : false skip_requesting_account_id = var.localstack_endpoint != "" ? true : false skip_metadata_api_check = var.localstack_endpoint != "" ? true : false dynamic "endpoints" { for_each = var.localstack_endpoint != "" ? [1] : [] content { s3 = var.localstack_endpoint ec2 = var.localstack_endpoint iam = var.localstack_endpoint sts = var.localstack_endpoint } } }

2. tfvarsで環境を分離する

# local.tfvars(LocalStack用) localstack_endpoint = "http://localhost:4566" # production.tfvars(本番AWS用) localstack_endpoint = ""

# LocalStackで確認 terraform apply -var-file=local.tfvars # 本番AWSに適用 terraform apply -var-file=production.tfvars

この設計にしておくと、HCLのリソース定義を書き換えずに環境を切り替えられます。切り替えの実績を`-var-file`の引数で記録できるため、どの環境に`apply`したかの確認もしやすくなります。

よくあるエラーと対処法

LocalStack + Terraformを組み合わせる際に出やすいエラーを整理します。

「dial tcp: connection refused」が出る

LocalStackコンテナが起動していないか、ポートが異なる場合に出ます。

# コンテナの状態確認 docker compose ps docker compose logs localstack | tail -20 # ポートが使用中かを確認 ss -tlnp | grep 4566

`docker compose ps`でコンテナのSTATUSが`running`になっているかを確認してください。

「InvalidClientTokenId」や「AuthFailure」が出る

`skip_credentials_validation = true`と`skip_metadata_api_check = true`が設定されていないと発生します。provider設定を再確認してください。

「NotImplemented: Operation not supported」が出る

LocalStack Community版では対応していないAPIが呼ばれた場合に出ます。リソースの種類がCommunity版でサポートされているかをLocalStackの公式ドキュメントで確認してください。Community版でサポートされていないリソース(EKS・RDSなど)を検証する場合はPro版が必要です。

「Error: failed to refresh cached provider plugin」が出る

`.terraform`ディレクトリのキャッシュが古い場合に起きます。`terraform init -upgrade`を実行するか、`.terraform`ディレクトリを削除してから`terraform init`をやり直してください。

本記事のまとめ

やりたいこと 対応方法
LocalStackをDockerで起動する docker compose up -d(docker-compose.ymlにSERVICESを列挙)
起動確認をする curl http://localhost:4566/_localstack/healthでrunning/availableを確認
TerraformをLocalStackに向ける providerのendpointsブロックにhttp://localhost:4566を設定
ダミー認証情報を使う access_key/secret_keyに"test"、skip系フラグをtrueに設定
本番AWSとLocalStackを切り替える variableでエンドポイントを受け取り、-var-file=xxx.tfvarsで環境を分離
対応サービスを確認する LocalStack公式ドキュメントのカバレッジページで確認(Community版は無償)
LocalStackを使うと、Terraformのコードを本番AWSに流す前にローカルで動作を確認する習慣が作りやすくなります。変数設計やモジュール設計の確認に使い、仕上がったコードを実際のAWSに向ければ、開発と検証のサイクルを速く回せます。設計パターンをさらに深めたい場合はterraform.linuxmaster.jpもあわせて参照してください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、

TerraformなどのIaCツールを含む、サーバー自動化・セキュリティ設定・運用設計まで、実務で通用するスキルを少人数のハンズオンで体系的に学べるセミナーを開催しています。

>> 詳細・申込はこちら(terraform.linuxmaster.jp)

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録

運営

リナックスマスター.JP(代表 宮崎智広)

株式会社イーネットマーキュリーが運営するLinux教育サイトです。代表の宮崎智広は現役のLinuxサーバー管理者として20年以上の実務経験を持ち、累計3,100名以上のエンジニアを指導してきました。実践型のLinuxセミナーや無料マニュアルの配布を通じてLinux人材の育成に取り組んでいます。