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.
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/
# 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
All flavors include the core security and DevOps toolkit. The difference is which cloud CLIs are included:
| Flavor | Description | Cloud CLIs | Use Case |
|---|---|---|---|
| base | Core tools only | None | Smallest image, cloud-agnostic |
| aws | AWS optimized | AWS CLI | AWS-only infrastructure |
| azure | Azure optimized | Azure CLI | Azure-only infrastructure |
| gcp | GCP optimized | Google Cloud SDK | GCP-only infrastructure |
| full | All clouds | AWS CLI + Azure CLI + Google Cloud SDK | Multi-cloud or development |
Jinja2 templating (
jinja2-cli) is bundled in every flavor — the entrypoint renders*.tf.j2files unconditionally.
*-base)Includes Terraform, security scanning, linting, and documentation tools. No cloud provider CLIs installed. Smallest image size.
Tools:
*-aws)Includes base + AWS CLI for Amazon Web Services infrastructure.
Additional tools:
*-azure)Includes base + Azure CLI for Microsoft Azure infrastructure.
Additional tools:
*-gcp)Includes base + Google Cloud SDK for Google Cloud Platform infrastructure.
Additional tools:
*-full)Includes all cloud CLIs. Recommended for:
Additional tools:
ghcr.io/oorabona/terraform:{version}-{flavor}
Examples:
latest or latest-full - Latest Terraform, all cloudslatest-base - Latest Terraform, no cloud CLIslatest-aws - Latest Terraform with AWS CLI1.10.3-azure - Terraform 1.10.3 with Azure CLIAll versions are pinned and automatically monitored for updates:
| Tool | Version | Description | Flavors |
|---|---|---|---|
| Terraform | (upstream) | Infrastructure as code | All |
| TFLint | 0.60.0 | Terraform linter | All |
| Trivy | 0.69.1 | Security scanner | All |
| Terragrunt | 0.99.1 | Terraform orchestration | All |
| terraform-docs | 0.21.0 | Documentation generator | All |
| Infracost | 0.10.43 | Cloud cost estimation | All |
| GitHub CLI | 2.86.0 | GitHub automation | All |
| AWS CLI | 1.44.33 | Amazon Web Services CLI | aws, full |
| Azure CLI | 2.83.0 | Microsoft Azure CLI | azure, full |
| Google Cloud SDK | latest | Google Cloud Platform CLI | gcp, full |
| jinja2-cli | 1.0.1 | Jinja2 templating CLI | All |
All flavors include:
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
# 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
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"
# 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 .
# 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
# 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
# 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 .
# 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 .
| Argument | Description | Default |
|---|---|---|
VERSION | Terraform version | latest |
UPSTREAM_VERSION | Raw Terraform version (without suffix) | (derived from VERSION) |
FLAVOR | Flavor to build | full |
TFLINT_VERSION | TFLint version | 0.60.0 |
TRIVY_VERSION | Trivy version | 0.69.1 |
TERRAGRUNT_VERSION | Terragrunt version | 0.99.1 |
TERRAFORM_DOCS_VERSION | terraform-docs version | 0.21.0 |
INFRACOST_VERSION | Infracost version | 0.10.43 |
GITHUB_CLI_VERSION | GitHub CLI version | 2.86.0 |
AWS_CLI_VERSION | AWS CLI version | 1.44.33 |
AZURE_CLI_VERSION | Azure CLI version | 2.83.0 |
GCP_CLI_VERSION | GCP SDK version | latest |
JINJA2_CLI_VERSION | jinja2-cli version | 1.0.1 |
| Variable | Description | Default |
|---|---|---|
CONFIGFILE | Jinja2 template data file (all flavors) | config.json |
TERRAFORM_FLAVOR | Flavor identifier | (set during build) |
AWS_ACCESS_KEY_ID | AWS credentials | (pass from environment) |
AWS_SECRET_ACCESS_KEY | AWS credentials | (pass from environment) |
AWS_DEFAULT_REGION | AWS region | (pass from environment) |
AZURE_SUBSCRIPTION_ID | Azure subscription | (pass from environment) |
AZURE_TENANT_ID | Azure tenant | (pass from environment) |
AZURE_CLIENT_ID | Azure service principal | (pass from environment) |
AZURE_CLIENT_SECRET | Azure service principal | (pass from environment) |
GOOGLE_APPLICATION_CREDENTIALS | GCP credentials file path | (pass from environment) |
TF_VAR_* | Terraform variables | (user-defined) |
| Path | Purpose | Notes |
|---|---|---|
/data | Terraform working directory | WORKDIR + VOLUME |
/home/terraform/.aws | AWS credentials | Mount read-only |
/home/terraform/.azure | Azure credentials | Mount read-only |
/home/terraform/.config/gcloud | GCP credentials | Mount read-only |
/.terraform.d | Terraform plugins/cache | Use tmpfs for security |
/.config | Tool configuration | Use tmpfs for security |
/tmp | Temporary files | Use tmpfs for security |
/sbin/nologin)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
# 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 .
All tool versions are pinned and automatically monitored for updates:
| Dependency | Version | Source | Monitoring | License |
|---|---|---|---|---|
| Terraform | upstream | hashicorp/terraform | Docker Hub | MPL-2.0 |
| TFLint | 0.60.0 | terraform-linters/tflint | GitHub Releases | MPL-2.0 |
| Trivy | 0.69.1 | aquasecurity/trivy | GitHub Releases | Apache-2.0 |
| Terragrunt | 0.99.1 | gruntwork-io/terragrunt | GitHub Releases | MIT |
| terraform-docs | 0.21.0 | terraform-docs/terraform-docs | GitHub Releases | MIT |
| Infracost | 0.10.43 | infracost/infracost | GitHub Releases | Apache-2.0 |
| GitHub CLI | 2.86.0 | cli/cli | GitHub Releases | MIT |
| AWS CLI | 1.44.33 | awscli | PyPI | Apache-2.0 |
| Azure CLI | 2.83.0 | azure-cli | PyPI | MIT |
| Google Cloud SDK | latest | N/A | Not 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.
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
The Dockerfile uses a multi-stage build process:
This approach:
Build-time FLAVOR argument determines:
TERRAFORM_FLAVOR(jinja2-cli is installed in every flavor, independent of FLAVOR.)
- 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 }}
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
# 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/
# Clear plugin cache
rm -rf .terraform/
docker run --rm -v $(pwd):/data \
ghcr.io/oorabona/terraform:latest init -upgrade
# 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
Content type
Image
Digest
sha256:3b2341ea5…
Size
654.6 MB
Last updated
about 1 hour ago
docker pull oorabona/terraform