Docker/prod deployment:
- multi-stage Dockerfile (JDK21 build, JRE21 run), docker-compose.prod.yml,
nginx config for lms.our-place.ru, deploy.sh; DEPLOY/IMPORT guides (UI flow)
- Fix Docker 401: LMS_JWT_JWK_SET_URI for academic/progress; forward-headers
Variant distribution (lab page only):
- round-robin by student level, shared random queue across selected groups,
least-used variants, manual pins always preserved; occupied/dup labels
- setup page: single form + one «Сохранить всё», batch level/variant for
selected students (checkboxes)
Grades, defense, materials:
- publication gate + comment lists; defense CSV import (2/3 cols, quotes)
- additional task after defense ("начать заново"); enroll/unenroll students
from group page; temporary-password lock (no navigation until changed) and
persistent "Смена пароля"; forced change once
- chapter page /learn/{c}; header: LMS home, Войти, user -> dashboard,
compact theme toggle; responsive mobile header
- markdown: single newlines are soft breaks; highlight.js with light/dark themes
- lab/content imports ZIP-only (lab.yaml+README+variants/assets,
chapters tree+assets); duplicate lab numbers rejected; variant ordering
and date defaults honored
Fixes:
- 500 on student create (@MapsId set before persist); broken dialogs/JS refs in group page
6.3 KiB
Деплой LMS на сервер lms.our-place.ru
Стек целиком запускается в Docker. Java на сервере не устанавливается — приложение
собирается и работает внутри контейнеров (multi-stage Dockerfile: сборка на JDK 21,
запуск на JRE 21).
Компоненты:
| Сервис | Контейнер | Наружу |
|---|---|---|
| web (Thymeleaf UI) | lms-web |
127.0.0.1:8090 (проксирует nginx) |
| gateway | lms-gateway |
нет |
| identity / academic / progress | lms-* |
нет |
| PostgreSQL 18 | lms-postgres |
нет |
Данные лежат в именованных volume: lms_pgdata (БД), lms_submissions (решения),
lms_assets (картинки материалов).
0. Что нужно
- Сервер с Ubuntu 22.04/24.04 (или другим Linux с Docker), sudo/root.
- Домен
lms.our-place.ru, A-запись которого указывает на IP сервера. - Открытые порты 80 и 443 (443 — если настраиваете HTTPS).
1. Установка Docker
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker "$USER" # перелогиньтесь, чтобы работать без sudo
docker compose version # нужна версия v2
2. Получить код
sudo mkdir -p /opt/lms && sudo chown "$USER" /opt/lms
git clone <URL-репозитория> /opt/lms
cd /opt/lms
3. Настроить окружение
cp .env.prod.example .env.prod
nano .env.prod
Обязательно задайте надёжный LMS_DB_PASSWORD. Остальные значения по умолчанию подходят.
4. Собрать и запустить
./deploy/deploy.sh up
Скрипт соберёт образы (первый раз ~5–15 минут: скачиваются Gradle и зависимости) и поднимет контейнеры. Проверка:
docker compose -f docker-compose.prod.yml --env-file .env.prod ps
curl -fsS http://127.0.0.1:8090/actuator/health # {"status":"UP",...}
5. Nginx + HTTPS
sudo apt-get update && sudo apt-get install -y nginx certbot python3-certbot-nginx
sudo mkdir -p /var/www/certbot
sudo cp deploy/nginx/lms.our-place.ru.conf /etc/nginx/sites-available/lms.our-place.ru.conf
sudo ln -sf /etc/nginx/sites-available/lms.our-place.ru.conf /etc/nginx/sites-enabled/lms.our-place.ru.conf
sudo rm -f /etc/nginx/sites-enabled/default
sudo nginx -t && sudo systemctl reload nginx
sudo certbot --nginx -d lms.our-place.ru --redirect -m admin@our-place.ru --agree-tos
certbot --nginx сам добавит TLS-блок и редирект с HTTP на HTTPS. Автопродление
уже настроено пакетом (systemctl status certbot.timer).
6. Первый запуск приложения
Откройте https://lms.our-place.ru → откроется /setup → создайте администратора.
6a. Наполнение данными
Дальше всё через интерфейс: импорт групп (.xls), импорт лабораторной ZIP'ом,
раздача вариантов, оценки и защита, материалы. Подробный порядок с проверками —
в IMPORT.md. Файлы со списками студентов и выгрузками паролей —
персональные данные, держите их вне репозитория.
7. Обновление версии
cd /opt/lms
git pull
./deploy/deploy.sh up # пересоберёт изменённые образы и перезапустит
Миграции БД (Flyway) применяются автоматически при старте сервисов.
8. Резервное копирование
# БД
docker compose -f docker-compose.prod.yml --env-file .env.prod exec -T postgres \
pg_dump -U "$LMS_DB_USER" "$LMS_DB_NAME" | gzip > lms-$(date +%F).sql.gz
# Файлы (решения и материалы)
docker run --rm -v lms_lms_submissions:/sub -v lms_lms_assets:/assets -v "$PWD":/backup alpine \
tar czf /backup/lms-files-$(date +%F).tar.gz -C / sub assets
Восстановление БД: gunzip -c backup.sql.gz | docker compose ... exec -T postgres psql -U lms lms.
9. Диагностика
./deploy/deploy.sh ps
./deploy/deploy.sh logs web
./deploy/deploy.sh logs gateway
./deploy/deploy.sh logs identity
Типичные проблемы:
- web отдаёт 502 через nginx — контейнер
webне поднялся: смотритеlogs web. Часто причина — занят порт 8090 или не заданLMS_DB_PASSWORD(compose не стартует). - Страница входа открывается, но запросы падают — проверьте
logs gatewayиlogs identity; gateway должен получить JWKS от identity. - 401 на страницах после входа (Docker) — у backend-сервисов не задан адрес
JWKS: должно быть
LMS_JWT_JWK_SET_URI=http://identity:8081/api/v1/auth/jwks.json(уже прописано вdocker-compose.prod.ymlдля academic/progress/gateway). Внутри контейнераlocalhost:8081недоступен, поэтому токен не проверяется. - Не проходят загрузки больших ZIP — увеличьте
client_max_body_sizeв nginx (сейчас 120 МБ) иspring.servlet.multipart.max-request-size.
Замечания по безопасности
- PostgreSQL наружу не публикуется; связь между контейнерами — по внутренней сети
lms. - Публикуется только
127.0.0.1:8090, доступ снаружи — исключительно через nginx/TLS. .env.prodсодержит пароль БД и не коммитится (в.gitignore).- Пароль администратора задаётся вами на шаге 6; хранение — BCrypt.