feat: Add regex managers for Docker container versioning in Terraform
Some checks failed
Code Quality & Security Scan / TFLint (push) Successful in 26s
Code Quality & Security Scan / Terraform Destroy (push) Has been skipped
Code Quality & Security Scan / Tfsec Security Scan (push) Successful in 33s
Code Quality & Security Scan / Checkov Security Scan (push) Successful in 39s
Code Quality & Security Scan / Terraform Validate (push) Failing after 32s
Code Quality & Security Scan / SonarQube Scan (push) Has been skipped
Code Quality & Security Scan / Terraform Plan (push) Has been skipped
Code Quality & Security Scan / Terraform Apply (push) Has been skipped
Some checks failed
Code Quality & Security Scan / TFLint (push) Successful in 26s
Code Quality & Security Scan / Terraform Destroy (push) Has been skipped
Code Quality & Security Scan / Tfsec Security Scan (push) Successful in 33s
Code Quality & Security Scan / Checkov Security Scan (push) Successful in 39s
Code Quality & Security Scan / Terraform Validate (push) Failing after 32s
Code Quality & Security Scan / SonarQube Scan (push) Has been skipped
Code Quality & Security Scan / Terraform Plan (push) Has been skipped
Code Quality & Security Scan / Terraform Apply (push) Has been skipped
Add support for Renovate to detect and update Docker image versions defined in Terraform files using annotation comments. Changes: - Add 3 regex managers to config.js.tpl for different annotation patterns: - Basic: # renovate: datasource=docker - With versioning: # renovate: datasource=docker versioning=semver - Separate variable: # renovate: datasource=docker depName=redis - Update README.md with comprehensive Docker container annotation docs - Update QUICKSTART.md with Terraform Docker container examples - Add example-annotated-containers.tf with usage patterns This enables Renovate to automatically create PRs when Docker images used in Terraform container definitions have updates available.
This commit is contained in:
parent
77e6102b0c
commit
16bb56c454
@ -302,6 +302,37 @@ Add this to `renovate.json`:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Terraform with Docker Containers
|
||||||
|
|
||||||
|
If you deploy Docker containers via Terraform and define image versions in your `.tf` files, Renovate can track those too!
|
||||||
|
|
||||||
|
**Add annotations to your Terraform code:**
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
locals {
|
||||||
|
containers = {
|
||||||
|
redis = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "redis:8.0.0"
|
||||||
|
# ... other settings
|
||||||
|
}
|
||||||
|
|
||||||
|
grafana = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "grafana/grafana:11.2.0"
|
||||||
|
# ... other settings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `# renovate: datasource=docker` comment tells Renovate to:
|
||||||
|
1. Parse the `image` value on the next line
|
||||||
|
2. Extract the image name and version
|
||||||
|
3. Create PRs when updates are available
|
||||||
|
|
||||||
|
**See README.md** for more annotation patterns and examples.
|
||||||
|
|
||||||
## Useful Commands
|
## Useful Commands
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
113
README.md
113
README.md
@ -370,6 +370,119 @@ For repositories with Terraform code:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Docker Container Versioning in Terraform
|
||||||
|
|
||||||
|
This Renovate deployment includes **regex managers** that can detect and update Docker image versions defined in Terraform files. This is useful when you deploy Docker containers via Terraform and want Renovate to keep those images up to date.
|
||||||
|
|
||||||
|
#### How It Works
|
||||||
|
|
||||||
|
Add a special comment annotation above your `image` definition in your Terraform code. Renovate will then detect the Docker image and create PRs when updates are available.
|
||||||
|
|
||||||
|
#### Annotation Format
|
||||||
|
|
||||||
|
**Basic annotation** (combined image:tag format):
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
locals {
|
||||||
|
containers = {
|
||||||
|
redis = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "docker.io/library/redis:8"
|
||||||
|
# ... other settings
|
||||||
|
}
|
||||||
|
|
||||||
|
traefik = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "traefik:3.1.2"
|
||||||
|
ports = [80, 443]
|
||||||
|
}
|
||||||
|
|
||||||
|
grafana = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "grafana/grafana:11.2.0"
|
||||||
|
# ... other settings
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**With explicit versioning scheme** (for non-standard versioning):
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
vault = {
|
||||||
|
# renovate: datasource=docker versioning=semver
|
||||||
|
image = "hashicorp/vault:1.17.3"
|
||||||
|
}
|
||||||
|
|
||||||
|
minio = {
|
||||||
|
# renovate: datasource=docker versioning=regex
|
||||||
|
image = "minio/minio:RELEASE.2024-08-29T01-40-52Z"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Separate version variable**:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
# renovate: datasource=docker depName=redis
|
||||||
|
variable "redis_version" {
|
||||||
|
type = string
|
||||||
|
default = "8.0.0"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Supported Patterns
|
||||||
|
|
||||||
|
| Pattern | Example | Use Case |
|
||||||
|
|---------|---------|----------|
|
||||||
|
| Combined image:tag | `image = "nginx:1.25.0"` | Most common - image and version in one string |
|
||||||
|
| With registry prefix | `image = "docker.io/library/redis:8"` | Official images with full path |
|
||||||
|
| Custom versioning | `versioning=semver` | Images with non-standard version formats |
|
||||||
|
| Separate variable | `depName=redis` + `version = "8.0.0"` | When image and version are split |
|
||||||
|
|
||||||
|
#### Example: Complete Container Definition
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
# Paperless-NGX with Redis broker
|
||||||
|
locals {
|
||||||
|
services = {
|
||||||
|
paperless-broker = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "docker.io/library/redis:8"
|
||||||
|
|
||||||
|
healthcheck = {
|
||||||
|
test = ["CMD", "redis-cli", "ping"]
|
||||||
|
interval = "30s"
|
||||||
|
timeout = "5s"
|
||||||
|
retries = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
volumes = {
|
||||||
|
"paperless-redisdata" = "/data"
|
||||||
|
}
|
||||||
|
|
||||||
|
networks = ["paperless-backend-network"]
|
||||||
|
container_ports = ["6379"]
|
||||||
|
}
|
||||||
|
|
||||||
|
paperless-webserver = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "ghcr.io/paperless-ngx/paperless-ngx:2.12.1"
|
||||||
|
|
||||||
|
networks = ["paperless-backend-network", "traefik_network"]
|
||||||
|
use_traefik = true
|
||||||
|
container_ports = ["8000"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
When Renovate scans this repository, it will:
|
||||||
|
1. Detect `redis:8` and create PRs for Redis updates
|
||||||
|
2. Detect `paperless-ngx:2.12.1` and create PRs for Paperless-NGX updates
|
||||||
|
3. Continue to update Terraform providers and modules as usual
|
||||||
|
|
||||||
|
An example annotated container file is provided in `files/example-annotated-containers.tf`.
|
||||||
|
|
||||||
## Variables
|
## Variables
|
||||||
|
|
||||||
### Terraform Variables
|
### Terraform Variables
|
||||||
|
|||||||
@ -25,5 +25,46 @@ module.exports = {
|
|||||||
// Additional recommended settings for Gitea
|
// Additional recommended settings for Gitea
|
||||||
requireConfig: 'optional',
|
requireConfig: 'optional',
|
||||||
|
|
||||||
|
// Regex managers for custom version detection
|
||||||
|
// This enables Renovate to detect Docker image versions in Terraform files
|
||||||
|
// when annotated with: # renovate: datasource=docker
|
||||||
|
regexManagers: [
|
||||||
|
{
|
||||||
|
// Match Docker image versions in Terraform files (.tf and .tfvars)
|
||||||
|
// Requires annotation comment above the image line
|
||||||
|
// Example:
|
||||||
|
// # renovate: datasource=docker
|
||||||
|
// image = "nginx:1.25.0"
|
||||||
|
fileMatch: ['\\.tf$', '\\.tfvars$'],
|
||||||
|
matchStrings: [
|
||||||
|
'#\\s*renovate:\\s*datasource=docker\\s*\\n\\s*image\\s*=\\s*"(?<depName>[^:"]+):(?<currentValue>[^"]+)"'
|
||||||
|
],
|
||||||
|
datasourceTemplate: 'docker'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Match Docker image versions with explicit versioning scheme
|
||||||
|
// Example:
|
||||||
|
// # renovate: datasource=docker versioning=semver
|
||||||
|
// image = "hashicorp/vault:1.17.3"
|
||||||
|
fileMatch: ['\\.tf$', '\\.tfvars$'],
|
||||||
|
matchStrings: [
|
||||||
|
'#\\s*renovate:\\s*datasource=docker\\s+versioning=(?<versioning>\\S+)\\s*\\n\\s*image\\s*=\\s*"(?<depName>[^:"]+):(?<currentValue>[^"]+)"'
|
||||||
|
],
|
||||||
|
datasourceTemplate: 'docker',
|
||||||
|
versioningTemplate: '{{versioning}}'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Match separate image and version/tag variables
|
||||||
|
// Example:
|
||||||
|
// # renovate: datasource=docker depName=redis
|
||||||
|
// version = "8.0.0"
|
||||||
|
fileMatch: ['\\.tf$', '\\.tfvars$'],
|
||||||
|
matchStrings: [
|
||||||
|
'#\\s*renovate:\\s*datasource=(?<datasource>\\S+)\\s+depName=(?<depName>\\S+)\\s*\\n.*?(?:version|tag)\\s*=\\s*"(?<currentValue>[^"]+)"'
|
||||||
|
],
|
||||||
|
datasourceTemplate: '{{datasource}}'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
// Repository-level settings can be overridden in renovate.json files
|
// Repository-level settings can be overridden in renovate.json files
|
||||||
};
|
};
|
||||||
|
|||||||
226
files/example-annotated-containers.tf
Normal file
226
files/example-annotated-containers.tf
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
# Example: Annotated Container Definitions for Renovate
|
||||||
|
#
|
||||||
|
# This file demonstrates how to annotate Docker container definitions
|
||||||
|
# in Terraform so that Renovate can detect and update image versions.
|
||||||
|
#
|
||||||
|
# Add the comment "# renovate: datasource=docker" above the image line
|
||||||
|
# to enable automatic version detection and updates.
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Basic Pattern: Combined image:tag format
|
||||||
|
# =============================================================================
|
||||||
|
# This is the most common pattern where image name and tag are in one string.
|
||||||
|
|
||||||
|
locals {
|
||||||
|
services = {
|
||||||
|
# Basic Redis container
|
||||||
|
redis = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "redis:8.0.0"
|
||||||
|
|
||||||
|
container_ports = ["6379"]
|
||||||
|
networks = ["backend-network"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# Container with full registry path
|
||||||
|
postgres = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "docker.io/library/postgres:16.4-alpine"
|
||||||
|
|
||||||
|
container_ports = ["5432"]
|
||||||
|
networks = ["backend-network"]
|
||||||
|
volumes = {
|
||||||
|
"postgres-data" = "/var/lib/postgresql/data"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Third-party image from Docker Hub
|
||||||
|
grafana = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "grafana/grafana:11.2.0"
|
||||||
|
|
||||||
|
container_ports = ["3000"]
|
||||||
|
networks = ["traefik_network", "monitoring-network"]
|
||||||
|
use_traefik = true
|
||||||
|
}
|
||||||
|
|
||||||
|
# Image from GitHub Container Registry
|
||||||
|
paperless = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "ghcr.io/paperless-ngx/paperless-ngx:2.12.1"
|
||||||
|
|
||||||
|
container_ports = ["8000"]
|
||||||
|
networks = ["traefik_network"]
|
||||||
|
use_traefik = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Advanced Pattern: With explicit versioning scheme
|
||||||
|
# =============================================================================
|
||||||
|
# Use this when the image has a non-standard version format.
|
||||||
|
|
||||||
|
locals {
|
||||||
|
advanced_services = {
|
||||||
|
# HashiCorp images use semver
|
||||||
|
vault = {
|
||||||
|
# renovate: datasource=docker versioning=semver
|
||||||
|
image = "hashicorp/vault:1.17.3"
|
||||||
|
|
||||||
|
container_ports = ["8200"]
|
||||||
|
networks = ["traefik_network"]
|
||||||
|
}
|
||||||
|
|
||||||
|
# MinIO uses date-based releases
|
||||||
|
minio = {
|
||||||
|
# renovate: datasource=docker versioning=regex:^RELEASE\.(?<major>\d{4})-(?<minor>\d{2})-(?<patch>\d{2})T\d{2}-\d{2}-\d{2}Z$
|
||||||
|
image = "minio/minio:RELEASE.2024-08-29T01-40-52Z"
|
||||||
|
|
||||||
|
container_ports = ["9000", "9001"]
|
||||||
|
networks = ["traefik_network"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Alternative Pattern: Separate version variable
|
||||||
|
# =============================================================================
|
||||||
|
# Use this when you prefer to define versions as separate variables.
|
||||||
|
|
||||||
|
# renovate: datasource=docker depName=traefik
|
||||||
|
variable "traefik_version" {
|
||||||
|
description = "Version of Traefik to deploy"
|
||||||
|
type = string
|
||||||
|
default = "3.1.2"
|
||||||
|
}
|
||||||
|
|
||||||
|
# renovate: datasource=docker depName=redis
|
||||||
|
variable "redis_version" {
|
||||||
|
description = "Version of Redis to deploy"
|
||||||
|
type = string
|
||||||
|
default = "8.0.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
# renovate: datasource=docker depName=grafana/grafana
|
||||||
|
variable "grafana_version" {
|
||||||
|
description = "Version of Grafana to deploy"
|
||||||
|
type = string
|
||||||
|
default = "11.2.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Usage example with separate variables
|
||||||
|
locals {
|
||||||
|
versioned_services = {
|
||||||
|
traefik = {
|
||||||
|
image = "traefik:${var.traefik_version}"
|
||||||
|
container_ports = ["80", "443", "8080"]
|
||||||
|
networks = ["traefik_network"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# =============================================================================
|
||||||
|
# Complete Example: Production-like container object
|
||||||
|
# =============================================================================
|
||||||
|
# This shows a realistic container definition with all common settings.
|
||||||
|
|
||||||
|
locals {
|
||||||
|
production_services = {
|
||||||
|
# Paperless-NGX Document Management System
|
||||||
|
paperless-webserver = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "ghcr.io/paperless-ngx/paperless-ngx:2.12.1"
|
||||||
|
|
||||||
|
healthcheck = {
|
||||||
|
test = ["CMD", "curl", "-f", "http://localhost:8000"]
|
||||||
|
interval = "30s"
|
||||||
|
timeout = "10s"
|
||||||
|
retries = 5
|
||||||
|
start_period = "60s"
|
||||||
|
}
|
||||||
|
|
||||||
|
vault_env_path = "secret/paperless-ngx"
|
||||||
|
environment = "prod"
|
||||||
|
replicas = 1
|
||||||
|
|
||||||
|
volumes = {
|
||||||
|
"paperless-data" = "/usr/src/paperless/data"
|
||||||
|
"paperless-media" = "/usr/src/paperless/media"
|
||||||
|
"paperless-export" = "/usr/src/paperless/export"
|
||||||
|
"paperless-consume" = "/usr/src/paperless/consume"
|
||||||
|
}
|
||||||
|
|
||||||
|
host_ports = []
|
||||||
|
container_ports = ["8000"]
|
||||||
|
networks = ["paperless-backend-network", "traefik_network"]
|
||||||
|
use_traefik = true
|
||||||
|
is_swarm_service = false
|
||||||
|
consul_service = true
|
||||||
|
access_docker_sock = false
|
||||||
|
create_cname_record = true
|
||||||
|
}
|
||||||
|
|
||||||
|
# Redis broker for Paperless
|
||||||
|
paperless-broker = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "docker.io/library/redis:8"
|
||||||
|
|
||||||
|
healthcheck = {
|
||||||
|
test = ["CMD", "redis-cli", "ping"]
|
||||||
|
interval = "30s"
|
||||||
|
timeout = "5s"
|
||||||
|
retries = 3
|
||||||
|
start_period = "10s"
|
||||||
|
}
|
||||||
|
|
||||||
|
vault_env_path = "secret/paperless-ngx"
|
||||||
|
environment = "prod"
|
||||||
|
replicas = 1
|
||||||
|
|
||||||
|
volumes = {
|
||||||
|
"paperless-redisdata" = "/data"
|
||||||
|
}
|
||||||
|
|
||||||
|
host_ports = []
|
||||||
|
container_ports = ["6379"]
|
||||||
|
networks = ["paperless-backend-network"]
|
||||||
|
use_traefik = false
|
||||||
|
is_swarm_service = false
|
||||||
|
consul_service = false
|
||||||
|
access_docker_sock = false
|
||||||
|
create_cname_record = false
|
||||||
|
}
|
||||||
|
|
||||||
|
# PostgreSQL database for Paperless
|
||||||
|
paperless-db = {
|
||||||
|
# renovate: datasource=docker
|
||||||
|
image = "docker.io/library/postgres:16.4-alpine"
|
||||||
|
|
||||||
|
healthcheck = {
|
||||||
|
test = ["CMD-SHELL", "pg_isready -U paperless"]
|
||||||
|
interval = "30s"
|
||||||
|
timeout = "5s"
|
||||||
|
retries = 3
|
||||||
|
start_period = "30s"
|
||||||
|
}
|
||||||
|
|
||||||
|
vault_env_path = "secret/paperless-ngx"
|
||||||
|
environment = "prod"
|
||||||
|
replicas = 1
|
||||||
|
|
||||||
|
volumes = {
|
||||||
|
"paperless-pgdata" = "/var/lib/postgresql/data"
|
||||||
|
}
|
||||||
|
|
||||||
|
host_ports = []
|
||||||
|
container_ports = ["5432"]
|
||||||
|
networks = ["paperless-backend-network"]
|
||||||
|
use_traefik = false
|
||||||
|
is_swarm_service = false
|
||||||
|
consul_service = false
|
||||||
|
access_docker_sock = false
|
||||||
|
create_cname_record = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user