Opinionated.tf/docker/service/service.tf

230 lines
6.6 KiB
Terraform
Raw Permalink Normal View History

2024-07-29 19:28:08 +00:00
resource "docker_service" "instance" {
# The name of the service is the stack name and the service name combined
2024-11-23 04:06:26 +00:00
name = local.service_name
2024-07-29 19:28:08 +00:00
#depends_on = [terraform_data.conditional_build_hack["build"]]
2024-07-29 19:28:08 +00:00
# Define the task spec
task_spec {
container_spec {
2024-12-10 01:02:22 +00:00
image = local.image_fully_qualified
2024-07-29 19:28:08 +00:00
command = var.command
env = var.environment_variables
2025-02-14 20:33:15 +00:00
# Mount the shm if needed
dynamic "mounts" {
for_each = docker_volume.shm
content {
source = docker_volume.shm[mounts.key].id
target = "/dev/shm"
type = "tmpfs"
tmpfs_options {
size_bytes = local.shm_bytes
}
read_only = false
}
}
2024-07-29 19:28:08 +00:00
# Mount all the created volumes
dynamic "mounts" {
for_each = var.volumes
content {
2024-11-26 09:50:53 +00:00
source = docker_volume.volume[mounts.key].id
target = mounts.value
type = "volume"
read_only = false # Nice assumption bro.
2024-07-29 19:28:08 +00:00
}
}
2024-11-23 04:06:26 +00:00
# Mount all the volumes being remotely attached to the container
dynamic "mounts" {
for_each = var.remote_volumes
content {
2024-11-26 09:50:53 +00:00
source = mounts.value.id
target = mounts.key
type = "volume"
read_only = false # Nice assumption bro.
}
}
2024-11-23 04:06:26 +00:00
# Iterate through "mounts" to bind host paths to container paths
2024-07-31 12:26:17 +00:00
dynamic "mounts" {
for_each = var.mounts
content {
2024-11-24 09:50:28 +00:00
source = mounts.key
2024-11-26 09:50:53 +00:00
target = mounts.value
2024-11-24 09:50:28 +00:00
type = "bind"
read_only = false # Nice assumption bro.
2024-07-31 12:26:17 +00:00
}
}
2024-11-23 04:06:26 +00:00
# Iterate through configs and attach the docker configs
2024-07-31 12:26:17 +00:00
dynamic "configs" {
for_each = var.configs
content {
2024-11-23 04:06:26 +00:00
config_id = module.config[configs.key].id
config_name = module.config[configs.key].name
2024-11-26 09:50:53 +00:00
file_name = configs.key
2024-07-31 12:26:17 +00:00
}
}
2025-01-06 09:45:37 +00:00
dynamic "configs" {
for_each = var.remote_configs
content {
config_id = configs.value.id
config_name = configs.value.name
file_name = configs.key
}
}
2025-02-14 20:31:35 +00:00
# Same for secrets
dynamic "secrets" {
for_each = var.secrets
content {
secret_id = module.secrets[secrets.key].id
secret_name = module.secrets[secrets.key].name
file_name = secrets.key
}
}
2024-07-29 19:28:08 +00:00
# Allow overriding DNS server in use
dynamic "dns_config" {
for_each = var.dns_nameservers != null ? [{}] : []
content {
nameservers = var.dns_nameservers
}
}
2024-11-23 04:06:26 +00:00
# Apply the healthcheck settings
healthcheck {
test = var.healthcheck != null ? var.healthcheck : []
2024-12-22 06:42:50 +00:00
interval = var.healthcheck != null ? var.healthcheck_interval : "0s"
timeout = var.healthcheck != null ? var.healthcheck_timeout : "0s"
retries = var.healthcheck_retries
start_period = var.healthcheck_start_period
2024-07-29 19:28:08 +00:00
}
2024-08-29 11:49:03 +00:00
2024-11-23 04:06:26 +00:00
# Apply the list of Container Labels
2024-08-29 11:49:03 +00:00
dynamic "labels" {
2024-12-05 18:10:16 +00:00
# Filter out null values
2025-01-16 18:38:54 +00:00
for_each = local.merged_labels
2024-08-29 11:49:03 +00:00
content {
label = labels.key
value = labels.value
}
}
2024-07-29 19:28:08 +00:00
}
# Apply the networks
dynamic "networks_advanced" {
2025-01-06 09:45:37 +00:00
for_each = local.networks
2024-07-29 19:28:08 +00:00
content {
2024-11-26 09:50:53 +00:00
name = networks_advanced.value.id
2024-07-29 19:28:08 +00:00
}
}
2024-07-30 02:08:50 +00:00
# Apply restart policy
2024-07-29 19:28:08 +00:00
restart_policy {
2024-11-23 04:06:26 +00:00
condition = var.one_shot ? "none" : var.restart_policy
2024-11-26 09:50:53 +00:00
delay = var.restart_delay
2024-07-29 19:28:08 +00:00
window = "0s"
max_attempts = 0
}
2024-11-26 09:50:53 +00:00
# Apply the placement constraints
2024-07-29 19:28:08 +00:00
placement {
2024-11-26 09:50:53 +00:00
max_replicas = var.parallelism_per_node
constraints = var.placement_constraints
2025-05-03 00:20:41 +00:00
dynamic "platforms" {
for_each = var.processor_architecture != null && var.operating_system != null ? [{}] : []
content {
architecture = var.processor_architecture
os = var.operating_system
}
2024-07-29 19:28:08 +00:00
}
}
2024-11-26 09:50:53 +00:00
# Apply the resource limits and reservations
resources {
limits {
memory_bytes = var.limit_ram_mb != null ? 1024 * 1024 * var.limit_ram_mb : 0
nano_cpus = var.limit_cpu != null ? (1000000000 / 100) * var.limit_cpu : 0
}
reservation {
memory_bytes = var.reserved_ram_mb != null ? 1024 * 1024 * var.reserved_ram_mb : 0
nano_cpus = var.reserved_cpu != null ? (1000000000 / 100) * var.reserved_cpu : 0
}
}
2024-07-29 19:28:08 +00:00
}
# Global deploy
dynamic "mode" {
for_each = var.global ? [{}] : []
content {
global = true
}
}
# Or replicated deploy
dynamic "mode" {
for_each = !var.global ? [{}] : []
content {
replicated {
2025-01-21 19:12:09 +00:00
replicas = var.enable ? var.parallelism : 0
2024-07-29 19:28:08 +00:00
}
}
}
2024-11-23 04:06:26 +00:00
# Behaviour regarding startup and delaying/waiting.
# Converging is not possible when:
# * in global deploy mode
# * in one-shot mode
# * converging is disabled
# * the service does not have a well-defined healthcheck, maybe you should add one to the service, or to the container itself ideally.
2024-07-29 19:28:08 +00:00
dynamic "converge_config" {
2024-11-23 04:06:26 +00:00
for_each = var.converge_enable && !var.global && !var.one_shot ? [{}] : []
2024-07-29 19:28:08 +00:00
content {
delay = "5s"
2024-09-23 21:45:34 +00:00
timeout = var.converge_timeout
2024-07-29 19:28:08 +00:00
}
}
# How to handle updates/re-deployments
update_config {
# Parallelism must be the size of the count of instances, divided by the number of update waves
# with a minimum of 1.
# Confusingly, the max() function gives you the largest number of the two, so if the parallelism is 0, 1 will be greater.
2024-08-01 17:12:28 +00:00
parallelism = max(1, ceil(var.parallelism / var.update_waves))
# The order of stopping and starting containers.
# Some containers can be run while the previous is still running (e.g web servers, anything ephemeral)
# Some cannot have more than 1 instance running at the same time (e.g databases, anything concrete)
2024-08-01 17:12:28 +00:00
order = var.start_first ? "start-first" : "stop-first"
2024-07-29 19:28:08 +00:00
}
# Ports and such
endpoint_spec {
dynamic "ports" {
for_each = var.ports
content {
2024-07-31 14:13:06 +00:00
target_port = ports.value.container
published_port = ports.value.host
protocol = ports.value.protocol
publish_mode = ports.value.publish_mode
2024-07-29 19:28:08 +00:00
}
}
}
# Service Labels
2024-11-23 04:06:26 +00:00
dynamic "labels" {
2025-01-16 18:38:54 +00:00
for_each = local.merged_labels
2024-11-23 04:06:26 +00:00
content {
label = labels.key
value = labels.value
}
2024-07-31 12:26:17 +00:00
}
lifecycle {
# Help prevent "this service already exists" irritations
create_before_destroy = false
#replace_triggered_by = [terraform_data.conditional_build_hack["build"]]
}
2024-07-31 12:26:17 +00:00
}