DealDocumentScreening/deploy/nomad/contract-check.nomad.hcl
febux a264b20c1c
Some checks failed
ci / Lint & typecheck (push) Successful in 29s
ci / Unit tests (push) Successful in 1m4s
deploy / build-and-deploy (push) Failing after 46s
nomad job: bind-mount compose .env (simpler than nomadVar templates);
enable docker volumes
2026-09-14 02:53:56 +03:00

392 lines
9.3 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. A sed one-liner rewrites compose hostnames (postgres, redis,
# rabbitmq, minio) to 172.17.0.1 + published ports so the connections work
# from outside the compose network.
#
# 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"
readonly = 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",
<<-SH
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
SH
]
ports = ["http"]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
readonly = 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",
<<-SH
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
SH
]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
readonly = 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",
<<-SH
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
SH
]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
readonly = 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",
<<-SH
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
SH
]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
readonly = 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",
<<-SH
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
SH
]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
readonly = 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",
<<-SH
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
SH
]
mounts = [
{
type = "bind"
target = "/secrets/.env"
source = "/root/DealDocumentScreening/.env"
readonly = true
},
]
}
kill_timeout = "60s"
resources {
cpu = 150
memory = 256
}
}
}
}