Sign inSign up

oorabona/terraform

By oorabona

•Updated about 1 hour ago

terraform container

Image
0

100K+

oorabona/terraform repository overview

⁠Terraform

Enterprise-grade Terraform container with comprehensive DevOps tooling for multi-cloud infrastructure as code. Available in multiple flavors optimized for AWS, Azure, GCP, or all clouds.

Docker Hub GHCR Build

⁠Verify this image

Every build ships a Sigstore-signed SBOM and a full Trivy scan — verify them yourself, no login required:

gh attestation verify oci://ghcr.io/oorabona/terraform:latest --owner oorabona

Full walkthrough (SBOM payload, Trivy findings, multi-arch manifest inspection, upstream dependency tracking) → https://oorabona.github.io/docker-containers/verify-images/⁠

⁠Quick Start

# Full flavor with all cloud CLIs (recommended for development)
docker pull ghcr.io/oorabona/terraform:latest

# Base flavor (smallest image, no cloud CLIs)
docker pull ghcr.io/oorabona/terraform:latest-base

# AWS-specific flavor
docker pull ghcr.io/oorabona/terraform:latest-aws

# Azure-specific flavor
docker pull ghcr.io/oorabona/terraform:latest-azure

# GCP-specific flavor
docker pull ghcr.io/oorabona/terraform:latest-gcp

⁠Available Flavors

All flavors include the core security and DevOps toolkit. The difference is which cloud CLIs are included:

FlavorDescriptionCloud CLIsUse Case
baseCore tools onlyNoneSmallest image, cloud-agnostic
awsAWS optimizedAWS CLIAWS-only infrastructure
azureAzure optimizedAzure CLIAzure-only infrastructure
gcpGCP optimizedGoogle Cloud SDKGCP-only infrastructure
fullAll cloudsAWS CLI + Azure CLI + Google Cloud SDKMulti-cloud or development

Jinja2 templating (jinja2-cli) is bundled in every flavor — the entrypoint renders *.tf.j2 files unconditionally.

⁠Flavor Details
⁠Base (*-base)

Includes Terraform, security scanning, linting, and documentation tools. No cloud provider CLIs installed. Smallest image size.

Tools:

  • Terraform
  • TFLint (linting)
  • Trivy (security scanning)
  • Terragrunt (orchestration)
  • terraform-docs (documentation generation)
  • Infracost (cost estimation)
  • GitHub CLI
  • jinja2-cli (Jinja2 templating)
  • Git, Jq, Yq
⁠AWS (*-aws)

Includes base + AWS CLI for Amazon Web Services infrastructure.

Additional tools:

  • AWS CLI (pinned version for reproducibility)
⁠Azure (*-azure)

Includes base + Azure CLI for Microsoft Azure infrastructure.

Additional tools:

  • Azure CLI (pinned version for reproducibility)
⁠GCP (*-gcp)

Includes base + Google Cloud SDK for Google Cloud Platform infrastructure.

