refactor: migrate deploy layout and stabilize compose runtime

This commit is contained in:
chengkai3
2026-05-02 12:24:39 +08:00
parent e3164f34ec
commit 85689bf1bd
24 changed files with 745 additions and 568 deletions
+138 -226
View File
@@ -122,218 +122,138 @@ jobs:
export COMPOSE_HTTP_TIMEOUT="${COMPOSE_HTTP_TIMEOUT:-600}"
DEPLOY_DIR="${DEPLOY_PATH:-/opt/fquiz}"
mkdir -p "${DEPLOY_DIR}"
cd "${DEPLOY_DIR}"
cat > docker-compose.prod.yml <<'YAML'
cat > deploy/pro-deploy/compose.yml <<'YAML'
services:
db:
image: ${POSTGRES_IMAGE:-docker.m.daocloud.io/pgvector/pgvector:pg16}
container_name: fquiz-db
image: ${POSTGRES_IMAGE}
container_name: ${COMPOSE_PROJECT_NAME}-db
environment:
POSTGRES_DB: ${POSTGRES_DB:-fquiz}
POSTGRES_USER: ${POSTGRES_USER:-fquiz}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-fquiz}
POSTGRES_DB: ${POSTGRES_DB}
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
ports:
- "${POSTGRES_PORT:-5434}:5432"
- "${POSTGRES_PORT}:5432"
volumes:
- fquiz_db_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-fquiz} -d ${POSTGRES_DB:-fquiz}"]
interval: 10s
timeout: 5s
retries: 8
start_period: 10s
- prod_db_data:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: ${REDIS_IMAGE:-docker.m.daocloud.io/library/redis:7-alpine}
container_name: fquiz-redis
image: ${REDIS_IMAGE}
container_name: ${COMPOSE_PROJECT_NAME}-redis
command: redis-server --appendonly yes
ports:
- "${REDIS_PORT:-6379}:6379"
- "${REDIS_PORT}:6379"
volumes:
- fquiz_redis_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 5
start_period: 5s
- prod_redis_data:/data
restart: unless-stopped
minio:
image: ${MINIO_IMAGE:-minio/minio:latest}
container_name: fquiz-minio
image: ${MINIO_IMAGE}
container_name: ${COMPOSE_PROJECT_NAME}-minio
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin}
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin}
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY}
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY}
ports:
- "${MINIO_API_PORT:-9000}:9000"
- "${MINIO_CONSOLE_PORT:-9001}:9001"
- "${MINIO_API_PORT}:9000"
- "${MINIO_CONSOLE_PORT}:9001"
volumes:
- fquiz_minio_data:/data
- prod_minio_data:/data
restart: unless-stopped
minio-init:
image: ${MINIO_MC_IMAGE:-minio/mc:latest}
container_name: fquiz-minio-init
image: ${MINIO_MC_IMAGE}
container_name: ${COMPOSE_PROJECT_NAME}-minio-init
depends_on:
minio:
condition: service_started
environment:
MINIO_ENDPOINT: ${MINIO_ENDPOINT:-http://minio:9000}
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin}
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin}
MINIO_BUCKET: ${MINIO_BUCKET:-fquiz-files}
- minio
entrypoint: /bin/sh
command:
- -c
- >
until mc alias set local "$$MINIO_ENDPOINT" "$$MINIO_ACCESS_KEY" "$$MINIO_SECRET_KEY"; do
until mc alias set local "$${MINIO_ENDPOINT}" "$${MINIO_ACCESS_KEY}" "$${MINIO_SECRET_KEY}"; do
sleep 1;
done;
mc mb -p "local/$$MINIO_BUCKET" || true;
mc mb -p "local/$${MINIO_BUCKET}" || true;
environment:
MINIO_ENDPOINT: ${MINIO_ENDPOINT}
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
MINIO_BUCKET: ${MINIO_BUCKET}
restart: "no"
api:
image: ${API_IMAGE}
container_name: fquiz-api
container_name: ${COMPOSE_PROJECT_NAME}-api
depends_on:
db:
condition: service_healthy
minio:
condition: service_started
minio-init:
condition: service_completed_successfully
- db
- redis
- minio
- minio-init
env_file:
- ./.env.prod
environment:
API_HOST: ${API_HOST:-0.0.0.0}
API_PORT: ${API_PORT:-8000}
API_CORS_ORIGINS: ${API_CORS_ORIGINS:-http://localhost:3000,http://127.0.0.1:3000}
API_CORS_ORIGIN_REGEX: ${API_CORS_ORIGIN_REGEX:-}
DATABASE_URL: ${DATABASE_URL:-postgresql+psycopg://fquiz:fquiz@db:5432/fquiz}
DB_HOST: ${DB_HOST:-db}
DB_PORT: ${DB_PORT:-5432}
DB_NAME: ${DB_NAME:-postgres}
DB_SCHEMA: ${DB_SCHEMA:-public}
DB_USERNAME: ${DB_USERNAME:-fquiz}
DB_PASSWORD: ${DB_PASSWORD:-fquiz}
USER_USERNAME_COLUMN: ${USER_USERNAME_COLUMN:-username}
USER_PASSWORD_COLUMN: ${USER_PASSWORD_COLUMN:-password_hash}
USER_STATUS_COLUMN: ${USER_STATUS_COLUMN:-status}
FILE_VFS_ROOT: ${FILE_VFS_ROOT:-./data/vfs}
MINIO_ENABLED: ${MINIO_ENABLED:-true}
MINIO_ENDPOINT: ${MINIO_ENDPOINT:-http://minio:9000}
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin}
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin}
MINIO_BUCKET: ${MINIO_BUCKET:-fquiz-files}
MINIO_REGION: ${MINIO_REGION:-us-east-1}
JWT_SECRET_KEY: ${JWT_SECRET_KEY:-change-this-in-production}
ACCESS_TOKEN_EXPIRE_MINUTES: ${ACCESS_TOKEN_EXPIRE_MINUTES:-480}
REFRESH_TOKEN_EXPIRE_DAYS: ${REFRESH_TOKEN_EXPIRE_DAYS:-30}
REFRESH_COOKIE_SECURE: ${REFRESH_COOKIE_SECURE:-false}
REFRESH_COOKIE_SAMESITE: ${REFRESH_COOKIE_SAMESITE:-lax}
LLM_PROVIDER_API_KEYS: ${LLM_PROVIDER_API_KEYS:-}
LLM_REQUEST_TIMEOUT_SECONDS: ${LLM_REQUEST_TIMEOUT_SECONDS:-60}
CHAT_CONTEXT_MESSAGE_LIMIT: ${CHAT_CONTEXT_MESSAGE_LIMIT:-12}
CHAT_DEFAULT_SYSTEM_PROMPT: ${CHAT_DEFAULT_SYSTEM_PROMPT:-You are a helpful assistant.}
CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://redis:6379/0}
CELERY_RESULT_BACKEND: ${CELERY_RESULT_BACKEND:-redis://redis:6379/1}
CELERY_TIMEZONE: ${CELERY_TIMEZONE:-Asia/Shanghai}
SCHEDULER_EXPIRE_INTERVAL_SECONDS: ${SCHEDULER_EXPIRE_INTERVAL_SECONDS:-60}
WINE_BINARY_PATH: ${WINE_BINARY_PATH:-wine}
WINE_ALLOWED_ROOT: ${WINE_ALLOWED_ROOT:-./data/wine}
WINE_DEFAULT_TIMEOUT_SECONDS: ${WINE_DEFAULT_TIMEOUT_SECONDS:-300}
WINE_MAX_TIMEOUT_SECONDS: ${WINE_MAX_TIMEOUT_SECONDS:-1800}
INITIAL_ADMIN_EMAIL: ${INITIAL_ADMIN_EMAIL:-admin@example.com}
INITIAL_ADMIN_USERNAME: ${INITIAL_ADMIN_USERNAME:-admin}
INITIAL_ADMIN_PASSWORD: ${INITIAL_ADMIN_PASSWORD:-change-me-strong-password}
ports:
- "${API_PORT:-8000}:8000"
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/health', timeout=2).read()"]
interval: 10s
timeout: 3s
retries: 5
start_period: 10s
API_HOST: 0.0.0.0
API_PORT: 8000
DB_HOST: db
DB_PORT: 5432
MINIO_ENDPOINT: http://minio:9000
CELERY_BROKER_URL: redis://redis:6379/0
CELERY_RESULT_BACKEND: redis://redis:6379/1
expose:
- "8000"
restart: unless-stopped
celery-worker:
image: ${API_IMAGE}
container_name: fquiz-celery-worker
container_name: ${COMPOSE_PROJECT_NAME}-celery-worker
command:
- celery
- -A
- app.core.celery_app.celery_app
- worker
- --loglevel=${CELERY_LOG_LEVEL:-INFO}
- --concurrency=${CELERY_WORKER_CONCURRENCY:-2}
- --queues=${CELERY_WORKER_QUEUES:-default,celery}
- --loglevel=${CELERY_LOG_LEVEL}
- --concurrency=${CELERY_WORKER_CONCURRENCY}
- --queues=${CELERY_WORKER_QUEUES}
depends_on:
api:
condition: service_healthy
redis:
condition: service_healthy
- api
- redis
env_file:
- ./.env.prod
environment:
DATABASE_URL: ${DATABASE_URL:-postgresql+psycopg://fquiz:fquiz@db:5432/fquiz}
DB_HOST: ${DB_HOST:-db}
DB_PORT: ${DB_PORT:-5432}
DB_NAME: ${DB_NAME:-postgres}
DB_SCHEMA: ${DB_SCHEMA:-public}
DB_USERNAME: ${DB_USERNAME:-fquiz}
DB_PASSWORD: ${DB_PASSWORD:-fquiz}
USER_USERNAME_COLUMN: ${USER_USERNAME_COLUMN:-username}
USER_PASSWORD_COLUMN: ${USER_PASSWORD_COLUMN:-password_hash}
USER_STATUS_COLUMN: ${USER_STATUS_COLUMN:-status}
CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://redis:6379/0}
CELERY_RESULT_BACKEND: ${CELERY_RESULT_BACKEND:-redis://redis:6379/1}
CELERY_TIMEZONE: ${CELERY_TIMEZONE:-Asia/Shanghai}
SCHEDULER_EXPIRE_INTERVAL_SECONDS: ${SCHEDULER_EXPIRE_INTERVAL_SECONDS:-60}
FLOWER_API_BASE_URL: ${FLOWER_API_BASE_URL:-http://flower:5555}
FLOWER_API_TIMEOUT_SECONDS: ${FLOWER_API_TIMEOUT_SECONDS:-10}
FLOWER_BASIC_AUTH: ${FLOWER_BASIC_AUTH:-admin:admin}
WORKER_REGISTRY_TTL_SECONDS: ${WORKER_REGISTRY_TTL_SECONDS:-90}
DB_HOST: db
DB_PORT: 5432
CELERY_BROKER_URL: redis://redis:6379/0
CELERY_RESULT_BACKEND: redis://redis:6379/1
FLOWER_API_BASE_URL: http://flower:5555
restart: unless-stopped
celery-beat:
image: ${API_IMAGE}
container_name: fquiz-celery-beat
container_name: ${COMPOSE_PROJECT_NAME}-celery-beat
command:
- celery
- -A
- app.core.celery_app.celery_app
- beat
- --loglevel=${CELERY_LOG_LEVEL:-INFO}
- --loglevel=${CELERY_LOG_LEVEL}
- --schedule=/tmp/celerybeat-schedule
depends_on:
api:
condition: service_healthy
redis:
condition: service_healthy
- api
- redis
env_file:
- ./.env.prod
environment:
DATABASE_URL: ${DATABASE_URL:-postgresql+psycopg://fquiz:fquiz@db:5432/fquiz}
DB_HOST: ${DB_HOST:-db}
DB_PORT: ${DB_PORT:-5432}
DB_NAME: ${DB_NAME:-postgres}
DB_SCHEMA: ${DB_SCHEMA:-public}
DB_USERNAME: ${DB_USERNAME:-fquiz}
DB_PASSWORD: ${DB_PASSWORD:-fquiz}
USER_USERNAME_COLUMN: ${USER_USERNAME_COLUMN:-username}
USER_PASSWORD_COLUMN: ${USER_PASSWORD_COLUMN:-password_hash}
USER_STATUS_COLUMN: ${USER_STATUS_COLUMN:-status}
CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://redis:6379/0}
CELERY_RESULT_BACKEND: ${CELERY_RESULT_BACKEND:-redis://redis:6379/1}
CELERY_TIMEZONE: ${CELERY_TIMEZONE:-Asia/Shanghai}
SCHEDULER_EXPIRE_INTERVAL_SECONDS: ${SCHEDULER_EXPIRE_INTERVAL_SECONDS:-60}
WORKER_REGISTRY_TTL_SECONDS: ${WORKER_REGISTRY_TTL_SECONDS:-90}
DB_HOST: db
DB_PORT: 5432
CELERY_BROKER_URL: redis://redis:6379/0
CELERY_RESULT_BACKEND: redis://redis:6379/1
restart: unless-stopped
flower:
image: ${API_IMAGE}
container_name: fquiz-flower
profiles:
- monitoring
container_name: ${COMPOSE_PROJECT_NAME}-flower
command:
- celery
- -A
@@ -342,67 +262,86 @@ jobs:
- --address=0.0.0.0
- --port=5555
- --persistent=False
- --basic-auth=${FLOWER_BASIC_AUTH:-admin:admin}
- --basic-auth=${FLOWER_BASIC_AUTH}
depends_on:
redis:
condition: service_healthy
- redis
environment:
CELERY_BROKER_URL: ${CELERY_BROKER_URL:-redis://redis:6379/0}
CELERY_RESULT_BACKEND: ${CELERY_RESULT_BACKEND:-redis://redis:6379/1}
CELERY_TIMEZONE: ${CELERY_TIMEZONE:-Asia/Shanghai}
FLOWER_BASIC_AUTH: ${FLOWER_BASIC_AUTH:-admin:admin}
ports:
- "${FLOWER_PORT:-5555}:5555"
CELERY_BROKER_URL: redis://redis:6379/0
CELERY_RESULT_BACKEND: redis://redis:6379/1
CELERY_TIMEZONE: ${CELERY_TIMEZONE}
FLOWER_BASIC_AUTH: ${FLOWER_BASIC_AUTH}
expose:
- "5555"
restart: unless-stopped
web:
image: ${WEB_IMAGE}
container_name: fquiz-web
container_name: ${COMPOSE_PROJECT_NAME}-web
depends_on:
api:
condition: service_healthy
- api
environment:
NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL:-http://localhost:8000}
NEXT_PUBLIC_API_BASE_URL: ${NEXT_PUBLIC_API_BASE_URL}
NODE_ENV: production
ports:
- "${WEB_PORT:-3000}:3000"
expose:
- "3000"
restart: unless-stopped
volumes:
fquiz_db_data:
fquiz_redis_data:
fquiz_minio_data:
prod_db_data:
prod_redis_data:
prod_minio_data:
YAML
if [ ! -f .env ]; then
cat > .env <<'ENV'
NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8000
WEB_PORT=3000
API_HOST=0.0.0.0
API_PORT=8000
API_CORS_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
API_CORS_ORIGIN_REGEX=
DATABASE_URL=postgresql+psycopg://fquiz:fquiz@db:5432/fquiz
if [ ! -f deploy/pro-deploy/.env ]; then
cat > deploy/pro-deploy/.env <<'ENV'
COMPOSE_PROJECT_NAME=fquiz-prod
API_IMAGE=ghcr.io/chengkml/fquiz-api:latest
WEB_IMAGE=ghcr.io/chengkml/fquiz-web:latest
POSTGRES_IMAGE=docker.m.daocloud.io/pgvector/pgvector:pg16
REDIS_IMAGE=docker.m.daocloud.io/library/redis:7-alpine
MINIO_IMAGE=minio/minio:latest
MINIO_MC_IMAGE=minio/mc:latest
POSTGRES_PORT=5434
REDIS_PORT=6379
MINIO_API_PORT=9000
MINIO_CONSOLE_PORT=9001
NEXT_PUBLIC_API_BASE_URL=https://quiz.example.com/api
CELERY_LOG_LEVEL=INFO
CELERY_WORKER_CONCURRENCY=4
CELERY_WORKER_QUEUES=default,celery
CELERY_TIMEZONE=Asia/Shanghai
FLOWER_BASIC_AUTH=admin:change_me
POSTGRES_DB=fquiz
POSTGRES_USER=fquiz
MINIO_ENDPOINT=http://minio:9000
MINIO_BUCKET=fquiz-files
ENV
echo "[warn] deploy/pro-deploy/.env 不存在,已写入默认模板,请尽快改成生产配置。"
fi
if [ ! -f deploy/pro-deploy/.env.prod ]; then
cat > deploy/pro-deploy/.env.prod <<'ENV'
DATABASE_URL=postgresql+psycopg://fquiz:replace_strong_password@db:5432/fquiz
DB_HOST=db
DB_PORT=5432
DB_NAME=postgres
DB_SCHEMA=public
DB_USERNAME=fquiz
DB_PASSWORD=fquiz
DB_PASSWORD=replace_strong_password
USER_USERNAME_COLUMN=username
USER_PASSWORD_COLUMN=password_hash
USER_STATUS_COLUMN=status
FILE_VFS_ROOT=./data/vfs
MINIO_ENABLED=true
MINIO_ENDPOINT=http://minio:9000
MINIO_ACCESS_KEY=minioadmin
MINIO_SECRET_KEY=minioadmin
MINIO_ACCESS_KEY=replace_strong_access_key
MINIO_SECRET_KEY=replace_strong_secret_key
MINIO_BUCKET=fquiz-files
MINIO_REGION=us-east-1
JWT_SECRET_KEY=change-this-in-production
JWT_SECRET_KEY=replace_strong_jwt_secret
ACCESS_TOKEN_EXPIRE_MINUTES=480
REFRESH_TOKEN_EXPIRE_DAYS=30
REFRESH_COOKIE_SECURE=false
REFRESH_COOKIE_SECURE=true
REFRESH_COOKIE_SAMESITE=lax
LLM_PROVIDER_API_KEYS=
LLM_REQUEST_TIMEOUT_SECONDS=60
@@ -411,60 +350,33 @@ jobs:
CELERY_BROKER_URL=redis://redis:6379/0
CELERY_RESULT_BACKEND=redis://redis:6379/1
CELERY_TIMEZONE=Asia/Shanghai
CELERY_LOG_LEVEL=INFO
CELERY_WORKER_CONCURRENCY=2
CELERY_WORKER_QUEUES=default,celery
SCHEDULER_EXPIRE_INTERVAL_SECONDS=60
FLOWER_API_BASE_URL=http://flower:5555
FLOWER_API_TIMEOUT_SECONDS=10
FLOWER_BASIC_AUTH=admin:admin
FLOWER_PORT=5555
FLOWER_BASIC_AUTH=admin:change_me
WORKER_REGISTRY_TTL_SECONDS=90
CELERY_WORKER_QUEUES=default,celery
WINE_BINARY_PATH=wine
WINE_ALLOWED_ROOT=./data/wine
WINE_DEFAULT_TIMEOUT_SECONDS=300
WINE_MAX_TIMEOUT_SECONDS=1800
INITIAL_ADMIN_EMAIL=admin@example.com
INITIAL_ADMIN_USERNAME=admin
INITIAL_ADMIN_PASSWORD=change-me-strong-password
INITIAL_ADMIN_PASSWORD=replace_strong_admin_password
POSTGRES_DB=fquiz
POSTGRES_USER=fquiz
POSTGRES_PASSWORD=fquiz
POSTGRES_PORT=5434
POSTGRES_IMAGE=docker.m.daocloud.io/pgvector/pgvector:pg16
REDIS_IMAGE=docker.m.daocloud.io/library/redis:7-alpine
REDIS_PORT=6379
MINIO_IMAGE=minio/minio:latest
MINIO_MC_IMAGE=minio/mc:latest
MINIO_API_PORT=9000
MINIO_CONSOLE_PORT=9001
POSTGRES_PASSWORD=replace_strong_password
API_CORS_ORIGINS=https://quiz.example.com
API_CORS_ORIGIN_REGEX=
ENV
echo "[warn] .env 不存在,已写入默认模板,请尽快改成生产配置。"
echo "[warn] deploy/pro-deploy/.env.prod 不存在,已写入默认模板,请尽快改成生产配置。"
fi
ensure_web_port_available() {
local target_web_port=3000
if grep -q '^WEB_PORT=' .env; then
sed -i "s/^WEB_PORT=.*/WEB_PORT=${target_web_port}/" .env
else
echo "WEB_PORT=${target_web_port}" >> .env
fi
local conflicting_web_containers
conflicting_web_containers="$(docker ps --filter "publish=${target_web_port}" --format '{{.Names}}' | grep -Ev '^fquiz-web$' || true)"
if [ -n "${conflicting_web_containers}" ]; then
echo "[error] WEB 端口 ${target_web_port} 已被其他容器占用,停止部署。"
echo "[error] 冲突容器: ${conflicting_web_containers//$'\n'/, }"
return 1
fi
}
ensure_web_port_available
cat > .images.env <<ENV
API_IMAGE=${API_IMAGE}:${IMAGE_TAG}
WEB_IMAGE=${WEB_IMAGE}:${IMAGE_TAG}
NEXT_PUBLIC_API_BASE_URL=${NEXT_PUBLIC_API_BASE_URL}
FLOWER_BASIC_AUTH=${FLOWER_BASIC_AUTH}
ENV
echo "${GHCR_TOKEN}" | docker login ghcr.io -u "${GHCR_USERNAME}" --password-stdin
@@ -478,7 +390,7 @@ jobs:
local max_retries=3
local attempt=1
while true; do
if ${COMPOSE_CMD} --env-file .env --env-file .images.env -f docker-compose.prod.yml pull; then
if ${COMPOSE_CMD} --env-file deploy/pro-deploy/.env --env-file deploy/pro-deploy/.env.prod --env-file .images.env -f deploy/pro-deploy/compose.yml pull; then
break
fi
if [ "${attempt}" -ge "${max_retries}" ]; then
@@ -493,15 +405,15 @@ jobs:
}
pull_with_retry
if ! ${COMPOSE_CMD} --env-file .env --env-file .images.env -f docker-compose.prod.yml up -d --remove-orphans; then
if ! ${COMPOSE_CMD} --env-file deploy/pro-deploy/.env --env-file deploy/pro-deploy/.env.prod --env-file .images.env -f deploy/pro-deploy/compose.yml up -d --remove-orphans; then
echo "[error] docker compose up failed, collecting container diagnostics..."
${COMPOSE_CMD} --env-file .env --env-file .images.env -f docker-compose.prod.yml ps || true
docker logs --tail 300 fquiz-api || true
docker logs --tail 200 fquiz-db || true
docker logs --tail 200 fquiz-redis || true
docker logs --tail 200 fquiz-celery-worker || true
docker logs --tail 200 fquiz-celery-beat || true
docker logs --tail 200 fquiz-flower || true
${COMPOSE_CMD} --env-file deploy/pro-deploy/.env --env-file deploy/pro-deploy/.env.prod --env-file .images.env -f deploy/pro-deploy/compose.yml ps || true
docker logs --tail 300 fquiz-prod-api || true
docker logs --tail 200 fquiz-prod-db || true
docker logs --tail 200 fquiz-prod-redis || true
docker logs --tail 200 fquiz-prod-celery-worker || true
docker logs --tail 200 fquiz-prod-celery-beat || true
docker logs --tail 200 fquiz-prod-flower || true
exit 1
fi
${COMPOSE_CMD} --env-file .env --env-file .images.env -f docker-compose.prod.yml ps
${COMPOSE_CMD} --env-file deploy/pro-deploy/.env --env-file deploy/pro-deploy/.env.prod --env-file .images.env -f deploy/pro-deploy/compose.yml ps