diff --git a/.dockerignore b/.dockerignore index 32afd83..d83c15a 100644 --- a/.dockerignore +++ b/.dockerignore @@ -4,7 +4,7 @@ .gitattributes # CI/CD -.drone.yml +.drone.yml* .github # Documentation @@ -12,6 +12,7 @@ !README.md CHANGELOG.md LICENSE +ОБНОВЛЕНИЯ.md # IDE .vscode @@ -24,9 +25,8 @@ LICENSE .DS_Store Thumbs.db -# Node +# Node.js frontend/node_modules -frontend/dist frontend/.vite frontend/npm-debug.log* frontend/yarn-debug.log* @@ -46,25 +46,30 @@ backend/pip-delete-this-directory.txt backend/.pytest_cache backend/.coverage backend/htmlcov +daemon/__pycache__ # Data (будет монтироваться как volume) backend/servers/* -backend/users.json -backend/tickets.json +!backend/servers/.gitkeep +backend/data/* +!backend/data/.gitkeep # Logs *.log -logs +logs/* +!logs/.gitkeep -# Environment +# Environment files .env .env.local .env.*.local +backend/.env* +frontend/.env* +daemon/.env* # Docker docker-compose.yml docker-compose.*.yml -Dockerfile .dockerignore # Tests @@ -72,8 +77,35 @@ tests test *.test.js *.spec.js +__tests__ # Build artifacts build dist *.egg-info +.pytest_cache + +# Temporary files +tmp +temp +*.tmp +*.temp + +# Batch files (Windows specific) +*.bat + +# Postman collections +*.postman_collection.json + +# Nginx configs (handled separately) +nginx/* + +# Keys and certificates +*.key +*.pem +*.crt +*.p12 + +# Backup files +*.bak +*.backup diff --git a/Dockerfile b/Dockerfile index 97531f6..cf4f7df 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,63 +1,139 @@ -# Multi-stage build для MC Panel +# ================================ +# MC Panel - Multi-Stage Production Dockerfile +# ================================ -# Stage 1: Build Frontend +# Stage 1: Frontend Build FROM node:18-alpine AS frontend-builder +# Установка зависимостей для сборки +RUN apk add --no-cache git + WORKDIR /app/frontend -# Копируем package файлы +# Копируем package files для кеширования зависимостей COPY frontend/package*.json ./ -# Устанавливаем ВСЕ зависимости (включая dev для сборки) -RUN npm ci +# Устанавливаем зависимости (включая dev для сборки) +RUN npm ci --silent -# Копируем исходники фронтенда +# Копируем исходники и конфиги COPY frontend/ ./ -# Собираем фронтенд +# Собираем продакшн версию RUN npm run build -# Stage 2: Backend + Frontend -FROM python:3.11-slim +# ================================ +# Stage 2: Python Dependencies +# ================================ +FROM python:3.11-slim AS python-deps -# Устанавливаем системные зависимости +# Устанавливаем системные зависимости для компиляции Python пакетов RUN apt-get update && apt-get install -y \ + build-essential \ curl \ && rm -rf /var/lib/apt/lists/* -# Создаем рабочую директорию -WORKDIR /app +# Обновляем pip и устанавливаем зависимости +COPY backend/requirements.txt /tmp/ +RUN pip install --no-cache-dir --upgrade pip && \ + pip install --no-cache-dir --user -r /tmp/requirements.txt -# Копируем requirements и устанавливаем Python зависимости -COPY backend/requirements.txt ./backend/ -RUN pip install --no-cache-dir -r backend/requirements.txt +# ================================ +# Stage 3: Daemon Dependencies (опционально) +# ================================ +FROM python:3.11-slim AS daemon-deps -# Копируем backend -COPY backend/ ./backend/ +RUN apt-get update && apt-get install -y \ + build-essential \ + && rm -rf /var/lib/apt/lists/* -# Копируем собранный frontend из первого stage -COPY --from=frontend-builder /app/frontend/dist ./frontend/dist +COPY daemon/requirements.txt /tmp/daemon-requirements.txt +RUN pip install --no-cache-dir --upgrade pip && \ + pip install --no-cache-dir --user -r /tmp/daemon-requirements.txt -# Создаем необходимые директории -RUN mkdir -p /app/backend/servers +# ================================ +# Stage 4: Production Runtime +# ================================ +FROM python:3.11-slim AS production -# Создаем пользователя для запуска приложения -RUN useradd -m -u 1000 mcpanel && \ - chown -R mcpanel:mcpanel /app - -USER mcpanel +# Метаданные +LABEL maintainer="MC Panel Team" +LABEL version="1.0.0" +LABEL description="MC Panel - Minecraft Server Management Panel" # Переменные окружения -ENV PYTHONUNBUFFERED=1 -ENV PORT=8000 +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + PYTHONPATH=/app \ + PORT=8000 \ + DEBIAN_FRONTEND=noninteractive -# Открываем порт +# Устанавливаем только runtime зависимости +RUN apt-get update && apt-get install -y \ + curl \ + procps \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# Создаем пользователя для безопасности +RUN groupadd -r mcpanel && \ + useradd -r -g mcpanel -d /app -s /bin/bash mcpanel + +# Создаем структуру директорий +WORKDIR /app +RUN mkdir -p \ + /app/backend \ + /app/frontend/dist \ + /app/daemon \ + /app/data \ + /app/logs \ + /app/backend/servers \ + /app/backend/data + +# Копируем Python зависимости из предыдущих стадий +COPY --from=python-deps /root/.local /home/mcpanel/.local +COPY --from=daemon-deps /root/.local /home/mcpanel/.local-daemon + +# Копируем собранный frontend +COPY --from=frontend-builder /app/frontend/dist ./frontend/dist + +# Копируем backend код +COPY backend/ ./backend/ + +# Копируем daemon код +COPY daemon/ ./daemon/ + +# Копируем дополнительные файлы +COPY key.py ./ +COPY users.json ./backend/ 2>/dev/null || true + +# Создаем конфигурационные файлы по умолчанию +RUN echo '{}' > /app/backend/users.json && \ + echo '{}' > /app/backend/tickets.json + +# Устанавливаем права доступа +RUN chown -R mcpanel:mcpanel /app && \ + chmod +x /app/backend/main.py + +# Переключаемся на непривилегированного пользователя +USER mcpanel + +# Добавляем локальные Python пакеты в PATH +ENV PATH="/home/mcpanel/.local/bin:$PATH" + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ + CMD curl -f http://localhost:${PORT}/api/auth/oidc/providers || exit 1 + +# Expose порты EXPOSE 8000 -# Healthcheck -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD curl -f http://localhost:8000/api/auth/oidc/providers || exit 1 +# Volumes для персистентных данных +VOLUME ["/app/backend/servers", "/app/backend/data", "/app/logs"] -# Запускаем приложение +# Рабочая директория для запуска WORKDIR /app/backend -CMD ["python", "main.py"] + +# Команда запуска +CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "1"] \ No newline at end of file diff --git a/docker-build.sh b/docker-build.sh new file mode 100644 index 0000000..2abeda7 --- /dev/null +++ b/docker-build.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +# MC Panel Docker Build Script + +set -e + +echo "🚀 Сборка MC Panel Docker образа..." + +# Проверяем наличие Docker +if ! command -v docker &> /dev/null; then + echo "❌ Docker не установлен!" + exit 1 +fi + +# Проверяем наличие docker-compose +if ! command -v docker-compose &> /dev/null; then + echo "⚠️ docker-compose не найден, используем docker compose" + COMPOSE_CMD="docker compose" +else + COMPOSE_CMD="docker-compose" +fi + +# Создаем необходимые директории +echo "📁 Создание директорий..." +mkdir -p backend/servers backend/data logs + +# Создаем .gitkeep файлы для пустых директорий +touch backend/servers/.gitkeep backend/data/.gitkeep logs/.gitkeep + +# Сборка образа +echo "🔨 Сборка Docker образа..." +docker build -t mc-panel:latest . + +echo "✅ Образ собран успешно!" + +# Опционально запускаем контейнер +read -p "🤔 Запустить контейнер сейчас? (y/N): " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + echo "🚀 Запуск контейнера..." + $COMPOSE_CMD up -d + + echo "✅ Контейнер запущен!" + echo "🌐 Панель доступна по адресу: http://localhost:8000" + echo "📊 Логи: $COMPOSE_CMD logs -f mcpanel" + echo "🛑 Остановка: $COMPOSE_CMD down" +fi + +echo "🎉 Готово!" \ No newline at end of file diff --git a/docker-compose-simple.yml b/docker-compose-simple.yml deleted file mode 100644 index 0dfc4a5..0000000 --- a/docker-compose-simple.yml +++ /dev/null @@ -1,36 +0,0 @@ -version: '3.8' - -services: - mc-panel: - build: - context: . - dockerfile: Dockerfile - container_name: mc-panel - restart: unless-stopped - ports: - - "80:8000" # Прямой доступ через порт 80 - environment: - - ZITADEL_ISSUER=${ZITADEL_ISSUER} - - ZITADEL_CLIENT_ID=${ZITADEL_CLIENT_ID} - - ZITADEL_CLIENT_SECRET=${ZITADEL_CLIENT_SECRET} - - BASE_URL=${BASE_URL:-http://localhost} - - FRONTEND_URL=${FRONTEND_URL:-http://localhost} - - SECRET_KEY=${SECRET_KEY:-change-this-in-production} - - PYTHONUNBUFFERED=1 - volumes: - - ./data/servers:/app/backend/servers - - ./data/users.json:/app/backend/users.json - - ./data/tickets.json:/app/backend/tickets.json - - ./data:/app/data - networks: - - mc-panel-network - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8000/api/auth/oidc/providers"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - -networks: - mc-panel-network: - driver: bridge \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 01b016d..a6a0715 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,36 +1,63 @@ version: '3.8' services: - mc-panel: + mcpanel: build: context: . dockerfile: Dockerfile container_name: mc-panel restart: unless-stopped - expose: - - "8000" + ports: + - "8000:8000" environment: - - ZITADEL_ISSUER=${ZITADEL_ISSUER} - - ZITADEL_CLIENT_ID=${ZITADEL_CLIENT_ID} - - ZITADEL_CLIENT_SECRET=${ZITADEL_CLIENT_SECRET} - - BASE_URL=${BASE_URL:-http://localhost} - - FRONTEND_URL=${FRONTEND_URL:-http://localhost} - - SECRET_KEY=${SECRET_KEY:-change-this-in-production} - - PYTHONUNBUFFERED=1 + # Основные настройки + - PORT=8000 + - BASE_URL=http://localhost:8000 + - FRONTEND_URL=http://localhost:8000 + + # Безопасность (ОБЯЗАТЕЛЬНО измените в продакшене!) + - SECRET_KEY=your-very-long-random-secret-key-change-this-in-production + + # OIDC настройки (раскомментируйте и настройте при необходимости) + # - ZITADEL_ISSUER=https://your-instance.zitadel.cloud + # - ZITADEL_CLIENT_ID=your_client_id_here + # - ZITADEL_CLIENT_SECRET=your_client_secret_here + + # Логирование + - LOG_LEVEL=INFO + volumes: - - ./data/servers:/app/backend/servers - - ./data/users.json:/app/backend/users.json - - ./data/tickets.json:/app/backend/tickets.json - - ./data:/app/data + # Персистентные данные + - mcpanel_servers:/app/backend/servers + - mcpanel_data:/app/backend/data + - mcpanel_logs:/app/logs + + # Конфигурационные файлы (опционально) + - ./backend/users.json:/app/backend/users.json + - ./backend/tickets.json:/app/backend/tickets.json + networks: - - mc-panel-network + - mcpanel-network + + # Ограничения ресурсов + deploy: + resources: + limits: + memory: 1G + cpus: '0.5' + reservations: + memory: 512M + cpus: '0.25' + + # Health check healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/api/auth/oidc/providers"] interval: 30s timeout: 10s retries: 3 - start_period: 40s + start_period: 60s + # Nginx reverse proxy (опционально) nginx: image: nginx:alpine container_name: mc-panel-nginx @@ -39,31 +66,23 @@ services: - "80:80" - "443:443" volumes: - - ./nginx/default.conf:/etc/nginx/nginx.conf:ro - - frontend-static:/usr/share/nginx/html:ro + - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - ./nginx/ssl:/etc/nginx/ssl:ro depends_on: - - frontend-init - - mc-panel + - mcpanel networks: - - mc-panel-network - - frontend-init: - build: - context: . - dockerfile: Dockerfile - container_name: mc-panel-frontend-init - volumes: - - frontend-static:/tmp/frontend - command: sh -c "cp -r /app/frontend/dist/* /tmp/frontend/ 2>/dev/null || echo 'No files to copy'; echo 'Frontend initialization complete'" - restart: "no" - networks: - - mc-panel-network - -networks: - mc-panel-network: - driver: bridge + - mcpanel-network + profiles: + - with-nginx volumes: - frontend-static: - driver: local \ No newline at end of file + mcpanel_servers: + driver: local + mcpanel_data: + driver: local + mcpanel_logs: + driver: local + +networks: + mcpanel-network: + driver: bridge \ No newline at end of file