postgres redis docker compose setup

This commit is contained in:
qananasikq
2026-04-08 22:54:51 +03:00
parent f4b9d20191
commit e5700f9623
7 changed files with 161 additions and 31 deletions

View File

@@ -14,4 +14,3 @@ coverage.xml
*.egg-info/ *.egg-info/
dist/ dist/
build/ build/
artifacts/

View File

@@ -1,15 +1,11 @@
IAAI_HEADLESS=true IAAI_HEADLESS=true
IAAI_RAW_OUTPUT_JSON=iaai_raw_network.json
IAAI_LOG_LEVEL=INFO IAAI_LOG_LEVEL=INFO
# IAAI_LOG_FILE=iaai_scraper.log # IAAI_LOG_FILE=iaai_scraper.log
# Conservative first-run mode. # Network capture settings.
IAAI_GENTLE_MODE=true
IAAI_CAPTURE_SAME_ORIGIN_ONLY=true IAAI_CAPTURE_SAME_ORIGIN_ONLY=true
IAAI_MAX_CAPTURED_REQUESTS=40 IAAI_MAX_CAPTURED_REQUESTS=40
IAAI_MAX_CAPTURED_JSON_RESPONSES=30 IAAI_MAX_CAPTURED_JSON_RESPONSES=30
IAAI_WARM_SCROLL_ROUNDS=1
IAAI_POST_OPEN_IDLE_MS=3500
# Sequential listing-first mode. # Sequential listing-first mode.
IAAI_CARS_LISTING_URL=https://www.iaai.com/Vehiclelisting/Cars IAAI_CARS_LISTING_URL=https://www.iaai.com/Vehiclelisting/Cars
@@ -34,8 +30,7 @@ IAAI_BETWEEN_VEHICLES_MAX_S=6.0
IAAI_AFTER_PAGE_CHANGE_MIN_S=3.0 IAAI_AFTER_PAGE_CHANGE_MIN_S=3.0
IAAI_AFTER_PAGE_CHANGE_MAX_S=6.0 IAAI_AFTER_PAGE_CHANGE_MAX_S=6.0
# Scheduler (default once per hour) # Sync settings
IAAI_SCHEDULER_INTERVAL_MINUTES=60
IAAI_SYNC_ONLY_NEW=true IAAI_SYNC_ONLY_NEW=true
# Retry / backoff # Retry / backoff
@@ -50,6 +45,19 @@ IAAI_RETRY_JITTER_SECONDS=0.25
# IAAI_PROXY_USERNAME= # IAAI_PROXY_USERNAME=
# IAAI_PROXY_PASSWORD= # IAAI_PROXY_PASSWORD=
# Database. # Database (PostgreSQL).
IAAI_DATABASE_URL=sqlite:///iaai_scraper.db IAAI_DATABASE_URL=postgresql+psycopg2://iaai:iaai@postgres:5432/iaai_scraper
IAAI_DATABASE_ECHO=false IAAI_DATABASE_ECHO=false
IAAI_DATABASE_POOL_SIZE=5
IAAI_DATABASE_MAX_OVERFLOW=10
# ─── Redis (Celery broker) ─────────────────────────────────
IAAI_REDIS_URL=redis://redis:6379/0
# ─── Celery ────────────────────────────────────────────────
CELERY_BROKER_URL=redis://redis:6379/0
CELERY_RESULT_BACKEND=redis://redis:6379/0
CELERY_TASK_SOFT_TIME_LIMIT=600
CELERY_TASK_TIME_LIMIT=900
CELERY_WORKER_CONCURRENCY=1
CELERY_BEAT_SYNC_INTERVAL_MINUTES=60

3
.gitignore vendored
View File

@@ -8,9 +8,10 @@ coverage.xml
*.pyd *.pyd
*.log *.log
*.db *.db
*.json
.env .env
.vscode/ .vscode/
*.egg-info/ *.egg-info/
dist/ dist/
build/ build/
artifacts/
celerybeat-schedule*

View File

