DevOps Track Β· Day 5 HCL Iteration Β· 20 min
Dynamic Code & Loops
DevOps Terraform Sprint β Day 5
Leverage count, for_each maps, and dynamic blocks for automated container networks and volume mounts
About Today's 20-Minute Lab
Declaring multiple environments or services individually leads to redundant code blocks. Today on Day 5, you will master HCL iteration constructs: for_each map expressions, count index loops, and dynamic nested blocks to spin up dynamic container clusters and networks cleanly.
π¬
Day 5 Video WalkthroughComing Soon
An interactive 20-minute video walkthrough for Day 5 is currently in production. Follow the step-by-step interactive playbook below!
π¦Sample Codebase & Working Solution (Day 5)Available Now
View on GitHubThe verified Day 5 sample code is live in the public GitHub repository. Clone it to get the complete working solution immediately.
Git Clone β Available Now
git clone https://github.com/letstrnsfrm-ai/devops-terraform-roadmap.git
cd devops-terraform-roadmap/day-5-dynamic-code1
Iterating Over Services with for_each
GOAL
Define a map of microservice specifications and provision containers using
for_each.MAIN.TF FOR_EACH
Create
main.tf using map iteration:HCL β main.tf
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.0.1"
}
}
}
provider "docker" {}
# Map of microservices configuration
locals {
services = {
web = {
image = "nginx:alpine"
port = 8088
}
cache = {
image = "redis:alpine"
port = 6379
}
}
}
# Image resources using for_each
resource "docker_image" "service_images" {
for_each = local.services
name = each.value.image
}
# Container resources using for_each
resource "docker_container" "microservices" {
for_each = local.services
name = "qe_${each.key}_service"
image = docker_image.service_images[each.key].image_id
ports {
internal = 80
external = each.value.port
}
}πProduction Context & Enterprise Real-World Implementation
π‘ Why We Are Doing This: `for_each` creates stable map key addresses (e.g. `docker_container.microservices['web']`). Unlike array `count`, removing an item from a map does not trigger accidental destruction of adjacent resources.
π’ Real-World Production Usecase: Production platforms (like Netflix or Lyft) manage dynamic clusters of microservices via maps. Adding or removing a service from a `locals.services` map dynamically provisions or destroys only that specific service.
βοΈ How Implemented in Production: Production modules use `for_each = var.subnets` to dynamically create multi-AZ subnets, IAM role bindings, and Kubernetes namespaces without hardcoding repetitive resource blocks.
2
Dynamic Nested Blocks for Docker Networks
GOAL
Construct dynamic Docker network connections using nested
dynamic "networks_advanced" blocks.DYNAMIC NETWORKS
Add custom Docker bridge network and dynamic attachment blocks:
HCL β Dynamic Network Block
resource "docker_network" "custom_bridge" {
name = "qe_custom_bridge_network"
}
# Example of dynamic nested block declaration
resource "docker_container" "dynamic_service" {
name = "qe_dynamic_networked_app"
image = "nginx:alpine"
dynamic "networks_advanced" {
for_each = [docker_network.custom_bridge.name]
content {
name = networks_advanced.value
}
}
ports {
internal = 80
external = 8089
}
}πProduction Context & Enterprise Real-World Implementation
π‘ Why We Are Doing This: Dynamic blocks allow nested configuration blocks (like security group rules, ingress routes, or volume mounts) to be constructed dynamically based on complex data structures.
π’ Real-World Production Usecase: Enterprise cloud security teams configure complex VPC Security Groups dynamically using `dynamic 'ingress'` blocks driven by firewall rule lists.
βοΈ How Implemented in Production: Production Terraform code uses `dynamic 'ingress'` and `dynamic 'subnet'` blocks to generate multi-region routing tables and container volume mounts conditionally.
3
Provisioning & Map Output Extraction
GOAL
Apply the dynamic HCL blueprint and extract container IP addresses using `for` expressions in `outputs.tf`.
OUTPUTS.TF
Create `outputs.tf` using `for` comprehension loops:
HCL β outputs.tf
output "service_endpoints" {
value = {
for k, v in docker_container.microservices : k => "http://localhost:${v.ports[0].external}"
}
description = "Map of microservice names to local endpoint URLs"
}APPLY WORKFLOW
Before applying, ensure your Docker daemon is running:Then run Terraform init and apply:
Terminal β Docker Daemon Setup (choose your OS)
# macOS β Docker Desktop (GUI: open app) OR Colima (CLI):
colima start
export DOCKER_HOST="unix://$HOME/.colima/default/docker.sock"
# Windows β ensure Docker Desktop is running with WSL2 backend
# Linux:
sudo systemctl start dockerTerminal β Init & Apply
terraform init
terraform apply -auto-approveπProduction Context & Enterprise Real-World Implementation
π‘ Why We Are Doing This: HCL `for` comprehension expressions transform complex resource state objects into clean key-value dictionary outputs consumed by external systems.
π’ Real-World Production Usecase: Service discovery platforms (like Consul or Kubernetes CoreDNS) consume Terraform output maps to register dynamic container IP addresses automatically.
βοΈ How Implemented in Production: In production pipelines, `for` expressions filter and extract active database connection strings into Kubernetes secrets or HashiCorp Vault entries.
4
Cluster Verification & Teardown
GOAL
Verify all dynamically provisioned endpoints via curl and inspect output map structure.
CLUSTER CHECK
Wait for containers to settle, then test web endpoint and output map:
Terminal β Output Map & Endpoint Check
# Display generated endpoint map
terraform output
# Allow container port binding to settle
sleep 2
# macOS / Linux β Curl Web Service (Port 8088)
curl -I http://localhost:8088
# macOS / Linux β Curl Dynamic Networked App (Port 8089)
curl -I http://localhost:8089
# Windows PowerShell equivalent:
# Invoke-WebRequest -Uri http://localhost:8088
# Invoke-WebRequest -Uri http://localhost:8089
# Clean up all dynamic resources
terraform destroy -auto-approveEXPECTED OUTPUT
Verification Success
service_endpoints = {"cache" = "http://localhost:6379", "web" = "http://localhost:8088"}HTTP/1.1 200 OK returned by dynamically provisioned web container.πProduction Context & Enterprise Real-World Implementation
π‘ Why We Are Doing This: Batch validation verifies that all dynamically iterated resources are healthy and responding over network interfaces before closing deployment gates.
π’ Real-World Production Usecase: Microservice platforms verify that all dynamic replicas across multi-container pods respond with healthy status codes during rolling updates.
βοΈ How Implemented in Production: Automated test runners iterate over the output map, executing concurrent HTTP health probes and latency audits against all generated microservice endpoints.