Additional tools:

  • Google Cloud SDK (always latest - GCP installer doesn't support version pinning)
  • gcloud, gsutil, bq commands
⁠Full (*-full)

Includes all cloud CLIs. Recommended for:

  • Multi-cloud environments
  • Development and testing
  • CI/CD pipelines
  • Template-based infrastructure

Additional tools:

  • AWS CLI
  • Azure CLI
  • Google Cloud SDK
⁠Image Tags
ghcr.io/oorabona/terraform:{version}-{flavor}

Examples:

  • latest or latest-full - Latest Terraform, all clouds
  • latest-base - Latest Terraform, no cloud CLIs
  • latest-aws - Latest Terraform with AWS CLI
  • 1.10.3-azure - Terraform 1.10.3 with Azure CLI

⁠Tools Reference

All versions are pinned and automatically monitored for updates:

ToolVersionDescriptionFlavors
Terraform(upstream)Infrastructure as codeAll
TFLint0.60.0Terraform linterAll
Trivy0.69.1Security scannerAll
Terragrunt0.99.1Terraform orchestrationAll
terraform-docs0.21.0Documentation generatorAll
Infracost0.10.43Cloud cost estimationAll
GitHub CLI2.86.0GitHub automationAll
AWS CLI1.44.33Amazon Web Services CLIaws, full
Azure CLI2.83.0Microsoft Azure CLIazure, full
Google Cloud SDKlatestGoogle Cloud Platform CLIgcp, full
jinja2-cli1.0.1Jinja2 templating CLIAll
⁠Built-in Utilities

All flavors include:

  • Git - Version control
  • Jq - JSON processor
  • Yq - YAML processor
  • jinja2-cli - Jinja2 templating
  • Bash - Shell scripting
  • Curl - HTTP client
  • Python 3 - Scripting runtime

⁠Usage

services:
  terraform:
    image: ghcr.io/oorabona/terraform:latest
    user: "1000:1000"
    volumes:
      - .:/data
      - ~/.aws:/home/terraform/.aws:ro  # AWS credentials (read-only)
      - ~/.azure:/home/terraform/.azure:ro  # Azure credentials (read-only)
      - ~/.config/gcloud:/home/terraform/.config/gcloud:ro  # GCP credentials (read-only)
    environment:
      # Pass credentials from environment, never hardcode
      - AWS_ACCESS_KEY_ID
      - AWS_SECRET_ACCESS_KEY
      - AWS_DEFAULT_REGION
      - AZURE_SUBSCRIPTION_ID
      - AZURE_TENANT_ID
      - AZURE_CLIENT_ID
      - AZURE_CLIENT_SECRET
      - GOOGLE_APPLICATION_CREDENTIALS
      - TF_VAR_project_id
⁠Docker Run
# Initialize and plan
docker run --rm \
  -v $(pwd):/data \
  -v ~/.aws:/home/terraform/.aws:ro \
  ghcr.io/oorabona/terraform:latest-aws \
  init

docker run --rm \
  -v $(pwd):/data \
  -v ~/.aws:/home/terraform/.aws:ro \
  -e AWS_DEFAULT_REGION \
  ghcr.io/oorabona/terraform:latest-aws \
  plan

# Apply with environment credentials
docker run --rm -it \
  -v $(pwd):/data \
  -e AWS_ACCESS_KEY_ID \
  -e AWS_SECRET_ACCESS_KEY \
  -e AWS_DEFAULT_REGION \
  ghcr.io/oorabona/terraform:latest-aws \
  apply
⁠Jinja2 Templating

Every flavor includes jinja2-cli for template-based infrastructure. The entrypoint renders any *.tf.j2 files in the working directory to *.tf (using $CONFIGFILE, default config.json) before running Terraform:

# Create templated Terraform files with .j2 extension
# Example: main.tf.j2
resource "aws_instance" "{{ instance_name }}" {
  instance_type = "{{ instance_type }}"
  ami           = "{{ ami_id }}"
}

# Create config.json with template variables
{
  "instance_name": "web-server",
  "instance_type": "t3.micro",
  "ami_id": "ami-12345678"
}

# Process templates
docker run --rm \
  -v $(pwd):/data \
  ghcr.io/oorabona/terraform:latest \
  bash -c "for f in *.tf.j2; do jinja2 \$f config.json > \${f%.j2}; done && terraform plan"
⁠Security Scanning
# Scan Terraform configurations for misconfigurations
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  trivy config .

# Scan with detailed output
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  trivy config --format table --severity HIGH,CRITICAL .

# Scan for sensitive data
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  trivy fs --scanners secret .
⁠Linting
# Initialize TFLint plugins
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  tflint --init

# Lint Terraform files
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  tflint

# Lint with AWS plugin
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest-aws \
  tflint --config=.tflint.hcl
⁠Documentation Generation
# Generate README.md from Terraform modules
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  terraform-docs markdown table . > README.md

# Generate JSON output
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  terraform-docs json . > module.json
⁠Cost Estimation
# Generate cost breakdown
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  infracost breakdown --path .

# Compare costs between branches
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  infracost diff --path .
⁠Building Locally
# Build specific flavor
docker build --build-arg VERSION=latest --build-arg FLAVOR=aws -t terraform:aws .

# Build full flavor (default)
docker build --build-arg VERSION=latest -t terraform:full .

# Build base flavor
docker build --build-arg VERSION=latest --build-arg FLAVOR=base -t terraform:base .

⁠Build Arguments

ArgumentDescriptionDefault
VERSIONTerraform versionlatest
UPSTREAM_VERSIONRaw Terraform version (without suffix)(derived from VERSION)
FLAVORFlavor to buildfull
TFLINT_VERSIONTFLint version0.60.0
TRIVY_VERSIONTrivy version0.69.1
TERRAGRUNT_VERSIONTerragrunt version0.99.1
TERRAFORM_DOCS_VERSIONterraform-docs version0.21.0
INFRACOST_VERSIONInfracost version0.10.43
GITHUB_CLI_VERSIONGitHub CLI version2.86.0
AWS_CLI_VERSIONAWS CLI version1.44.33
AZURE_CLI_VERSIONAzure CLI version2.83.0
GCP_CLI_VERSIONGCP SDK versionlatest
JINJA2_CLI_VERSIONjinja2-cli version1.0.1

⁠Environment Variables

VariableDescriptionDefault
CONFIGFILEJinja2 template data file (all flavors)config.json
TERRAFORM_FLAVORFlavor identifier(set during build)
AWS_ACCESS_KEY_IDAWS credentials(pass from environment)
AWS_SECRET_ACCESS_KEYAWS credentials(pass from environment)
AWS_DEFAULT_REGIONAWS region(pass from environment)
AZURE_SUBSCRIPTION_IDAzure subscription(pass from environment)
AZURE_TENANT_IDAzure tenant(pass from environment)
AZURE_CLIENT_IDAzure service principal(pass from environment)
AZURE_CLIENT_SECRETAzure service principal(pass from environment)
GOOGLE_APPLICATION_CREDENTIALSGCP credentials file path(pass from environment)
TF_VAR_*Terraform variables(user-defined)

⁠Volumes

PathPurposeNotes
/dataTerraform working directoryWORKDIR + VOLUME
/home/terraform/.awsAWS credentialsMount read-only
/home/terraform/.azureAzure credentialsMount read-only
/home/terraform/.config/gcloudGCP credentialsMount read-only
/.terraform.dTerraform plugins/cacheUse tmpfs for security
/.configTool configurationUse tmpfs for security
/tmpTemporary filesUse tmpfs for security

⁠Security

⁠Base Security
  • Multi-stage build minimizes attack surface
  • Alpine-based final image for minimal footprint
  • Regular security updates through automated rebuilds
  • Includes Trivy for security scanning
  • Non-root execution by default
  • No shell access for terraform user (/sbin/nologin)
⁠Credential Security (CRITICAL)

NEVER hardcode credentials in docker-compose.yml or Dockerfiles:

# BAD - Never do this:
environment:
  AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE

# GOOD - Use environment variables:
environment:
  AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
  AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}