@@ -17,5 +17,6 @@ RUN chmod +x entrypoint.sh
STOPSIGNAL SIGINT STOPSIGNAL SIGINT
# По умолчанию — API, но worker/beat переопределяют CMD в docker-compose
ENTRYPOINT ["./entrypoint.sh"] ENTRYPOINT ["./entrypoint.sh"]
CMD ["python", "main.py", "run-daemon"] CMD ["uvicorn", "iaai_scraper.api.app:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@@ -1,15 +1,105 @@
services: services:
iaai-scraper: # ─── PostgreSQL ───────────────────────────────────────────
postgres:
image: postgres:16-alpine
container_name: iaai-postgres
restart: unless-stopped
environment:
POSTGRES_USER: iaai
POSTGRES_PASSWORD: iaai
POSTGRES_DB: iaai_scraper
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U iaai -d iaai_scraper"]
interval: 5s
timeout: 3s
retries: 5
# ─── Redis (Celery broker) ────────────────────────────────
redis:
image: redis:7-alpine
container_name: iaai-redis
restart: unless-stopped
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
# ─── FastAPI ──────────────────────────────────────────────
api:
build: . build: .
container_name: iaai-scraper container_name: iaai-api
restart: unless-stopped
env_file: env_file:
- path: .env - path: .env
required: false required: false
volumes: environment:
- ./:/app IAAI_DATABASE_URL: postgresql+psycopg2://iaai:iaai@postgres:5432/iaai_scraper
- /app/.venv IAAI_REDIS_URL: redis://redis:6379/0
- /app/__pycache__ CELERY_BROKER_URL: redis://redis:6379/0
working_dir: /app CELERY_RESULT_BACKEND: redis://redis:6379/0
ports:
- "8000:8000"
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
command: >
uvicorn iaai_scraper.api.app:app
--host 0.0.0.0 --port 8000 --workers 2
# ─── Celery Worker ────────────────────────────────────────
worker:
build: .
container_name: iaai-worker
restart: unless-stopped restart: unless-stopped
stop_grace_period: 30s env_file:
command: python main.py run-daemon - path: .env
required: false
environment:
IAAI_DATABASE_URL: postgresql+psycopg2://iaai:iaai@postgres:5432/iaai_scraper
IAAI_REDIS_URL: redis://redis:6379/0
CELERY_BROKER_URL: redis://redis:6379/0
CELERY_RESULT_BACKEND: redis://redis:6379/0
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
stop_grace_period: 60s
command: >
celery -A iaai_scraper.worker.celery_app worker
--loglevel=info --concurrency=1 --pool=prefork
-Q scraping --without-heartbeat
# ─── Celery Beat (периодический планировщик) ──────────────
beat:
build: .
container_name: iaai-beat
restart: unless-stopped
env_file:
- path: .env
required: false
environment:
IAAI_DATABASE_URL: postgresql+psycopg2://iaai:iaai@postgres:5432/iaai_scraper
IAAI_REDIS_URL: redis://redis:6379/0
CELERY_BROKER_URL: redis://redis:6379/0
CELERY_RESULT_BACKEND: redis://redis:6379/0
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
command: >
celery -A iaai_scraper.worker.celery_app beat
--loglevel=info
volumes:
pgdata:

View File

@@ -20,12 +20,38 @@ if [ -n "$SOCKS5_PROXY_HOST" ]; then
echo "[entrypoint] Proxy bridge started (PID $BRIDGE_PID)" echo "[entrypoint] Proxy bridge started (PID $BRIDGE_PID)"
fi fi
# IAAI blocks headless Chromium on Linux; run headed via Xvfb virtual display # Xvfb needed only for worker (Playwright) — not for API or beat
export DISPLAY=:99 NEEDS_XVFB=false
export IAAI_HEADLESS=false case "$1" in
Xvfb :99 -screen 0 1920x1080x24 -nolisten tcp & celery*|python*main*)
XVFB_PID=$! NEEDS_XVFB=true
sleep 0.5 ;;
echo "[entrypoint] Xvfb started (PID $XVFB_PID, DISPLAY=$DISPLAY)" *)
# Check if any arg contains "worker"
for arg in "$@"; do
case "$arg" in
*worker*) NEEDS_XVFB=true; break ;;
esac
done
;;
esac
if [ "$NEEDS_XVFB" = "true" ]; then
# IAAI blocks headless Chromium on Linux; run headed via Xvfb virtual display
export DISPLAY=:99
export IAAI_HEADLESS=false
Xvfb :99 -screen 0 1920x1080x24 -nolisten tcp &
XVFB_PID=$!
sleep 0.5
echo "[entrypoint] Xvfb started (PID $XVFB_PID, DISPLAY=$DISPLAY)"
fi
# Run Alembic migrations (only for API service, skip for worker/beat)
case "$1" in
uvicorn*)
echo "[entrypoint] Running Alembic migrations..."
alembic upgrade head || echo "[entrypoint] WARNING: Alembic migration failed, continuing..."
;;
esac
exec "$@" exec "$@"

View File

@@ -2,6 +2,11 @@ playwright>=1.53.0
python-dotenv>=1.0.1 python-dotenv>=1.0.1
pydantic>=2.8.2 pydantic>=2.8.2
SQLAlchemy>=2.0.32 SQLAlchemy>=2.0.32
PySocks>=1.7.1 fastapi>=0.115.0
uvicorn>=0.34.0
celery>=5.4.0
redis>=5.2.0
psycopg2-binary>=2.9.9
alembic>=1.14.0
pytest>=8.3.0 pytest>=8.3.0
pytest-cov>=5.0.0 pytest-cov>=5.0.0