From 44d6ef1da51cc7793d7969a958e13d3f73c2bd8b Mon Sep 17 00:00:00 2001 From: DeepAgent Date: Mon, 27 Oct 2025 13:04:00 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=BF=D1=82=D0=B8=D0=BC=D0=B8=D0=B7?= =?UTF-8?q?=D0=B0=D1=86=D0=B8=D1=8F=20=D1=81=D0=B1=D0=BE=D1=80=D0=BA=D0=B8?= =?UTF-8?q?=20Docker:=20=D1=83=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B7=D0=B0=D0=B2=D0=B8=D1=81=D0=B0=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BD=D0=B0=20yarn=20install?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Устранена двойная установка зависимостей в Dockerfile - Добавлены ENV переменные для пропуска ненужных бинарников - Создан .dockerignore для ускорения копирования файлов - Обновлены скрипты deploy.sh и update.sh с поддержкой --fast режима - Добавлена документация BUILD_OPTIMIZATION.md и QUICK_FIX.md Ожидаемое время сборки с --fast: 10-15 минут (было 30+ минут) --- .dockerignore | 73 ++++++++--------- BUILD_OPTIMIZATION.md | 132 ++++++++++++++++++++++++++++++ BUILD_OPTIMIZATION.pdf | Bin 0 -> 46056 bytes Dockerfile | 12 ++- QUICK_FIX.md | 177 +++++++++++++++++++++++++++++++++++++++++ deploy.sh | 46 ++++++++++- update.sh | 74 +++++++++++++++-- 7 files changed, 461 insertions(+), 53 deletions(-) create mode 100644 BUILD_OPTIMIZATION.md create mode 100644 BUILD_OPTIMIZATION.pdf create mode 100644 QUICK_FIX.md diff --git a/.dockerignore b/.dockerignore index 86bae41..c9458ff 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,33 +1,21 @@ -# Dependencies +# Зависимости node_modules nextjs_space/node_modules -npm-debug.log - -# Next.js build output -nextjs_space/.next -.next - -# Testing -coverage -.nyc_output - -# Misc -.DS_Store -*.pem - -# Environment variables (except example) -.env -.env.local -.env.development.local -.env.test.local -.env.production.local - -# Debug logs npm-debug.log* yarn-debug.log* yarn-error.log* +# Build +nextjs_space/.next +nextjs_space/out +nextjs_space/build +nextjs_space/dist + +# Тестирование +nextjs_space/coverage +nextjs_space/.nyc_output + # IDE .vscode .idea @@ -35,29 +23,34 @@ yarn-error.log* *.swo *~ +# OS +.DS_Store +Thumbs.db + +# Переменные окружения (они монтируются отдельно) +.env +.env.local +.env*.local +nextjs_space/.env* + # Git .git .gitignore -# Documentation (не нужны в образе) -README.md -README.deployment.md -DATABASE.md -DATABASE.pdf - -# Docker files +# Docker Dockerfile -docker-compose.yml +docker-compose*.yml .dockerignore -# Scripts +# Документация +README*.md +*.md + +# Логи и кеш +*.log +.cache + +# Скрипты развертывания *.sh - -# Backups -backups/ -*.sql -*.sql.gz - -# Config examples -nginx.conf.example traefik-config-example.yml +nginx.conf.example diff --git a/BUILD_OPTIMIZATION.md b/BUILD_OPTIMIZATION.md new file mode 100644 index 0000000..cb73642 --- /dev/null +++ b/BUILD_OPTIMIZATION.md @@ -0,0 +1,132 @@ + +# Оптимизация сборки Docker образа + +## Проблема: Медленная сборка на этапе "Building fresh packages" + +Сборка может занимать **15-30 минут** из-за компиляции нативных модулей (Prisma, bcryptjs и др.). + +## Внесенные оптимизации + +### 1. Устранена двойная установка зависимостей +**Было:** +```dockerfile +RUN yarn install --production --frozen-lockfile +RUN yarn install --frozen-lockfile +``` + +**Стало:** +```dockerfile +RUN yarn install --immutable --network-timeout 600000 +``` + +### 2. Добавлены переменные окружения для ускорения +```dockerfile +ENV SKIP_SASS_BINARY_DOWNLOAD_FOR_CI=true +ENV SKIP_NODE_SASS_TESTS=true +ENV CYPRESS_INSTALL_BINARY=0 +ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true +``` + +### 3. Создан .dockerignore +Исключены ненужные файлы из контекста сборки (логи, кеш, документация и т.д.). + +## Рекомендации при развертывании + +### Если сборка все еще медленная: + +#### Вариант 1: Увеличьте ресурсы Docker +```bash +# Проверьте текущие лимиты +docker info | grep -i "CPUs\|Memory" + +# Для Docker Desktop: Settings → Resources +# CPU: минимум 2 ядра, рекомендуется 4 +# RAM: минимум 4GB, рекомендуется 8GB +``` + +#### Вариант 2: Используйте готовый образ (рекомендуется) +Соберите образ один раз на мощной машине и загрузите в реестр: + +```bash +# На мощной машине +docker build -t global-it24:latest . +docker save global-it24:latest | gzip > global-it24-image.tar.gz + +# Перенесите файл на сервер и загрузите +docker load < global-it24-image.tar.gz +``` + +#### Вариант 3: Используйте BuildKit с кешированием +```bash +# Включите BuildKit +export DOCKER_BUILDKIT=1 + +# Соберите с кешем +docker build --build-arg BUILDKIT_INLINE_CACHE=1 -t global-it24:latest . +``` + +#### Вариант 4: Установите более быстрый линкер (на хосте) +```bash +# Для Ubuntu/Debian +sudo apt-get install -y mold + +# Добавьте в Dockerfile перед RUN yarn install +ENV CC=clang +ENV CXX=clang++ +ENV LD=mold +``` + +## Мониторинг прогресса сборки + +```bash +# В отдельном терминале следите за процессом +docker ps -a | grep build +docker stats + +# Проверьте логи подробнее +docker build --progress=plain -t global-it24:latest . +``` + +## Типичное время сборки + +| Конфигурация | Время | +|-------------|-------| +| 2 CPU, 4GB RAM | 20-30 минут | +| 4 CPU, 8GB RAM | 10-15 минут | +| 8 CPU, 16GB RAM | 5-8 минут | +| С кешем BuildKit | 2-5 минут | + +## Нормальное поведение + +✅ **Это нормально:** +- Предупреждения о peer dependencies (они не влияют на работу) +- Долгая компиляция на этапе "Building fresh packages" (10-20 минут) +- Множество предупреждений от Prisma и других пакетов + +❌ **Это проблема:** +- Сборка зависла более 45 минут без прогресса +- Ошибки (errors), а не предупреждения (warnings) +- Выход с кодом ошибки + +## Если сборка зависла намертво + +```bash +# Остановите сборку +Ctrl+C + +# Очистите все промежуточные контейнеры и кеш +docker builder prune -a -f + +# Попробуйте снова с --no-cache +docker build --no-cache -t global-it24:latest . +``` + +## Альтернатива: Многоступенчатая сборка на CI/CD + +Если у вас есть GitHub Actions, GitLab CI или Jenkins: + +1. Соберите образ на CI/CD сервере (обычно там больше ресурсов) +2. Загрузите в Docker Registry (Docker Hub, GitHub Registry, GitLab Registry) +3. На продакшн-сервере просто выполните `docker pull` + +Это самый быстрый и надежный способ для production. diff --git a/BUILD_OPTIMIZATION.pdf b/BUILD_OPTIMIZATION.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2cd5a1d3965e6ec093168219461f4daa13fe4648 GIT binary patch literal 46056 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

