Docker Compose+Terraform在LocalStack创建S3桶遇连接拒绝
浏览器访问http://localhost:4566/health能正常查看LocalStack服务状态,但执行Terraform创建S3桶时提示连接拒绝,错误信息如下:
Error: creating Amazon S3 (Simple Storage) Bucket (bucket-c): RequestError: send request failed
terraform | │ caused by: Put "http://localhost:4566/bucket-c": dial tcp 127.0.0.1:4566: connect: connection refused
terraform | │
terraform | │ with aws_s3_bucket.bucket["bucket-c"],
terraform | │ on main.tf line 1, in resource "aws_s3_bucket" "bucket":
| │ 1: resource "aws_s3_bucket" "bucket" {
我的Docker Compose配置
version: '3' services: localstack: image: localstack/localstack container_name: localstack network_mode: bridge ports: - "127.0.0.1:4566:4566" # LocalStack Gateway - "127.0.0.1:4510-4559:4510-4559" # external services port range - "127.0.0.1:443:443" # LocalStack HTTPS Gateway networks: - test-net hostname: localstack environment: - AWS_DEFAULT_REGION=eu-west-2 - AWS_ACCESS_KEY_ID=test - AWS_SECRET_ACCESS_KEY=test - DEBUG=${DEBUG:-1} - DOCKER_HOST=unix:///var/run/docker.sock - LS_LOG=WARN - HOSTNAME_EXTERNAL=localstack - SERVICES=s3,kafka - HOST_TMP_FOLDER=${TMPDIR} - DATA_DIR=/tmp/localstack/data - PERSISTENCE=${PERSISTENCE-} volumes: - "${TMPDIR:-/tmp}/localstack:/var/lib/localstack" - "/Users/devops/.rd/docker.sock:/var/run/docker.sock" - "localstack_data:/tmp/localstack" terraform: image: hashicorp/terraform:latest # Use an official Terraform image working_dir: /app volumes: - ./terraform:/app depends_on: - localstack environment: AWS_ACCESS_KEY_ID: test AWS_SECRET_ACCESS_KEY: test AWS_DEFAULT_REGION: eu-west-2 entrypoint: ["sh", "/app/run-terraform.sh"] volumes: kafka-data: localstack_data:
Terraform配置
provider "aws" { region = "eu-west-2" access_key = "test" secret_key = "test" skip_credentials_validation = true skip_metadata_api_check = true skip_requesting_account_id = true s3_use_path_style = true endpoints { s3 = "http://localhost:4566" } } resource "aws_s3_bucket" "bucket" { for_each = toset(["bucket-a", "bucket-b", "bucket-c"]) bucket = each.key } resource "aws_s3_bucket_acl" "s3_bucket" { for_each = aws_s3_bucket.bucket bucket = aws_s3_bucket.bucket[each.key].id acl = "public-read-write" } resource "aws_s3_bucket_policy" "s3_bucket_policy" { for_each = aws_s3_bucket.bucket bucket = each.value.id policy = jsonencode({ Version = "2012-10-17", Statement = [ { Sid = "PublicReadGetObject", Effect = "Allow", Principal = "*", Action = "s3:GetObject", Resource = [ "${each.value.arn}/*", ], }, ], }) }
1. 修正容器间网络访问地址
Terraform容器内的localhost指向容器自身,而非LocalStack容器。由于两个容器在同一自定义网络test-net中,直接使用LocalStack的服务名localstack作为域名访问:
修改Terraform的AWS provider配置中的endpoint:
endpoints { s3 = "http://localstack:4566" }
2. 修复Docker Compose网络配置冲突
LocalStack配置中同时设置了network_mode: bridge和networks: - test-net,这会导致网络配置异常。删除network_mode: bridge,让容器使用自定义的test-net网络:
services: localstack: image: localstack/localstack container_name: localstack # 移除这一行:network_mode: bridge ports: - "127.0.0.1:4566:4566" # LocalStack Gateway - "127.0.0.1:4510-4559:4510-4559" # external services port range - "127.0.0.1:443:443" # LocalStack HTTPS Gateway networks: - test-net # 其他配置保持不变
3. 确保LocalStack服务就绪后再执行Terraform
depends_on仅保证容器启动顺序,不保证服务完全就绪。修改run-terraform.sh,添加等待LocalStack S3服务启动的逻辑:
#!/bin/sh # 等待LocalStack S3服务就绪 until curl -s http://localstack:4566/health | grep -q "\"s3\": \"running\""; do echo "等待LocalStack S3服务启动..." sleep 2 done # 执行Terraform命令 terraform init terraform apply -auto-approve
内容的提问来源于stack exchange,提问作者user5820327