# BETTER - Use credential files mounted read-only:
volumes:
  - ~/.aws:/home/terraform/.aws:ro
services:
  terraform:
    image: ghcr.io/oorabona/terraform:latest
    user: "1000:1000"  # terraform:terraform
    read_only: true
    tmpfs:
      - /.terraform.d
      - /.config
      - /tmp
    cap_drop:
      - ALL
    security_opt:
      - no-new-privileges:true
    volumes:
      - .:/data:ro  # Read-only if only planning
      - ~/.aws:/home/terraform/.aws:ro
    environment:
      # Pass credentials from environment, never hardcode
      - AWS_ACCESS_KEY_ID
      - AWS_SECRET_ACCESS_KEY
      - AWS_DEFAULT_REGION
⁠Scanning Your Infrastructure
# Scan for security issues before applying
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  trivy config --severity HIGH,CRITICAL .

# Scan for common Terraform mistakes
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  tflint --enable-rule=terraform_deprecated_interpolation

# Check for secrets in code
docker run --rm -v $(pwd):/data ghcr.io/oorabona/terraform:latest \
  trivy fs --scanners secret .

⁠Dependencies

All tool versions are pinned and automatically monitored for updates:

DependencyVersionSourceMonitoringLicense
Terraformupstreamhashicorp/terraformDocker HubMPL-2.0
TFLint0.60.0terraform-linters/tflintGitHub ReleasesMPL-2.0
Trivy0.69.1aquasecurity/trivyGitHub ReleasesApache-2.0
Terragrunt0.99.1gruntwork-io/terragruntGitHub ReleasesMIT
terraform-docs0.21.0terraform-docs/terraform-docsGitHub ReleasesMIT
Infracost0.10.43infracost/infracostGitHub ReleasesApache-2.0
GitHub CLI2.86.0cli/cliGitHub ReleasesMIT
AWS CLI1.44.33awscliPyPIApache-2.0
Azure CLI2.83.0azure-cliPyPIMIT
Google Cloud SDKlatestN/ANot tracked*Apache-2.0

