Files
shopdb-flask/docker-compose.prebuilt.yml
Proudlock 0b252db7d2 Apply migrate service pattern to docker-compose.prebuilt.yml
Brings docker-compose.prebuilt.yml in line with the migrate service
refactor from wilm (commit 58a3670529). Migrations, plugin bootstrap,
and seeds now run in a dedicated service with restart: "no" so failures
block deployment instead of crash-looping.

Changes:
- Add dedicated migrate service (runs db upgrade, bootstrap, seeds)
- API now depends on migrate: service_completed_successfully
- Database bound to 127.0.0.1:3306 (not 0.0.0.0) for security
- UTF-8 charset enforced server-wide
- Healthcheck uses TCP not socket (prevents false-healthy during init)

Testing:
- Verified migrations are idempotent (safe to re-run)
- Verified failed migration blocks API startup (fail-closed)
- Verified startup sequence: db -> migrate -> api (44s)
- Database at schema version 7d51_endpoint_logcollections (head)

Aligns dev environment with pull/airgap deployment pattern.
2026-09-11 12:43:02 -04:00

113 lines
3.1 KiB
YAML

# Docker Compose using pre-built frontend
# Build frontend on host first: cd frontend && npm run build
# Then: docker compose -f docker-compose.prebuilt.yml build
services:
db:
image: mysql:8.4
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
ports:
- "127.0.0.1:3306:3306"
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: shopdb_flask
MYSQL_USER: shopdb
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 10s
timeout: 5s
retries: 5
restart: unless-stopped
# Schema, plugin bootstrap and seed data - runs once before API starts
migrate:
build:
context: .
dockerfile: Dockerfile.prebuilt
restart: "no"
depends_on:
db:
condition: service_healthy
environment:
- FLASK_ENV=${FLASK_ENV:-production}
- DATABASE_URL=mysql+pymysql://shopdb:${MYSQL_PASSWORD}@db:3306/shopdb_flask?charset=utf8mb4
- SECRET_KEY=${SECRET_KEY}
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
- CORS_ORIGINS=${CORS_ORIGINS}
- LOG_LEVEL=${LOG_LEVEL:-INFO}
command:
- sh
- -c
- >
flask db upgrade &&
/app/scripts/bootstrap-plugins.sh &&
flask plugin upgrade-all &&
flask seed permissions &&
flask seed settings &&
flask seed reference-data
volumes:
- ./plugins:/app/plugins:ro
- ./scripts:/app/scripts:ro
- instance_data:/app/instance
api:
build:
context: .
dockerfile: Dockerfile.prebuilt
ports:
- "${API_PORT:-5001}:5001"
environment:
- DATABASE_URL=mysql+pymysql://shopdb:${MYSQL_PASSWORD}@db:3306/shopdb_flask
- SECRET_KEY=${SECRET_KEY}
- JWT_SECRET_KEY=${JWT_SECRET_KEY}
- FLASK_ENV=${FLASK_ENV:-production}
- FLASK_DEBUG=${FLASK_DEBUG:-0}
- CORS_ORIGINS=${CORS_ORIGINS}
- SHOPDB_ENV_LABEL=${SHOPDB_ENV_LABEL}
- LOG_LEVEL=${LOG_LEVEL:-INFO}
- ZABBIX_URL=${ZABBIX_URL:-}
- ZABBIX_TOKEN=${ZABBIX_TOKEN:-}
- COLLECTOR_API_KEY=${COLLECTOR_API_KEY:-}
- COLLECTOR_API_KEY_ENDPOINTS=${COLLECTOR_API_KEY_ENDPOINTS:-}
volumes:
- instance_data:/app/instance
- ./plugins:/app/plugins:ro
- ./scripts:/app/scripts:ro
- ./certs:/app/certs:ro
depends_on:
db:
condition: service_healthy
migrate:
condition: service_completed_successfully
restart: unless-stopped
command:
- gunicorn
- --bind
- 0.0.0.0:5001
- --worker-class
- gevent
- --workers
- "4"
- --worker-connections
- "2000"
- --timeout
- "60"
- --access-logfile
- "-"
- --access-logformat
- '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s %(D)sus "%(f)s" "%(a)s"'
- --error-logfile
- "-"
- --certfile
- /app/certs/server.crt
- --keyfile
- /app/certs/server.key
- wsgi:app
volumes:
db_data:
instance_data: