Files
OpenTofuPlayground/modules/app-openresty-pg-redis/main.tf
Lutz Finsterle 806aecfce5
Some checks failed
Test / Static Analysis (push) Successful in 32s
Test / Unit Tests — Docker Stack (push) Failing after 25s
Test / Unit Tests — K8s Stack (push) Failing after 25s
Test / Integration Test — K8s (k3d) (push) Has been skipped
Update BugFix Tofu Validate
2026-03-13 20:28:42 +01:00

190 lines
6.2 KiB
HCL

terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 3.9"
}
}
}
locals {
persistent = var.environment == "prod"
# Inject oauth2 token into git URL for private repos
git_repo_url = (
var.openresty_git_token != ""
? replace(var.openresty_git_repo, "://", "://oauth2:${var.openresty_git_token}@")
: var.openresty_git_repo
)
# Entrypoint for git_clone mode: installs git via apk, clones the pinned ref,
# then hands off to openresty. The cloned repo must have an 'openresty/' subdirectory
# containing a valid nginx.conf (used as the -p prefix path).
git_clone_entrypoint = [
"/bin/sh", "-c",
"apk add --no-cache git && git clone --depth 1 --branch '${var.openresty_git_ref}' '${local.git_repo_url}' /tmp/app && exec openresty -g 'daemon off;' -p /tmp/app/openresty"
]
}
# ─── Network ──────────────────────────────────────────────────────────────────
# Each app gets its own isolated bridge network. Postgres and Redis are not
# exposed externally; only OpenResty has a published port.
resource "docker_network" "app" {
name = "${var.app_name}-network"
driver = "bridge"
}
# ─── Volumes (prod only) ──────────────────────────────────────────────────────
# In dev mode containers are ephemeral; volumes are created only for prod.
resource "docker_volume" "postgres" {
count = local.persistent ? 1 : 0
name = "${var.app_name}-postgres-data"
}
resource "docker_volume" "redis" {
count = local.persistent ? 1 : 0
name = "${var.app_name}-redis-data"
}
# ─── Images ───────────────────────────────────────────────────────────────────
# Standard OpenResty image — used for bind_mount and git_clone modes.
resource "docker_image" "openresty" {
count = var.openresty_source_type != "local_build" ? 1 : 0
name = var.openresty_image
keep_locally = true
}
# Custom-built OpenResty image — used for local_build mode.
# The build context is transferred from the local machine to the remote Docker
# daemon over SSH and built there. Rebuilds are triggered by changes to any
# file in the context directory.
resource "docker_image" "openresty_custom" {
count = var.openresty_source_type == "local_build" ? 1 : 0
name = "${var.app_name}-openresty:latest"
keep_locally = true
build {
context = var.openresty_local_build_context
dockerfile = var.openresty_dockerfile
}
triggers = {
# Rebuild when any file in the build context changes.
context_hash = sha1(join("", [
for f in sort(fileset(var.openresty_local_build_context, "**/*")) :
filesha1("${var.openresty_local_build_context}/${f}")
]))
}
}
resource "docker_image" "postgres" {
name = var.postgres_image
keep_locally = true
}
resource "docker_image" "redis" {
name = var.redis_image
keep_locally = true
}
# ─── PostgreSQL ───────────────────────────────────────────────────────────────
resource "docker_container" "postgres" {
image = docker_image.postgres.image_id
name = "${var.app_name}-postgres"
restart = "unless-stopped"
networks_advanced {
name = docker_network.app.name
}
env = [
"POSTGRES_DB=${var.db_name}",
"POSTGRES_USER=${var.db_user}",
"POSTGRES_PASSWORD=${var.db_password}",
]
dynamic "volumes" {
for_each = local.persistent ? [1] : []
content {
volume_name = docker_volume.postgres[0].name
container_path = "/var/lib/postgresql/data"
}
}
}
# ─── Redis ────────────────────────────────────────────────────────────────────
resource "docker_container" "redis" {
image = docker_image.redis.image_id
name = "${var.app_name}-redis"
restart = "unless-stopped"
networks_advanced {
name = docker_network.app.name
}
dynamic "volumes" {
for_each = local.persistent ? [1] : []
content {
volume_name = docker_volume.redis[0].name
container_path = "/data"
}
}
}
# ─── OpenResty ────────────────────────────────────────────────────────────────
resource "docker_container" "openresty" {
image = (
var.openresty_source_type == "local_build"
? docker_image.openresty_custom[0].image_id
: docker_image.openresty[0].image_id
)
name = "${var.app_name}-openresty"
restart = "unless-stopped"
networks_advanced {
name = docker_network.app.name
}
ports {
internal = 80
external = var.openresty_external_port
}
# bind_mount: mount a pre-existing directory from the remote host.
# The directory must contain a valid nginx.conf and any Lua files.
dynamic "volumes" {
for_each = var.openresty_source_type == "bind_mount" ? [1] : []
content {
host_path = var.openresty_remote_config_path
container_path = "/usr/local/openresty/nginx/conf"
read_only = true
}
}
# git_clone: override the container entrypoint to clone the repo and start openresty.
# The base image must support apk (Alpine). The cloned repo must have an openresty/
# subdirectory with nginx.conf.
entrypoint = var.openresty_source_type == "git_clone" ? local.git_clone_entrypoint : null
# Expose service connection info as env vars so Lua code can use them via os.getenv().
env = [
"APP_NAME=${var.app_name}",
"POSTGRES_HOST=${var.app_name}-postgres",
"POSTGRES_DB=${var.db_name}",
"POSTGRES_USER=${var.db_user}",
"POSTGRES_PASSWORD=${var.db_password}",
"REDIS_HOST=${var.app_name}-redis",
]
depends_on = [
docker_container.postgres,
docker_container.redis,
]
}