// Generic Docker service module // Creates and manages a Docker container with configurable options module "system_globals" { source = "../../00-globals/system" } terraform { required_providers { docker = { source = "kreuzwerker/docker" } dotenv = { source = "germanbrew/dotenv" } } } locals { network_mode = var.network_mode container_name = var.container_name image_name = "${var.image}:${var.tag}" default_env_vars = { TZ = module.system_globals.timezone PUID = var.puid != null ? var.puid : module.system_globals.puid PGID = var.pgid != null ? var.pgid : module.system_globals.pgid } env_vars = merge(var.env_vars, local.default_env_vars) // Prepare ports configuration ports_config = [ for port in var.ports : { internal = port.internal external = port.external protocol = port.protocol } ] // Prepare volumes configuration volumes_config = [ for volume in var.volumes : { host_path = volume.host_path container_path = volume.container_path read_only = volume.read_only } ] // Define monitoring labels if enabled monitoring_labels = var.monitoring ? { "com.centurylinklabs.watchtower.enable" = "true" } : {} // Merge provided labels with monitoring labels merged_labels = merge(var.labels, local.monitoring_labels) } // Pull the Docker image resource "docker_image" "service_image" { name = local.image_name keep_locally = var.keep_image_locally pull_triggers = [var.tag] } // Create the Docker container resource "docker_container" "service_container" { name = local.container_name image = docker_image.service_image.image_id restart = var.restart_policy # Set the network mode (bridge, host, etc.) network_mode = local.network_mode # Add host mappings (entries for /etc/hosts) dynamic "host" { for_each = var.host_mappings content { host = host.value.host ip = host.value.ip } } # Dynamically configure ports based on the provided list dynamic "ports" { for_each = local.ports_config content { internal = ports.value.internal external = ports.value.external protocol = ports.value.protocol } } # Dynamically configure networks based on the provided list dynamic "networks_advanced" { for_each = var.networks content { name = networks_advanced.value } } # Dynamically configure volumes based on the provided list dynamic "volumes" { for_each = local.volumes_config content { host_path = volumes.value.host_path container_path = volumes.value.container_path read_only = volumes.value.read_only } } # Configure environment variables - map to array of strings env = [for k, v in local.env_vars : "${k}=${v}"] # Set container labels dynamic "labels" { for_each = local.merged_labels content { label = labels.key value = labels.value } } # Add container healthcheck if configured dynamic "healthcheck" { for_each = var.healthcheck != null ? [var.healthcheck] : [] content { test = healthcheck.value.test interval = healthcheck.value.interval timeout = healthcheck.value.timeout start_period = healthcheck.value.start_period retries = healthcheck.value.retries } } # Set resource limits if specified memory = var.memory_limit memory_swap = var.memory_swap_limit cpu_shares = var.cpu_shares # Other container options dns = var.dns dns_search = var.dns_search hostname = var.hostname domainname = var.domainname user = var.user group_add = var.group_add working_dir = var.working_dir command = var.command entrypoint = var.entrypoint privileged = var.privileged destroy_grace_seconds = var.destroy_grace_seconds # Linux capabilities controls dynamic "capabilities" { for_each = length(var.capabilities_add) > 0 || length(var.capabilities_drop) > 0 ? [1] : [] content { add = var.capabilities_add drop = var.capabilities_drop } } # Device mappings dynamic "devices" { for_each = var.devices content { host_path = devices.value.host_path container_path = devices.value.container_path permissions = devices.value.permissions } } # Set log options log_driver = var.log_driver log_opts = var.log_opts }