Files
Simulators/docker-compose.yml
inecs a3ce2d473c Add self-contained API simulators lab with Compose and Helm.
Ship Proxmox, oVirt, VMware, and OpenStack behind one Postgres stack,
Makefile helpers (up/clean/helm up|down/push), and a Helm chart with
namespace, Let's Encrypt ingresses, migrate inits, and skip-if-seeded jobs.
2026-07-18 11:52:33 +03:00

352 lines
10 KiB
YAML

# Self-contained lab stack: Proxmox + oVirt + VMware + OpenStack
# One PostgreSQL, four databases. No sibling source trees required.
#
# cd /Users/inecs/Разработка/simulators
# docker compose pull
# docker compose up -d
#
# Override tags: IMAGE_TAG=0.1.0 docker compose up -d
#
# Laboratory only — default passwords / TICKET_SIGNING_KEY are intentional.
name: api-simulators-lab
x-ticket: &ticket
TICKET_SIGNING_KEY: ${TICKET_SIGNING_KEY:-development-only-signing-key-change-me}
LOG_LEVEL: ${LOG_LEVEL:-INFO}
networks:
lab:
proxmox_net:
ovirt_net:
vmware_net:
openstack_net:
volumes:
postgres-data:
services:
postgres:
image: postgres:17.5-bookworm
restart: unless-stopped
networks: [lab, proxmox_net, ovirt_net, vmware_net, openstack_net]
environment:
POSTGRES_USER: lab
POSTGRES_PASSWORD: lab
POSTGRES_DB: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready -U lab -d postgres"]
interval: 5s
timeout: 3s
retries: 12
start_period: 5s
volumes:
- postgres-data:/var/lib/postgresql/data
- ./docker/postgres-init:/docker-entrypoint-initdb.d:ro
ports:
- "127.0.0.1:5432:5432"
# ── Proxmox VE API ──────────────────────────────────────
proxmox-migrate:
profiles: [init]
image: inecs/proxmox-api-simulator:${IMAGE_TAG:-latest}
networks: [proxmox_net]
environment:
<<: *ticket
DATABASE_URL: postgresql://proxmox:proxmox@postgres:5432/proxmox_simulator
CONTRACT_SNAPSHOT: /app/contracts/pve-9.2.3.json
COMPATIBILITY_EVIDENCE: /app/evidence/pve-9.2.3.json
depends_on:
postgres: { condition: service_healthy }
entrypoint: ["python"]
command: ["-m", "app.db.migrate_cli"]
restart: "no"
proxmox:
image: inecs/proxmox-api-simulator:${IMAGE_TAG:-latest}
restart: unless-stopped
networks: [proxmox_net]
environment:
<<: *ticket
DATABASE_URL: postgresql://proxmox:proxmox@postgres:5432/proxmox_simulator
CONTRACT_SNAPSHOT: /app/contracts/pve-9.2.3.json
COMPATIBILITY_EVIDENCE: /app/evidence/pve-9.2.3.json
TASK_WORKER_CONCURRENCY: "2"
SIMULATION_TIME_SCALE: "10"
depends_on:
postgres: { condition: service_healthy }
healthcheck:
test:
[
"CMD",
"python",
"-c",
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8006/health/ready', timeout=2)",
]
interval: 10s
timeout: 3s
retries: 10
start_period: 25s
ports:
- "8006:8006"
proxmox-seed:
profiles: [init]
image: inecs/proxmox-api-simulator:${IMAGE_TAG:-latest}
networks: [proxmox_net]
environment:
<<: *ticket
DATABASE_URL: postgresql://proxmox:proxmox@postgres:5432/proxmox_simulator
SEED_PROFILE: ${PROXMOX_SEED_PROFILE:-small}
depends_on:
proxmox: { condition: service_healthy }
entrypoint: ["python"]
command: ["-m", "app.simulation.seed_cli"]
restart: "no"
# ── oVirt Engine API ────────────────────────────────────
ovirt-migrate:
profiles: [init]
image: inecs/ovirt-api-simulator:${IMAGE_TAG:-latest}
networks: [ovirt_net]
environment:
<<: *ticket
DATABASE_URL: postgresql://ovirt:ovirt@postgres:5432/ovirt_simulator
OVIRT_SERIES: ${OVIRT_SERIES:-4.5}
depends_on:
postgres: { condition: service_healthy }
entrypoint: ["python"]
command: ["-m", "app.db.migrate_cli"]
restart: "no"
ovirt:
image: inecs/ovirt-api-simulator:${IMAGE_TAG:-latest}
restart: unless-stopped
networks:
ovirt_net:
aliases: [simulator]
environment:
<<: *ticket
DATABASE_URL: postgresql://ovirt:ovirt@postgres:5432/ovirt_simulator
OVIRT_SERIES: ${OVIRT_SERIES:-4.5}
APP_PORT: "8080"
depends_on:
postgres: { condition: service_healthy }
healthcheck:
test:
[
"CMD",
"python",
"-c",
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/health/ready', timeout=2)",
]
interval: 10s
timeout: 3s
retries: 10
start_period: 30s
expose:
- "8080"
ovirt-gateway:
image: nginx:1.28.0-alpine
restart: unless-stopped
networks: [ovirt_net]
depends_on:
ovirt: { condition: service_healthy }
ports:
- "7443:443"
- "7500:5000"
volumes:
- ./docker/ovirt/ovirt-engine.conf:/etc/nginx/conf.d/default.conf:ro
- ./docker/tls/server.crt:/etc/nginx/tls/server.crt:ro
- ./docker/tls/server.key:/etc/nginx/tls/server.key:ro
read_only: true
tmpfs: [/var/cache/nginx, /var/run, /tmp]
security_opt: [no-new-privileges:true]
ovirt-seed:
profiles: [init]
image: inecs/ovirt-api-simulator:${IMAGE_TAG:-latest}
networks: [ovirt_net]
environment:
<<: *ticket
DATABASE_URL: postgresql://ovirt:ovirt@postgres:5432/ovirt_simulator
OVIRT_SERIES: ${OVIRT_SERIES:-4.5}
depends_on:
ovirt: { condition: service_healthy }
entrypoint: ["python"]
command: ["-m", "app.ovirt.seed_cli", "--profile", "${OVIRT_SEED_PROFILE:-minimal}"]
restart: "no"
# ── VMware vSphere API ──────────────────────────────────
vmware-migrate:
profiles: [init]
image: inecs/vmware-api-simulator:${IMAGE_TAG:-latest}
networks: [vmware_net]
environment:
<<: *ticket
DATABASE_URL: postgresql://vmware:vmware@postgres:5432/vmware_simulator
ENABLE_PVE_STUB: "false"
APP_PORT: "8080"
depends_on:
postgres: { condition: service_healthy }
entrypoint: ["python"]
command: ["-m", "app.db.migrate_cli"]
restart: "no"
vmware:
image: inecs/vmware-api-simulator:${IMAGE_TAG:-latest}
restart: unless-stopped
networks:
vmware_net:
aliases: [simulator]
environment:
<<: *ticket
DATABASE_URL: postgresql://vmware:vmware@postgres:5432/vmware_simulator
ENABLE_PVE_STUB: "false"
SEED_VSPHERE_PROFILE: ${VMWARE_SEED_PROFILE:-small}
APP_PORT: "8080"
TASK_WORKER_CONCURRENCY: "2"
SIMULATION_TIME_SCALE: "10"
depends_on:
postgres: { condition: service_healthy }
healthcheck:
test:
[
"CMD",
"python",
"-c",
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/health/ready', timeout=2)",
]
interval: 10s
timeout: 3s
retries: 10
start_period: 25s
expose:
- "8080"
vmware-gateway:
image: nginx:1.28.0-alpine
restart: unless-stopped
networks: [vmware_net]
depends_on:
vmware: { condition: service_healthy }
ports:
- "8081:80"
- "8443:443"
volumes:
- ./docker/vmware/vmware-ports.conf:/etc/nginx/conf.d/default.conf:ro
- ./docker/tls/server.crt:/etc/nginx/tls/server.crt:ro
- ./docker/tls/server.key:/etc/nginx/tls/server.key:ro
read_only: true
tmpfs: [/var/cache/nginx, /var/run, /tmp]
security_opt: [no-new-privileges:true]
vmware-seed:
profiles: [init]
image: inecs/vmware-api-simulator:${IMAGE_TAG:-latest}
networks: [vmware_net]
environment:
<<: *ticket
DATABASE_URL: postgresql://vmware:vmware@postgres:5432/vmware_simulator
ENABLE_PVE_STUB: "false"
SEED_PROFILE: ${VMWARE_SEED_PROFILE:-small}
SEED_VSPHERE_PROFILE: ${VMWARE_SEED_PROFILE:-small}
depends_on:
vmware: { condition: service_healthy }
entrypoint: ["python"]
command: ["-m", "app.simulation.seed_cli"]
restart: "no"
# ── OpenStack API ───────────────────────────────────────
openstack-migrate:
profiles: [init]
image: inecs/openstack-api-simulator:${IMAGE_TAG:-latest}
networks: [openstack_net]
environment:
<<: *ticket
DATABASE_URL: postgresql://openstack:openstack@postgres:5432/openstack_simulator
APP_PORT: "8080"
depends_on:
postgres: { condition: service_healthy }
entrypoint: ["python"]
command: ["-m", "app.db.migrate_cli"]
restart: "no"
openstack:
image: inecs/openstack-api-simulator:${IMAGE_TAG:-latest}
restart: unless-stopped
networks:
openstack_net:
aliases: [simulator]
environment:
<<: *ticket
DATABASE_URL: postgresql://openstack:openstack@postgres:5432/openstack_simulator
APP_PORT: "8080"
TASK_WORKER_CONCURRENCY: "2"
SIMULATION_TIME_SCALE: "10"
depends_on:
postgres: { condition: service_healthy }
healthcheck:
test:
[
"CMD",
"python",
"-c",
"import urllib.request; urllib.request.urlopen('http://127.0.0.1:8080/health/ready', timeout=2)",
]
interval: 10s
timeout: 3s
retries: 10
start_period: 25s
expose:
- "8080"
openstack-gateway:
image: nginx:1.28.0-alpine
restart: unless-stopped
networks: [openstack_net]
depends_on:
openstack: { condition: service_healthy }
ports:
- "9080:80"
- "9443:443"
- "9500:5000"
- "5050:5050"
- "6385:6385"
- "8000:8000"
- "8003:8003"
- "8004:8004"
- "8042:8042"
- "8080:8080"
- "8774:8774"
- "8776:8776"
- "8779:8779"
- "8786:8786"
- "8989:8989"
- "9001:9001"
- "9090:9090"
- "9292:9292"
- "9696:9696"
- "9876:9876"
volumes:
- ./docker/openstack/openstack-ports.conf:/etc/nginx/conf.d/default.conf:ro
- ./docker/tls/server.crt:/etc/nginx/tls/server.crt:ro
- ./docker/tls/server.key:/etc/nginx/tls/server.key:ro
read_only: true
tmpfs: [/var/cache/nginx, /var/run, /tmp]
security_opt: [no-new-privileges:true]
openstack-seed:
profiles: [init]
image: inecs/openstack-api-simulator:${IMAGE_TAG:-latest}
networks: [openstack_net]
environment:
<<: *ticket
DATABASE_URL: postgresql://openstack:openstack@postgres:5432/openstack_simulator
depends_on:
openstack: { condition: service_healthy }
entrypoint: ["python"]
command: ["-m", "app.openstack.seed_cli", "--profile", "${OPENSTACK_SEED_PROFILE:-minimal}"]
restart: "no"