*Google Cloud SDK installer always fetches the latest version - version pinning is not supported by the GCP installer. The GCP_CLI_VERSION in config.yaml is for reference only.

⁠Architecture

terraform/
├── Dockerfile                 # Multi-stage, multi-flavor build
├── docker-entrypoint.sh       # Entrypoint script
├── docker-compose.yml         # Example composition
├── config.yaml               # Tool version configuration
├── version.sh                # Upstream version discovery
└── build                     # Build script with auto-version detection
⁠Multi-stage Build

The Dockerfile uses a multi-stage build process:

  1. terraform stage - Extracts Terraform binary from HashiCorp image
  2. security-tools stage - Downloads TFLint and Trivy
  3. devops-tools stage - Downloads Terragrunt, terraform-docs, Infracost, GitHub CLI
  4. cloud-tools-gcp stage - Conditionally installs Google Cloud SDK (only for gcp/full flavors)
  5. Final stage - Assembles tools based on FLAVOR argument and installs cloud CLIs via pip

This approach:

  • Minimizes final image size
  • Enables parallel builds of independent stages
  • Allows conditional inclusion of cloud-specific tools
  • Maintains clean separation of concerns
⁠Flavor Selection

Build-time FLAVOR argument determines:

  • Which cloud CLIs are installed via pip (AWS, Azure)
  • Whether Google Cloud SDK is copied from cloud-tools-gcp stage
  • Contents of environment variable TERRAFORM_FLAVOR

(jinja2-cli is installed in every flavor, independent of FLAVOR.)

⁠CI/CD Integration

⁠GitHub Actions
- name: Terraform Plan
  uses: docker://ghcr.io/oorabona/terraform:latest-aws
  with:
    args: plan -out=tfplan
  env:
    AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
    AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    AWS_DEFAULT_REGION: us-east-1

- name: Security Scan
  uses: docker://ghcr.io/oorabona/terraform:latest
  with:
    args: trivy config --exit-code 1 --severity HIGH,CRITICAL .

- name: Cost Estimation
  uses: docker://ghcr.io/oorabona/terraform:latest
  with:
    args: infracost breakdown --path .
  env:
    INFRACOST_API_KEY: ${{ secrets.INFRACOST_API_KEY }}
⁠GitLab CI
terraform:
  image: ghcr.io/oorabona/terraform:latest-aws
  script:
    - terraform init
    - terraform plan
    - trivy config .
  variables:
    AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
    AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY

⁠Troubleshooting

⁠Permission Denied
# Ensure proper user ownership
docker run --rm -it --user 1000:1000 \
  -v $(pwd):/data \
  ghcr.io/oorabona/terraform:latest init

# Or fix permissions on host
sudo chown -R 1000:1000 .terraform/
⁠Plugin Installation Issues
# Clear plugin cache
rm -rf .terraform/
docker run --rm -v $(pwd):/data \
  ghcr.io/oorabona/terraform:latest init -upgrade
⁠Cloud Provider Authentication
# AWS - Verify credentials
docker run --rm \
  -e AWS_ACCESS_KEY_ID \
  -e AWS_SECRET_ACCESS_KEY \
  ghcr.io/oorabona/terraform:latest-aws \
  aws sts get-caller-identity

# Azure - Verify login
docker run --rm \
  -v ~/.azure:/home/terraform/.azure:ro \
  ghcr.io/oorabona/terraform:latest-azure \
  az account show

# GCP - Verify authentication
docker run --rm \
  -v ~/.config/gcloud:/home/terraform/.config/gcloud:ro \
  ghcr.io/oorabona/terraform:latest-gcp \
  gcloud auth list

Tag summary

Content type

Image

Digest

sha256:3b2341ea5…

Size

654.6 MB

Last updated

about 1 hour ago

docker pull oorabona/terraform