DealDocumentScreening/deploy/nomad/contract-check.nomad.hcl
febux b0a07cac53
Some checks failed
ci / Lint & typecheck (push) Successful in 30s
ci / Unit tests (push) Successful in 1m6s
deploy / build-and-deploy (push) Failing after 1m16s
Update contract-check.nomad.hcl
2026-09-14 02:59:48 +03:00

330 lines
8.6 KiB
HCL

# «Контракт-чек» app services on Nomad (single VPS, docker driver).
#
# Groups: api (with prestart migrations) + 5 workers. Stateful infra
# (postgres/redis/rabbitmq/minio) stays on compose; tasks reach it via the
# docker0 host gateway 172.17.0.1 and the host-published ports
# (15432/17379/5672/9000). The nginx edge cascade is unchanged.
#
# Env: the compose .env file (~/DealDocumentScreening/.env on the VPS) is
# bind-mounted into every container at /secrets/.env and sourced before the
# app starts. Shell parameter substitution rewrites compose hostnames
# (postgres, redis, rabbitmq, minio) to 172.17.0.1 + published ports.
#
# Image tag uses ${IMAGE_TAG}, rendered by envsubst at submit time.
# Registry auth: host-level `docker login` on the VPS (README §5).
job "contract-check" {
datacenters = ["vps"]
type = "service"
update {
max_parallel = 1
min_healthy_time = "15s"
healthy_deadline = "5m"
progress_deadline = "10m"
auto_revert = true
}
# ══ API ════════════════════════════════════════════════════════════════════
group "api" {
count = 1
update {
max_parallel = 1
}
restart {
attempts = 3
interval = "10m"
delay = "15s"
mode = "delay"
}
network {
port "http" {
static = 18000
to = 8000
}
}
service {
name = "contract-check-api"
port = "http"
provider = "nomad"
check {
name = "healthz"
type = "http"
path = "/healthz"
interval = "10s"
timeout = "3s"
}
check_restart {
limit = 3
grace = "30s"
}
}
# One-shot migrations before the API starts.
task "migrate" {
lifecycle {
hook = "prestart"
}
driver = "docker"
config {
image = "p2gnl.mu-dungeon.xyz/admin-git/contract-check-api:${IMAGE_TAG}"
command = "sh"
args = ["-c", "set -a; . /secrets/.env; set +a; exec alembic upgrade head"]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
read_only = true
},
]
}
resources {
cpu = 150
memory = 256
}
}
task "api" {
driver = "docker"
config {
image = "p2gnl.mu-dungeon.xyz/admin-git/contract-check-api:${IMAGE_TAG}"
command = "sh"
args = ["-c", "set -a; . /secrets/.env; set +a; export DATABASE_URL=$${DATABASE_URL/@postgres:/@172.17.0.1:15432:}; export REDIS_URL=$${REDIS_URL/@redis:/@172.17.0.1:17379:}; export RABBITMQ_URL=$${RABBITMQ_URL/@rabbitmq:/@172.17.0.1:5672:}; export S3_ENDPOINT_URL=http://172.17.0.1:9000; export APP_VERSION=${IMAGE_TAG}; exec python -m src.contract_check.api"]
ports = ["http"]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
read_only = true
},
]
}
kill_timeout = "30s"
resources {
cpu = 300
memory = 512
}
}
}
# ══ WORKERS ═══════════════════════════════════════════════════════════════
group "worker-extract" {
count = 1
update {
canary = 1
auto_promote = true
}
restart {
attempts = 3
interval = "10m"
delay = "15s"
mode = "delay"
}
task "worker-extract" {
driver = "docker"
config {
image = "p2gnl.mu-dungeon.xyz/admin-git/contract-check-worker-extract:${IMAGE_TAG}"
command = "sh"
args = ["-c", "set -a; . /secrets/.env; set +a; export DATABASE_URL=$${DATABASE_URL/@postgres:/@172.17.0.1:15432:}; export RABBITMQ_URL=$${RABBITMQ_URL/@rabbitmq:/@172.17.0.1:5672:}; export S3_ENDPOINT_URL=http://172.17.0.1:9000; export APP_VERSION=${IMAGE_TAG}; exec python -m src.contract_check.worker_extract"]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
read_only = true
},
]
}
kill_timeout = "60s"
resources {
cpu = 500
memory = 640
}
}
}
group "worker-analyze" {
count = 1
update {
canary = 1
auto_promote = true
}
restart {
attempts = 3
interval = "10m"
delay = "15s"
mode = "delay"
}
task "worker-analyze" {
driver = "docker"
config {
image = "p2gnl.mu-dungeon.xyz/admin-git/contract-check-worker-analyze:${IMAGE_TAG}"
command = "sh"
args = ["-c", "set -a; . /secrets/.env; set +a; export DATABASE_URL=$${DATABASE_URL/@postgres:/@172.17.0.1:15432:}; export RABBITMQ_URL=$${RABBITMQ_URL/@rabbitmq:/@172.17.0.1:5672:}; export S3_ENDPOINT_URL=http://172.17.0.1:9000; export APP_VERSION=${IMAGE_TAG}; exec python -m src.contract_check.worker_analyze"]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
read_only = true
},
]
}
kill_timeout = "120s"
resources {
cpu = 250
memory = 384
}
}
}
group "worker-prescreen" {
count = 1
update {
canary = 1
auto_promote = true
}
restart {
attempts = 3
interval = "10m"
delay = "15s"
mode = "delay"
}
task "worker-prescreen" {
driver = "docker"
config {
image = "p2gnl.mu-dungeon.xyz/admin-git/contract-check-worker-prescreen:${IMAGE_TAG}"
command = "sh"
args = ["-c", "set -a; . /secrets/.env; set +a; export DATABASE_URL=$${DATABASE_URL/@postgres:/@172.17.0.1:15432:}; export RABBITMQ_URL=$${RABBITMQ_URL/@rabbitmq:/@172.17.0.1:5672:}; export S3_ENDPOINT_URL=http://172.17.0.1:9000; export APP_VERSION=${IMAGE_TAG}; exec python -m src.contract_check.worker_prescreen"]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
read_only = true
},
]
}
kill_timeout = "60s"
resources {
cpu = 150
memory = 256
}
}
}
group "worker-billing" {
count = 1
update {
canary = 1
auto_promote = true
}
restart {
attempts = 3
interval = "10m"
delay = "15s"
mode = "delay"
}
task "worker-billing" {
driver = "docker"
config {
image = "p2gnl.mu-dungeon.xyz/admin-git/contract-check-worker-billing:${IMAGE_TAG}"
command = "sh"
args = ["-c", "set -a; . /secrets/.env; set +a; export DATABASE_URL=$${DATABASE_URL/@postgres:/@172.17.0.1:15432:}; export APP_VERSION=${IMAGE_TAG}; exec python -m src.contract_check.worker_billing"]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
read_only = true
},
]
}
kill_timeout = "60s"
resources {
cpu = 150
memory = 256
}
}
}
group "worker-notify" {
count = 1
update {
canary = 1
auto_promote = true
}
restart {
attempts = 3
interval = "10m"
delay = "15s"
mode = "delay"
}
task "worker-notify" {
driver = "docker"
config {
image = "p2gnl.mu-dungeon.xyz/admin-git/contract-check-worker-notify:${IMAGE_TAG}"
command = "sh"
args = ["-c", "set -a; . /secrets/.env; set +a; export DATABASE_URL=$${DATABASE_URL/@postgres:/@172.17.0.1:15432:}; export RABBITMQ_URL=$${RABBITMQ_URL/@rabbitmq:/@172.17.0.1:5672:}; export APP_VERSION=${IMAGE_TAG}; exec python -m src.contract_check.worker_notify"]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
read_only = true
},
]
}
kill_timeout = "60s"
resources {
cpu = 150
memory = 256
}
}
}
}