+&$0E1~#E* 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 literal 0 HcmV?d00001 diff --git a/Dockerfile b/Dockerfile index ed244f7..081f4c0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,11 +9,15 @@ WORKDIR /app # Копируем файлы зависимостей COPY nextjs_space/package.json nextjs_space/yarn.lock ./ -# Устанавливаем только production зависимости -RUN yarn install --production --frozen-lockfile --network-timeout 600000 +# Настройки для ускорения компиляции +ENV NODE_ENV=development +ENV SKIP_SASS_BINARY_DOWNLOAD_FOR_CI=true +ENV SKIP_NODE_SASS_TESTS=true +ENV CYPRESS_INSTALL_BINARY=0 +ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true -# Устанавливаем dev зависимости отдельно -RUN yarn install --frozen-lockfile --network-timeout 600000 +# Устанавливаем все зависимости одним вызовом +RUN yarn install --immutable --network-timeout 600000 # Стадия 2: Сборка приложения FROM node:18-alpine AS builder diff --git a/QUICK_FIX.md b/QUICK_FIX.md new file mode 100644 index 0000000..f59c164 --- /dev/null +++ b/QUICK_FIX.md @@ -0,0 +1,177 @@ +# 🚀 Быстрое решение проблемы зависания сборки + +## Проблема +Сборка зависла на этапе `[4/4] Building fresh packages...` при `yarn install --immutable` + +## ✅ Что было исправлено + +1. **Устранена двойная установка зависимостей** в Dockerfile +2. **Добавлены переменные окружения** для пропуска ненужных бинарников +3. **Создан .dockerignore** для ускорения копирования файлов +4. **Обновлены скрипты развертывания** с поддержкой быстрой сборки + +## 📋 Инструкция по развертыванию + +### Вариант 1: Первое развертывание (рекомендуется) + +```bash +cd /home/ubuntu/global_it24_landing + +# Остановите текущую сборку (если запущена) +docker compose down +docker builder prune -f + +# Запустите развертывание с быстрой сборкой +./deploy.sh --fast +``` + +**Ожидаемое время:** 10-15 минут (вместо 30+ минут) + +### Вариант 2: Если всё ещё медленно + +Если сборка всё равно занимает более 20 минут, увеличьте ресурсы Docker: + +```bash +# Проверьте текущие лимиты +docker info | grep -i "CPUs\|Memory" + +# Для Docker на Ubuntu (редактируйте daemon.json) +sudo nano /etc/docker/daemon.json +``` + +Добавьте или измените: +```json +{ + "default-runtime": "runc", + "builder": { + "gc": { + "enabled": true + } + } +} +``` + +Перезапустите Docker: +```bash +sudo systemctl restart docker +``` + +### Вариант 3: Использование готового образа (самый быстрый) + +Если у вас есть доступ к более мощной машине: + +**На мощной машине:** +```bash +cd /home/ubuntu/global_it24_landing +docker build -t global-it24:latest . +docker save global-it24:latest | gzip > global-it24-image.tar.gz +``` + +**Перенесите файл на сервер и загрузите:** +```bash +scp global-it24-image.tar.gz user@server:/home/ubuntu/ +ssh user@server +docker load < /home/ubuntu/global-it24-image.tar.gz +cd /home/ubuntu/global_it24_landing +docker compose up -d +``` + +## 🎯 Рекомендации + +### Для первого развертывания: +```bash +./deploy.sh --fast +``` + +### Для обновлений кода: +```bash +./update.sh --rebuild +``` + +### Для простого перезапуска (изменения в .env): +```bash +./update.sh +``` + +## ⏱️ Ожидаемое время сборки + +| Метод | Время | Когда использовать | +|-------|-------|-------------------| +| `./deploy.sh` | 20-30 мин | Первое развертывание без кеша | +| `./deploy.sh --fast` | 10-15 мин | Первое развертывание с кешем | +| `./update.sh --rebuild` | 5-10 мин | Обновление кода | +| `./update.sh` | ~10 сек | Изменения .env или перезапуск | + +## ℹ️ Что происходит при сборке + +1. **[1/11] Создание базового образа** (~30 сек) +2. **[2/11] Установка системных пакетов** (~1 мин) +3. **[3/11] Копирование файлов** (~10 сек) +4. **[4/11] yarn install** (~8-12 мин) ⚠️ Самый долгий этап +5. **[5/11] Сборка Next.js** (~2-3 мин) +6. **[6/11] Prisma generate** (~30 сек) +7. **[7/11-11/11] Финализация образа** (~1 мин) + +## ✅ Нормальное поведение + +**Это нормально:** +- Множество предупреждений о peer dependencies +- Долгая компиляция на "Building fresh packages" (8-12 минут) +- Предупреждения от ESLint, Prettier, Prisma + +**Это проблема:** +- Сборка зависла более 30 минут без прогресса +- Ошибки (errors), а не предупреждения (warnings) +- Выход с кодом ошибки + +## 🔍 Мониторинг прогресса + +В отдельном терминале: +```bash +# Следите за логами +docker compose logs -f web + +# Проверяйте использование ресурсов +docker stats + +# Подробные логи сборки +docker compose build --progress=plain +``` + +## 📝 После успешной сборки + +```bash +# Проверьте статус +./status.sh + +# Просмотрите логи +./logs.sh + +# Локальная проверка +curl http://localhost:3000 + +# Настройте Traefik для доступа из интернета +``` + +## 🆘 Если проблема не решена + +1. Проверьте доступные ресурсы: +```bash +free -h +df -h +docker system df +``` + +2. Очистите Docker кеш: +```bash +docker builder prune -a -f +docker system prune -a -f +``` + +3. Попробуйте пересобрать с нуля: +```bash +docker compose down -v +./deploy.sh +``` + +Если ничего не помогает, рассмотрите Вариант 3 (сборка на мощной машине). diff --git a/deploy.sh b/deploy.sh index 3967743..60abd9b 100755 --- a/deploy.sh +++ b/deploy.sh @@ -2,9 +2,43 @@ #!/bin/bash # Скрипт для быстрого развертывания Global-IT24 на Ubuntu с внешним Traefik +# Использование: +# ./deploy.sh - полная сборка без кеша (медленно, 15-30 минут) +# ./deploy.sh --fast - быстрая сборка с кешем (5-10 минут) set -e +FAST_BUILD=false + +# Парсинг аргументов +while [[ $# -gt 0 ]]; do + case $1 in + --fast) + FAST_BUILD=true + shift + ;; + --help|-h) + echo "Использование: $0 [--fast] [--help]" + echo "" + echo "Опции:" + echo " --fast Быстрая сборка с использованием кеша" + echo " --help Показать эту справку" + echo "" + echo "Примеры:" + echo " $0 # Полная сборка без кеша" + echo " $0 --fast # Быстрая сборка с кешем" + echo "" + echo "Рекомендация: используйте --fast для обновлений и пересборок" + exit 0 + ;; + *) + echo "❌ Неизвестный параметр: $1" + echo "Используйте --help для справки" + exit 1 + ;; + esac +done + echo "🚀 Развертывание Global-IT24..." # Проверка наличия .env файла @@ -31,8 +65,16 @@ echo "🛑 Остановка предыдущей версии..." docker compose down 2>/dev/null || true # Сборка нового образа -echo "🔨 Сборка Docker образа..." -docker compose build --no-cache +if [ "$FAST_BUILD" = true ]; then + echo "⚡ Быстрая сборка с использованием кеша (5-10 минут)..." + export DOCKER_BUILDKIT=1 + export COMPOSE_DOCKER_CLI_BUILD=1 + docker compose build +else + echo "🔨 Полная сборка Docker образа без кеша (15-30 минут)..." + echo "💡 Подсказка: используйте --fast для ускорения следующих сборок" + docker compose build --no-cache +fi # Запуск контейнера echo "▶️ Запуск контейнера..." diff --git a/update.sh b/update.sh index eb908ab..33afbc3 100755 --- a/update.sh +++ b/update.sh @@ -1,24 +1,84 @@ #!/bin/bash -# Скрипт для быстрого обновления приложения без пересборки +# Скрипт для обновления приложения +# Использование: +# ./update.sh - просто перезапуск (без пересборки) +# ./update.sh --rebuild - пересборка с кешем и перезапуск (5-10 минут) set -e +REBUILD=false + +# Парсинг аргументов +while [[ $# -gt 0 ]]; do + case $1 in + --rebuild|-r) + REBUILD=true + shift + ;; + --help|-h) + echo "Использование: $0 [--rebuild] [--help]" + echo "" + echo "Опции:" + echo " --rebuild, -r Пересобрать образ перед перезапуском" + echo " --help, -h Показать эту справку" + echo "" + echo "Примеры:" + echo " $0 # Просто перезапустить (быстро)" + echo " $0 --rebuild # Пересобрать и перезапустить" + echo "" + echo "Когда использовать --rebuild:" + echo " - Изменился код приложения" + echo " - Обновились зависимости (package.json)" + echo " - Изменилась конфигурация Next.js" + echo "" + echo "Когда НЕ нужен --rebuild:" + echo " - Изменились только переменные в .env" + echo " - Нужно применить миграции базы данных" + exit 0 + ;; + *) + echo "❌ Неизвестный параметр: $1" + echo "Используйте --help для справки" + exit 1 + ;; + esac +done + echo "🔄 Обновление Global-IT24..." -# Перезапуск контейнера -echo "🔄 Перезапуск контейнера..." -docker-compose restart +if [ "$REBUILD" = true ]; then + echo "🔨 Пересборка образа с использованием кеша (5-10 минут)..." + export DOCKER_BUILDKIT=1 + export COMPOSE_DOCKER_CLI_BUILD=1 + + # Остановка контейнера + docker compose down + + # Пересборка + docker compose build + + # Запуск + docker compose up -d +else + echo "🔄 Перезапуск контейнера без пересборки..." + docker compose restart +fi echo "⏳ Ожидание готовности..." sleep 5 -if docker-compose ps | grep -q "Up"; then +if docker compose ps | grep -q "Up"; then echo "✅ Обновление завершено!" - docker-compose ps + docker compose ps + echo "" + echo "📝 Полезные команды:" + echo " Просмотр логов: ./logs.sh" + echo " Статус: ./status.sh" + echo " С пересборкой: ./update.sh --rebuild" else echo "❌ Ошибка при перезапуске!" - docker-compose logs --tail=50 + docker compose logs --tail=50 exit 1 fi