Sidecar
The sidecar resource creates a supplementary container that runs alongside a target container. Sidecars are commonly used for logging, monitoring, proxying, or other supporting services that complement the main application container.
Use Cases
Section titled “Use Cases”As a lab author, you can use sidecars to enhance your lab environment without modifying main application containers:
- Add Observability: Attach log collectors (e.g. Fluent Bit), metrics exporters (e.g. Prometheus node-exporter), or APM agents to demonstrate monitoring without changing your app
- Simulate Production Patterns: Include service mesh proxies (e.g. Envoy), load balancers, or security scanners to show real-world architectures
- Provide Development Tools: Add debugging containers, code hot-reload watchers, or development proxies to create better learning experiences
Sidecars let you create rich, multi-container lab environments that mirror production complexity while keeping your main application containers simple and focused.
HCL Syntax
Section titled “HCL Syntax”Basic Syntax
Section titled “Basic Syntax”resource "sidecar" "proxy" {  target = resource.container.app
  image {    name = "envoy:latest"  }}Full Syntax
Section titled “Full Syntax”resource "sidecar" "monitoring" {  target = resource.container.app
  image {    name = "prometheus/node-exporter:latest"    username = "registry_user"    password = "registry_pass"  }
  # Container configuration  entrypoint = ["/bin/node_exporter"]  command = ["--path.rootfs=/host"]  privileged = false  max_restart_count = 3
  # Environment variables  environment = {    NODE_ID = "worker-1"    METRICS_PORT = "9100"  }
  # Labels  labels = {    service = "monitoring"    component = "exporter"  }
  # Volume mounts  volume {    source = "/proc"    destination = "/host/proc"    type = "bind"    read_only = true  }
  volume {    source = "/sys"    destination = "/host/sys"    type = "bind"    read_only = true  }
  # Resource constraints  resources {    cpu = 100      # 0.1 CPU    memory = 128   # 128MB
    gpu {      driver = "nvidia"      device_ids = ["0"]    }  }
  # Health check  health_check {    timeout = "30s"
    http {      address = "http://localhost:9100/metrics"      success_codes = [200]    }
    tcp {      address = "localhost:9100"    }
    exec {      script = <<-EOF        #!/bin/bash        curl -f http://localhost:9100/metrics || exit 1      EOF    }  }}Fields
Section titled “Fields”| Field | Required | Type | Description | 
|---|---|---|---|
| target | ✓ | reference to container | Reference to the target container this sidecar runs alongside | 
| image | ✓ | block | Container image configuration | 
| entrypoint | list(string) | Override the container’s entrypoint | |
| command | list(string) | Command arguments to pass to the container | |
| environment | map(string) | Environment variables to set in the container | |
| labels | map(string) | Labels to apply to the container | |
| privileged | bool | Whether to run the container in privileged mode | |
| max_ | number | Maximum number of times to restart the container on failure | |
| volume | block | Volume mounts (repeatable) | |
| resources | block | Resource constraints | |
| health_ | block | Health check configuration | 
Image Configuration
Section titled “Image Configuration”sidecar → image
Configures the Docker image to use for the sidecar container.
| Field | Required | Type | Description | 
|---|---|---|---|
| name | ✓ | string | Image name and tag (e.g., “nginx:latest”, “docker.io/library/redis:6”) | 
| username | string | Username for private registry authentication | |
| password | string | Password for private registry authentication | 
Volume Configuration
Section titled “Volume Configuration”sidecar → volume
Configures volume mounts for the sidecar container. This block can be repeated to mount multiple volumes.
| Field | Required | Type | Description | 
|---|---|---|---|
| source | ✓ | string | Source path on the host (relative paths are relative to the HCL file) | 
| destination | ✓ | string | Destination path inside the container (must be absolute) | 
| type | string | Volume type: “bind”, “volume”, or “tmpfs”. Defaults to “bind”. | |
| read_ | bool | Whether the volume should be read-only | |
| bind_ | string | Bind propagation mode: “shared”, “private”, “slave”, “rslave”, “rprivate” | |
| bind_ | bool | Whether to use non-recursive bind mounting | |
| selinux_ | string | SELinux relabeling mode: “shared” or “private” | 
Resource Constraints
Section titled “Resource Constraints”sidecar → resources
Configures CPU, memory, and GPU resource limits for the sidecar container.
| Field | Required | Type | Description | 
|---|---|---|---|
| cpu | number | CPU limit in MHz (1000 = 1 CPU core) | |
| cpu_ | list(number) | Pin container to specific CPU cores | |
| memory | number | Memory limit in megabytes | |
| gpu | block | GPU resource allocation | 
GPU Configuration
Section titled “GPU Configuration”Configures GPU resource allocation for the sidecar container.
| Field | Required | Type | Description | 
|---|---|---|---|
| driver | ✓ | string | GPU driver to use (e.g., “nvidia”) | 
| device_ | ✓ | list(string) | GPU device IDs to allocate | 
Health Monitoring
Section titled “Health Monitoring”sidecar → health_check
Configures health checks to monitor sidecar status and availability.
| Field | Required | Type | Description | 
|---|---|---|---|
| timeout | ✓ | string | Maximum time to wait for health check (e.g., ”30s”, “2m”) | 
| http | block | HTTP health check (repeatable) | |
| tcp | block | TCP health check (repeatable) | |
| exec | block | Execute command health check (repeatable) | 
HTTP Health Check
Section titled “HTTP Health Check”sidecar → health_check → http
Defines an HTTP-based health check that sends requests to specified endpoints.
| Field | Required | Type | Description | 
|---|---|---|---|
| address | ✓ | string | URL to check | 
| method | string | HTTP method to use. Defaults to “GET”. | |
| body | string | Request body to send | |
| headers | map(list(string)) | HTTP headers to send | |
| success_ | list(number) | HTTP status codes that indicate success. Defaults to [200]. | 
TCP Health Check
Section titled “TCP Health Check”sidecar → health_check → tcp
Defines a TCP-based health check that verifies network connectivity.
| Field | Required | Type | Description | 
|---|---|---|---|
| address | ✓ | string | Address to check (e.g., “localhost:8080”) | 
Exec Health Check
Section titled “Exec Health Check”sidecar → health_check → exec
Defines a command-based health check that executes a script or command to determine sidecar health.
| Field | Required | Type | Description | 
|---|---|---|---|
| command | list(string) | Command to execute | |
| script | string | Script to execute | |
| exit_ | number | Expected exit code for success. Defaults to 0. | 
Computed Attributes
Section titled “Computed Attributes”The following attributes are set by the system after the sidecar is created:
| Field | Type | Description | 
|---|---|---|
| meta.id | string | Full resource ID (e.g., resource.sidecar.proxy) | 
| meta.type | string | Resource type ( sidecar) | 
| meta.name | string | Resource name | 
| container_name | string | Fully qualified domain name for accessing the sidecar | 
Validation Rules
Section titled “Validation Rules”- Target requirement: Must reference a valid container resource
- Volume source paths: Made absolute relative to the config file location
- Health check timeout: Must be a valid Go duration string (e.g., ”30s”, “2m”)
- CPU limits: Specified in MHz where 1000 = 1 CPU core
- Memory limits: Specified in megabytes
Examples
Section titled “Examples”Logging Sidecar Example
Section titled “Logging Sidecar Example”resource "container" "app" {  image {    name = "myapp:latest"  }}
resource "sidecar" "logs" {  target = resource.container.app
  image {    name = "fluent/fluent-bit:latest"  }
  volume {    source = "./fluent-bit.conf"    destination = "/fluent-bit/etc/fluent-bit.conf"    type = "bind"    read_only = true  }}Proxy Sidecar Example
Section titled “Proxy Sidecar Example”resource "container" "backend" {  image {    name = "backend-service:latest"  }}
resource "sidecar" "proxy" {  target = resource.container.backend
  image {    name = "envoyproxy/envoy:v1.28.0"  }
  command = [    "envoy",    "-c", "/etc/envoy/envoy.yaml",    "--service-cluster", "backend",    "--service-node", "backend-proxy"  ]
  volume {    source = "./envoy.yaml"    destination = "/etc/envoy/envoy.yaml"    type = "bind"    read_only = true  }
  health_check {    timeout = "10s"
    http {      address = "http://localhost:9901/ready"      success_codes = [200]    }  }}Monitoring Sidecar with Resource Constraints
Section titled “Monitoring Sidecar with Resource Constraints”resource "container" "web" {  image {    name = "nginx:alpine"  }}
resource "sidecar" "metrics" {  target = resource.container.web
  image {    name = "nginx/nginx-prometheus-exporter:latest"  }
  command = [    "-nginx.scrape-uri=http://localhost:8080/metrics"  ]
  resources {    cpu = 50      # 0.05 CPU    memory = 64   # 64MB  }
  health_check {    timeout = "5s"
    tcp {      address = "localhost:9113"    }  }}Best Practices
Section titled “Best Practices”- Resource Limits: Set appropriate CPU and memory limits to prevent sidecars from consuming excessive resources
- Health Checks: Configure health checks for critical sidecars to ensure they’re functioning properly
- Volume Mounts: Use read-only mounts when the sidecar only needs to read configuration files
- Image Tags: Always specify explicit image tags rather than using latest
- Target Dependencies: Ensure the target container is properly configured before adding sidecars
- Single Responsibility: Keep each sidecar focused on a single function (logging, monitoring, proxying)
- Shared Volumes: Use shared volumes to facilitate communication between the main container and sidecar
