如何使用Terraform配置两个不同端口的Nginx Docker实例?
Got it, let's tackle this problem step by step. To run two web instances on the same server with different external ports (and integrate Nginx as part of the setup using Terraform), here's a clean, scalable approach:
We'll use Terraform's count meta-argument to spin up multiple web instances, a dedicated Docker network for inter-container communication, and Nginx as a reverse proxy to route traffic from different external ports to each web instance.
Step 1: Define a Docker Network
First, create a private Docker network so all containers can communicate with each other using their names (no messy IP dependencies):
resource "docker_network" "web_network" { name = "web-instances-net" }
Step 2: Spin Up Two Web Instances
Use count = 2 to create identical (or configurable) web instances. We'll use Nginx as the web app here, but you can swap in any image you need:
# Pull the base web app image resource "docker_image" "web_app" { name = "nginx:1.11-alpine" } # Create 2 web instances resource "docker_container" "web_instance" { count = 2 name = "web-instance-${count.index + 1}" # Names: web-instance-1, web-instance-2 image = docker_image.web_app.latest # Attach to our private network networks_advanced { name = docker_network.web_network.name } # Internal port stays 80 (no need to expose directly to the host) ports { internal = 80 } }
Step 3: Configure Nginx as Reverse Proxy
We'll generate an Nginx config dynamically using Terraform's template functionality, mapping external ports 8080 and 8081 to our two web instances.
Option A: Use an inline template (no external file)
# Pull the Nginx proxy image resource "docker_image" "nginx_proxy" { name = "nginx:1.11-alpine" } # Dynamically render Nginx config data "template_file" "nginx_proxy_config" { template = <<EOF events {} http { # Route external port 8080 to web-instance-1 server { listen 8080; server_name localhost; location / { proxy_pass http://${web_instance_1}:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } # Route external port 8081 to web-instance-2 server { listen 8081; server_name localhost; location / { proxy_pass http://${web_instance_2}:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } } EOF vars = { web_instance_1 = docker_container.web_instance[0].name web_instance_2 = docker_container.web_instance[1].name } } # Save the rendered config to a local file resource "local_file" "nginx_proxy_config" { content = data.template_file.nginx_proxy_config.rendered filename = "${path.module}/nginx-proxy.conf" } # Launch the Nginx proxy container resource "docker_container" "nginx_proxy" { name = "nginx-reverse-proxy" image = docker_image.nginx_proxy.latest networks_advanced { name = docker_network.web_network.name } # Expose the external ports to the host ports { internal = 8080 external = 8080 } ports { internal = 8081 external = 8081 } # Mount our custom config into the Nginx container volumes { container_path = "/etc/nginx/nginx.conf" host_path = local_file.nginx_proxy_config.filename read_only = true } # Ensure the config file and web instances exist before starting the proxy depends_on = [local_file.nginx_proxy_config, docker_container.web_instance] }
Option B: Use an external template file
If you prefer keeping the Nginx config separate, create a file named nginx-proxy.conf.tpl in your Terraform directory:
events {} http { server { listen 8080; server_name localhost; location / { proxy_pass http://${web_instance_1}:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } server { listen 8081; server_name localhost; location / { proxy_pass http://${web_instance_2}:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } }
Then replace the data "template_file" block with:
data "template_file" "nginx_proxy_config" { template = file("${path.module}/nginx-proxy.conf.tpl") vars = { web_instance_1 = docker_container.web_instance[0].name web_instance_2 = docker_container.web_instance[1].name } }
How It Works
- Private Network: All containers are on the same network, so Nginx can reach the web instances using their container names (e.g.,
web-instance-1). - Dynamic Config: Terraform injects the correct container names into the Nginx config, so you don't have to hardcode IPs.
- Port Routing: External traffic to
localhost:8080goes to the first web instance, andlocalhost:8081goes to the second.
Key Notes
- Scalability: If you need more instances later, just change
count = 2tocount = Nand update the Nginx config template to add more server blocks (or use a loop in the template withforif you're using Terraform 0.12+). - Custom Web Apps: Swap the
docker_image.web_appname with your actual web app image (e.g.,my-node-app:latest) and adjust the internal port if your app uses something other than 80. - Dependency Order: The
depends_onensures the proxy doesn't start before the web instances and config file are ready, avoiding startup errors.
内容的提问来源于stack exchange,提问作者user9744081

