From 389b92f68a6bb157558320192ac20a4f126990ef Mon Sep 17 00:00:00 2001 From: arkonsadter Date: Wed, 18 Mar 2026 20:02:20 +0600 Subject: [PATCH] Replace Dockerfiles, Compose and Drone CI with clean working setup --- .drone.yml | 92 ++------------ backend/Dockerfile | 79 +++--------- deploy/docker-compose.hosting.yml | 19 +-- docker-compose.dev.yml | 41 +++--- docker-compose.yml | 40 +++--- frontend/Dockerfile | 200 ++---------------------------- frontend/nginx.conf | 37 ++++++ 7 files changed, 108 insertions(+), 400 deletions(-) create mode 100644 frontend/nginx.conf diff --git a/.drone.yml b/.drone.yml index 7a4b8c2..c18a467 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,18 +1,16 @@ -kind: pipeline +kind: pipeline type: docker -name: code-quality +name: checks trigger: event: - - push - pull_request steps: - - name: backend-sanity + - name: backend-syntax image: python:3.11-slim commands: - cd backend - - pip install --no-cache-dir -r requirements.txt - python -m py_compile main.py auth.py daemons.py oidc_config.py - name: frontend-build-check @@ -21,14 +19,6 @@ steps: - cd frontend - npm ci --silent - npm run build - - npm run lint || echo "ESLint warnings found" - - - name: frontend-security - image: node:20-alpine - commands: - - cd frontend - - npm ci --silent - - npm audit --audit-level=moderate || echo "Security warnings found" --- kind: pipeline @@ -36,31 +26,24 @@ type: docker name: build-images trigger: - branch: - - main - - master - - develop event: - push - tag -depends_on: - - code-quality - steps: - name: build-backend-image image: plugins/docker settings: registry: registry.nevetime.ru repo: registry.nevetime.ru/mc-panel-backend + context: backend + dockerfile: Dockerfile tags: - latest - - "${DRONE_BUILD_NUMBER}" - - "${DRONE_COMMIT_SHA:0:8}" - - "${DRONE_BRANCH}" + - ${DRONE_BUILD_NUMBER} auto_tag: true - dockerfile: backend/Dockerfile - context: backend + cache_from: + - registry.nevetime.ru/mc-panel-backend:latest username: from_secret: docker_username password: @@ -71,66 +54,15 @@ steps: settings: registry: registry.nevetime.ru repo: registry.nevetime.ru/mc-panel-frontend - tags: - - latest - - "${DRONE_BUILD_NUMBER}" - - "${DRONE_COMMIT_SHA:0:8}" - - "${DRONE_BRANCH}" - auto_tag: true - dockerfile: frontend/Dockerfile context: frontend - username: - from_secret: docker_username - password: - from_secret: docker_password - build_args: - - BUILD_DATE=${DRONE_BUILD_CREATED} - - VCS_REF=${DRONE_COMMIT_SHA} - - VERSION=${DRONE_TAG:-${DRONE_BRANCH}} - when: - event: - - push - - tag - ---- -kind: pipeline -type: docker -name: build-monolith - -trigger: - branch: - - main - - master - - develop - event: - - push - - tag - -depends_on: - - code-quality - -steps: - - name: build-monolith-image - image: plugins/docker - settings: - registry: registry.nevetime.ru - repo: registry.nevetime.ru/mc-panel + dockerfile: Dockerfile tags: - latest - - "${DRONE_COMMIT_SHA:0:8}" - - "${DRONE_BRANCH}" + - ${DRONE_BUILD_NUMBER} auto_tag: true - dockerfile: Dockerfile - context: . + cache_from: + - registry.nevetime.ru/mc-panel-frontend:latest username: from_secret: docker_username password: from_secret: docker_password - build_args: - - BUILD_DATE=${DRONE_BUILD_CREATED} - - VCS_REF=${DRONE_COMMIT_SHA} - - VERSION=${DRONE_TAG:-${DRONE_BRANCH}} - when: - event: - - push - - tag diff --git a/backend/Dockerfile b/backend/Dockerfile index f773a60..6d7687c 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,79 +1,30 @@ -# ================================ -# MC Panel Backend - Production Dockerfile -# ================================ +FROM python:3.11-slim -FROM python:3.11-slim AS production - -# Метаданные -LABEL maintainer="MC Panel Team" \ - version="2.0.0" \ - description="MC Panel Backend - FastAPI Server" \ - component="backend" - -# Переменные окружения ENV PYTHONDONTWRITEBYTECODE=1 \ PYTHONUNBUFFERED=1 \ PYTHONPATH=/app \ PORT=8000 \ - WORKERS=1 \ - DEBIAN_FRONTEND=noninteractive + WORKERS=2 -# Устанавливаем системные зависимости -RUN apt-get update && apt-get install -y --no-install-recommends \ - curl \ - procps \ - ca-certificates \ - tini \ - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean - -# Создаем пользователя для безопасности -RUN groupadd -r -g 1000 mcpanel && \ - useradd -r -u 1000 -g mcpanel -d /app -s /bin/bash mcpanel - -# Создаем рабочую директорию WORKDIR /app -# Копируем requirements и устанавливаем зависимости +RUN apt-get update \ + && apt-get install -y --no-install-recommends curl \ + && rm -rf /var/lib/apt/lists/* + COPY requirements.txt ./ -RUN pip install --no-cache-dir --upgrade pip && \ - pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir --upgrade pip \ + && pip install --no-cache-dir -r requirements.txt -# Копируем исходный код -COPY --chown=mcpanel:mcpanel . ./ +COPY . ./ -# Создаем необходимые директории -RUN mkdir -p \ - servers \ - data \ - logs \ - && touch users.json tickets.json +RUN mkdir -p /app/servers /app/data /app/logs \ + && ([ -f /app/users.json ] || echo '{}' > /app/users.json) \ + && ([ -f /app/tickets.json ] || echo '{}' > /app/tickets.json) -# Создаем конфигурационные файлы по умолчанию если их нет -RUN [ ! -f users.json ] && echo '{}' > users.json || true && \ - [ ! -f tickets.json ] && echo '{}' > tickets.json || true - -# Устанавливаем права доступа -RUN chown -R mcpanel:mcpanel /app && \ - chmod -R 755 /app && \ - chmod +x main.py - -# Переключаемся на непривилегированного пользователя -USER mcpanel - -# Health check -HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ - CMD curl -f http://localhost:${PORT}/health 2>/dev/null || \ - curl -f http://localhost:${PORT}/ 2>/dev/null || exit 1 - -# Expose порт EXPOSE 8000 -# Volumes для персистентных данных -VOLUME ["/app/servers", "/app/data", "/app/logs"] +HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \ + CMD curl -fsS "http://localhost:${PORT}/health" || exit 1 -# Используем tini как init процесс -ENTRYPOINT ["/usr/bin/tini", "--"] - -# Команда запуска -CMD ["sh", "-c", "python -m uvicorn main:app --host 0.0.0.0 --port ${PORT} --workers ${WORKERS}"] \ No newline at end of file +CMD ["sh", "-c", "uvicorn main:app --host 0.0.0.0 --port ${PORT:-8000} --workers ${WORKERS:-2}"] diff --git a/deploy/docker-compose.hosting.yml b/deploy/docker-compose.hosting.yml index 97116ac..7446a7b 100644 --- a/deploy/docker-compose.hosting.yml +++ b/deploy/docker-compose.hosting.yml @@ -1,4 +1,4 @@ -version: '3.8' +version: '3.8' services: backend: @@ -10,20 +10,17 @@ services: environment: PORT: 8000 WORKERS: 2 - PYTHONPATH: /app - DEBUG: 'false' volumes: - mc_servers:/app/servers - mc_data:/app/data - mc_logs:/app/logs networks: - - mc-panel-network + - mc-panel healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + test: ["CMD", "curl", "-fsS", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 - start_period: 60s frontend: image: ${FRONTEND_IMAGE:-registry.nevetime.ru/mc-panel-frontend:${IMAGE_TAG:-latest}} @@ -35,22 +32,18 @@ services: backend: condition: service_healthy networks: - - mc-panel-network + - mc-panel healthcheck: - test: ["CMD", "curl", "-f", "http://localhost/health"] + test: ["CMD", "wget", "-qO-", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 - start_period: 30s volumes: mc_servers: - driver: local mc_data: - driver: local mc_logs: - driver: local networks: - mc-panel-network: + mc-panel: driver: bridge diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index aaa6111..fce5d8a 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -1,61 +1,48 @@ -version: '3.8' +version: '3.8' services: - # Backend для разработки - backend-dev: + backend: build: context: ./backend dockerfile: Dockerfile - target: production container_name: mc-panel-backend-dev restart: unless-stopped ports: - "8000:8000" + env_file: + - ./backend/.env environment: - - PORT=8000 - - WORKERS=1 - - PYTHONPATH=/app - - DEBUG=true - - LOG_LEVEL=DEBUG + PORT: 8000 + WORKERS: 1 volumes: - # Монтируем исходный код для hot reload - ./backend:/app - mc_servers_dev:/app/servers - mc_data_dev:/app/data - mc_logs_dev:/app/logs + command: ["sh", "-c", "uvicorn main:app --host 0.0.0.0 --port 8000 --reload"] networks: - mc-panel-dev - command: ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"] - # Frontend для разработки - frontend-dev: + frontend: build: context: ./frontend dockerfile: Dockerfile - target: development + args: + VITE_API_URL: http://localhost:8000 container_name: mc-panel-frontend-dev restart: unless-stopped ports: - - "5173:5173" - volumes: - # Монтируем исходный код для hot reload - - ./frontend:/app - - /app/node_modules + - "3000:80" + depends_on: + - backend networks: - mc-panel-dev - environment: - - VITE_API_URL=http://localhost:8000 - depends_on: - - backend-dev volumes: mc_servers_dev: - driver: local mc_data_dev: - driver: local mc_logs_dev: - driver: local networks: mc-panel-dev: - driver: bridge \ No newline at end of file + driver: bridge diff --git a/docker-compose.yml b/docker-compose.yml index 1f53211..8fc3f72 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,59 +1,49 @@ -version: '3.8' +version: '3.8' services: - # Backend сервис backend: - image: registry.nevetime.ru/mc-panel-backend:${IMAGE_TAG:-latest} + image: ${BACKEND_IMAGE:-registry.nevetime.ru/mc-panel-backend:${IMAGE_TAG:-latest}} container_name: mc-panel-backend restart: unless-stopped - ports: - - "8000:8000" - environment: - - PORT=8000 - - WORKERS=2 - - PYTHONPATH=/app - - DEBUG=false env_file: - ./backend/.env + environment: + PORT: ${BACKEND_PORT:-8000} + WORKERS: ${BACKEND_WORKERS:-2} volumes: - mc_servers:/app/servers - mc_data:/app/data - mc_logs:/app/logs networks: - - mc-panel-network + - mc-panel healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:8000/health"] + test: ["CMD", "curl", "-fsS", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 - start_period: 60s - # Frontend сервис frontend: - image: registry.nevetime.ru/mc-panel-frontend:${IMAGE_TAG:-latest} + image: ${FRONTEND_IMAGE:-registry.nevetime.ru/mc-panel-frontend:${IMAGE_TAG:-latest}} container_name: mc-panel-frontend restart: unless-stopped ports: - - "80:80" + - "${FRONTEND_PORT:-80}:80" depends_on: - - backend + backend: + condition: service_healthy networks: - - mc-panel-network + - mc-panel healthcheck: - test: ["CMD", "curl", "-f", "http://localhost/health"] + test: ["CMD", "wget", "-qO-", "http://localhost/health"] interval: 30s timeout: 10s retries: 3 - start_period: 30s volumes: mc_servers: - driver: local mc_data: - driver: local mc_logs: - driver: local networks: - mc-panel-network: - driver: bridge \ No newline at end of file + mc-panel: + driver: bridge diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 0cb4491..34dcd15 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,207 +1,25 @@ -# ================================ -# MC Panel Frontend - Multi-Stage Dockerfile -# ================================ +FROM node:20-alpine AS build -# Stage 1: Build Stage -FROM node:20-alpine AS builder - -# Метаданные -LABEL maintainer="MC Panel Team" \ - version="2.0.0" \ - description="MC Panel Frontend - React Build Stage" \ - component="frontend" - -# Устанавливаем зависимости для сборки -RUN apk add --no-cache git python3 make g++ - -# Создаем рабочую директорию WORKDIR /app -# Копируем package files для кеширования зависимостей COPY package*.json ./ - -# Устанавливаем зависимости RUN npm ci --silent -# Копируем исходный код COPY . ./ -# Собираем приложение для production +ARG VITE_API_URL= +ENV VITE_API_URL=${VITE_API_URL} + RUN npm run build -# Проверяем размер сборки -RUN du -sh dist/ && \ - echo "Build completed successfully" +FROM nginx:1.27-alpine -# ================================ -# Stage 2: Production Stage (Nginx) -# ================================ -FROM nginx:alpine AS production +COPY nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=build /app/dist /usr/share/nginx/html -# Метаданные -LABEL maintainer="MC Panel Team" \ - version="2.0.0" \ - description="MC Panel Frontend - Nginx Production Server" \ - component="frontend" - -# Устанавливаем дополнительные пакеты -RUN apk add --no-cache curl tini - -# Создаем пользователя nginx если его нет -RUN addgroup -g 1000 -S mcpanel && \ - adduser -u 1000 -D -S -G mcpanel mcpanel - -# Копируем собранное приложение из builder stage -COPY --from=builder /app/dist /usr/share/nginx/html - -# Создаем кастомную конфигурацию Nginx -RUN cat > /etc/nginx/conf.d/default.conf << 'EOF' -server { - listen 80; - listen [::]:80; - server_name _; - - root /usr/share/nginx/html; - index index.html; - - # Gzip compression - gzip on; - gzip_vary on; - gzip_min_length 1024; - gzip_types text/plain text/css text/xml text/javascript application/javascript application/xml+rss application/json; - - # Security headers - add_header X-Frame-Options "SAMEORIGIN" always; - add_header X-Content-Type-Options "nosniff" always; - add_header X-XSS-Protection "1; mode=block" always; - add_header Referrer-Policy "no-referrer-when-downgrade" always; - - # Cache static assets - location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { - expires 1y; - add_header Cache-Control "public, immutable"; - } - - # Handle React Router (SPA) - location / { - try_files $uri $uri/ /index.html; - } - - # API proxy (если нужно) - location /api/ { - proxy_pass http://backend:8000/; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - # WebSocket proxy (если нужно) - location /ws/ { - proxy_pass http://backend:8000/ws/; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - } - - # Health check endpoint - location /health { - access_log off; - return 200 "healthy\n"; - add_header Content-Type text/plain; - } -} -EOF - -# Создаем кастомную конфигурацию nginx.conf -RUN cat > /etc/nginx/nginx.conf << 'EOF' -user nginx; -worker_processes auto; -error_log /var/log/nginx/error.log notice; -pid /var/run/nginx.pid; - -events { - worker_connections 1024; - use epoll; - multi_accept on; -} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - - sendfile on; - tcp_nopush on; - tcp_nodelay on; - keepalive_timeout 65; - types_hash_max_size 2048; - client_max_body_size 100M; - - include /etc/nginx/conf.d/*.conf; -} -EOF - -# Health check -HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ - CMD curl -f http://localhost/health || exit 1 - -# Expose порт EXPOSE 80 -# Используем tini как init процесс -ENTRYPOINT ["/sbin/tini", "--"] +HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \ + CMD wget -qO- http://localhost/health >/dev/null || exit 1 -# Команда запуска CMD ["nginx", "-g", "daemon off;"] - -# ================================ -# Stage 3: Development Stage -# ================================ -FROM node:20-alpine AS development - -# Метаданные -LABEL maintainer="MC Panel Team" \ - version="2.0.0" \ - description="MC Panel Frontend - Development Server" \ - component="frontend" - -# Устанавливаем зависимости для разработки -RUN apk add --no-cache git python3 make g++ - -# Создаем пользователя для разработки -RUN addgroup -g 1000 -S mcpanel && \ - adduser -u 1000 -D -S -G mcpanel mcpanel - -# Создаем рабочую директорию -WORKDIR /app - -# Меняем владельца директории -RUN chown mcpanel:mcpanel /app - -# Переключаемся на пользователя -USER mcpanel - -# Копируем package files -COPY --chown=mcpanel:mcpanel package*.json ./ - -# Устанавливаем зависимости -RUN npm ci - -# Копируем исходный код -COPY --chown=mcpanel:mcpanel . ./ - -# Expose порт для dev сервера -EXPOSE 5173 - -# Команда для разработки -CMD ["npm", "run", "dev"] \ No newline at end of file diff --git a/frontend/nginx.conf b/frontend/nginx.conf new file mode 100644 index 0000000..7a5635f --- /dev/null +++ b/frontend/nginx.conf @@ -0,0 +1,37 @@ +server { + listen 80; + server_name _; + + root /usr/share/nginx/html; + index index.html; + + location / { + try_files $uri $uri/ /index.html; + } + + location /api/ { + proxy_pass http://backend:8000; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location /ws/ { + proxy_pass http://backend:8000; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location = /health { + access_log off; + return 200 'ok'; + add_header Content-Type text/plain; + } +}