- Platform support пользователь теперь создается с is_superuser=True для полного доступа - Добавлено сохранение credentials (домен:логин:пароль) в support_credentials.txt - Добавлен support_credentials.txt в .gitignore для безопасности - Обновлена документация развертывания на NAS Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
16 KiB
Развёртывание на TerraMaster F2-424 (TOS 6)
Требования
- TerraMaster NAS с TOS 6
- Docker и Docker Compose установлены
- SSH доступ к NAS
- 32 GB RAM (более чем достаточно)
Структура на NAS
/Volume1/DockerYAML/mix/ # Только docker-compose.yml
└── docker-compose.yml
/Volume1/DockerAppsData/mixapp/ # Всё остальное
├── app/ # Код приложения (весь проект)
│ ├── myproject/
│ ├── requirements.txt
│ └── docker/
│ ├── Dockerfile
│ ├── entrypoint.sh
│ └── .env.docker
├── postgres/ # База данных PostgreSQL
├── redis/ # Данные Redis
├── media/ # Загруженные файлы (фото товаров)
└── static/ # Статические файлы Django
Шаг 1: Подготовка директорий на NAS
# Подключаемся к NAS по SSH
ssh admin@<NAS_IP>
# Создаём директории
mkdir -p /Volume1/DockerAppsData/mixapp/{app,postgres,redis,media,static}
mkdir -p /Volume1/DockerYAML/mix
# Устанавливаем права (uid 1000 для контейнера appuser)
chown -R 1000:1000 /Volume1/DockerAppsData/mixapp/app
chown -R 1000:1000 /Volume1/DockerAppsData/mixapp/media
chown -R 1000:1000 /Volume1/DockerAppsData/mixapp/static
chmod -R u+rwX /Volume1/DockerAppsData/mixapp
chown -R 1000:1000 /Volume1/DockerYAML/mix
Шаг 2: Копирование файлов проекта на NAS
Вариант A: Через SCP (с Windows)
# Из папки проекта на Windows
cd C:\Users\team_\Desktop\test_qwen
# Копируем код приложения в папку данных
scp -r myproject requirements.txt docker .dockerignore admin@<NAS_IP>:/Volume1/DockerAppsData/mixapp/app/
# Копируем docker-compose.yml в папку YAML
scp docker/docker-compose.yml admin@<NAS_IP>:/Volume1/DockerYAML/mix/
Вариант B: Через общую папку SMB
- Подключите сетевую папку NAS
- Скопируйте содержимое папки проекта (
myproject/,requirements.txt,docker/и т.д.) в/Volume1/DockerAppsData/mixapp/app/ - Скопируйте
docker/docker-compose.ymlв/Volume1/DockerYAML/mix/
Шаг 3: Настройка переменных окружения
# На NAS
cd /Volume1/DockerAppsData/mixapp/app/docker
# Редактируем .env.docker
nano .env.docker
ВАЖНО! Измените следующие значения:
# Django settings
SECRET_KEY=ваш-очень-длинный-секретный-ключ-минимум-50-символов
DEBUG=False
ALLOWED_HOSTS=*
CSRF_TRUSTED_ORIGINS=https://mix.smaa.by,https://*.mix.smaa.by
DOMAIN_NAME=mix.smaa.by
# Database (PostgreSQL)
DB_NAME=inventory_db
DB_USER=postgres
DB_PASSWORD=ваш-надежный-пароль-postgres
DB_HOST=db
DB_PORT=5432
# Значения для официального образа Postgres (ДОЛЖНЫ СОВПАДАТЬ с DB_*)
POSTGRES_DB=inventory_db
POSTGRES_USER=postgres
POSTGRES_PASSWORD=ваш-надежный-пароль-postgres
# Redis
REDIS_HOST=redis
REDIS_PORT=6379
REDIS_DB=0
# Celery
CELERY_BROKER_URL=redis://redis:6379/0
# Platform Admin (администратор платформы - создаётся автоматически)
PLATFORM_ADMIN_EMAIL=admin@mix.smaa.by
PLATFORM_ADMIN_PASSWORD=ваш-надёжный-пароль-минимум-16-символов
PLATFORM_ADMIN_NAME=Platform Admin
# Django-tenants
PUBLIC_SCHEMA_DOMAIN=mix.smaa.by
TENANT_DOMAIN_BASE=mix.smaa.by
USE_HTTPS=True
⚠️ КРИТИЧЕСКИ ВАЖНО:
-
DB_PASSWORDиPOSTGRES_PASSWORDДОЛЖНЫ БЫТЬ ОДИНАКОВЫМИ!
Иначе Django не сможет подключиться к PostgreSQL. -
В
docker-compose.ymlу сервисаdbНЕ должно быть блокаenvironment:
Все переменные читаются напрямую из.env.dockerчерезenv_file. -
При смене пароля БД после первого запуска:
Простое изменениеPOSTGRES_PASSWORDв.env.dockerНЕ изменит пароль существующей базы.
Нужно пересоздать данные PostgreSQL:cd /Volume1/DockerYAML/mix docker-compose down rm -rf /Volume1/DockerAppsData/mixapp/postgres docker-compose up -d --build⚠️ Это удалит все данные в БД!
Генерация SECRET_KEY:
python3 -c "import secrets; print(secrets.token_urlsafe(64))"
Шаг 4: Исправление прав entrypoint.sh и файлов проекта
# Конвертируем из Windows формата (CRLF -> LF)
cd /Volume1/DockerAppsData/mixapp/app/myproject/docker
sed -i 's/\r$//' entrypoint.sh
chmod +x entrypoint.sh
# Убедитесь, что весь проект принадлежит UID 1000 (appuser внутри контейнера)
cd /Volume1/DockerAppsData/mixapp/app
chown -R 1000:1000 myproject
chmod -R u+rwX myproject
Шаг 5: Сборка и запуск
cd /Volume1/DockerYAML/mix
# Запускаем в фоновом режиме (автоматически соберет образы, используя пути из yml)
docker-compose up -d --build
# Проверяем статус
docker-compose ps
# Смотрим логи
docker-compose logs -f
Шаг 6: Первичная настройка
При первом запуске автоматически:
- Создаётся база данных PostgreSQL
- Применяются миграции Django
- Собираются статические файлы
- Создаётся public tenant
- Создаётся PlatformAdmin из переменных
PLATFORM_ADMIN_*в.env.docker
Проверка работоспособности:
# Проверяем что все контейнеры работают
docker-compose ps
# Должны быть в статусе "Up":
# - mix_postgres
# - mix_redis
# - mix_web
# - mix_celery_worker
# - mix_celery_beat
Шаг 7: Настройка Nginx (на NAS или внешний)
Пример конфигурации nginx:
# Upstream для Django
upstream mix_django {
server 127.0.0.1:8000;
}
# HTTP -> HTTPS редирект
server {
listen 80;
server_name mix.smaa.by *.mix.smaa.by;
return 301 https://$host$request_uri;
}
# HTTPS сервер
server {
listen 443 ssl http2;
server_name mix.smaa.by *.mix.smaa.by;
# SSL сертификаты (Let's Encrypt или свои)
ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;
# Безопасность
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# Лимиты
client_max_body_size 50M;
# Статические файлы
location /static/ {
alias /Volume1/DockerAppsData/mixapp/static/;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Медиа файлы
location /media/ {
alias /Volume1/DockerAppsData/mixapp/media/;
expires 7d;
add_header Cache-Control "public";
}
# Django приложение
location / {
proxy_pass http://mix_django;
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 support (если понадобится)
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Таймауты
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
}
}
Создание тенантов (магазинов)
Рекомендуемый способ: Через форму регистрации и активацию в админке.
- Пользователь заполняет форму на
https://mix.smaa.by/register/ - PlatformAdmin входит в
https://mix.smaa.by/admin/ - В разделе "Заявки на регистрацию" нажимает "Активировать"
При активации автоматически:
- Создаётся тенант и домен
- Применяются миграции
- Создаётся владелец (CustomUser)
- Инициализируются данные (склад, статусы и т.д.)
- Отправляется email с ссылкой для установки пароля
Архитектура пользователей
| Модель | Schema | Доступ |
|---|---|---|
PlatformAdmin |
public | Django Admin везде |
CustomUser |
tenant | Только фронтенд |
PlatformAdmin может войти в Django Admin любого тенанта для техподдержки.
Полезные команды
# Переходим в папку с docker-compose.yml
cd /Volume1/DockerYAML/mix
# Перезапуск всех контейнеров
docker-compose restart
# Перезапуск только web
docker-compose restart web
# Просмотр логов конкретного сервиса
docker-compose logs -f web
docker-compose logs -f celery-worker
# Выполнение команд Django
docker-compose exec web python manage.py shell
docker-compose exec web python manage.py createsuperuser
docker-compose exec web python manage.py migrate_schemas --shared
# Остановка
docker-compose down
# Остановка с удалением volumes (ОСТОРОЖНО - удалит данные!)
docker-compose down -v
Резервное копирование
База данных:
# Создание бэкапа
docker-compose exec db pg_dump -U postgres inventory_db > backup_$(date +%Y%m%d).sql
# Восстановление
cat backup.sql | docker-compose exec -T db psql -U postgres inventory_db
Медиа файлы:
# Бэкап медиа
tar -czvf media_backup_$(date +%Y%m%d).tar.gz /Volume1/DockerAppsData/mixapp/media/
Обновление приложения
cd /Volume1/DockerYAML/mix
# Остановить контейнеры
docker-compose down
# Обновить код в /Volume1/DockerAppsData/mixapp/app/
# (скопировать новые файлы myproject/, requirements.txt, docker/)
# ⚠️ КРИТИЧЕСКИ ВАЖНО: После КАЖДОГО обновления кода настроить права доступа!
cd /Volume1/DockerAppsData/mixapp/app
chown -R 1000:1000 myproject
chmod -R u+rwX myproject
# Вернуться в папку с docker-compose.yml
cd /Volume1/DockerYAML/mix
# Пересобрать образы
docker-compose build --no-cache
# Запустить
docker-compose up -d
⚠️ ВАЖНО: Если после обновления кода контейнеры не запускаются или тенанты недоступны (404), первым делом проверьте права доступа командами выше!
Мониторинг
# Статус контейнеров
docker-compose ps
# Использование ресурсов
docker stats
# Логи в реальном времени
docker-compose logs -f --tail=100
Возможные проблемы
1. Ошибка "permission denied" для entrypoint.sh
sed -i 's/\r$//' entrypoint.sh
chmod +x entrypoint.sh
2. PostgreSQL не запускается
# Проверьте логи
docker-compose logs db
# Возможно нужны права на директорию
sudo chown -R 999:999 /Volume1/DockerAppsData/mixapp/postgres
3. Celery не подключается к Redis
# Проверьте что Redis запущен
docker-compose logs redis
# Проверьте сеть
docker-compose exec web ping redis
4. Статические файлы не отображаются
# Пересоберите статику
docker-compose exec web python manage.py collectstatic --noinput
# Проверьте права
sudo chown -R 1000:1000 /Volume1/DockerAppsData/mixapp/static
5. Ошибка "password authentication failed for user postgres"
Причина: DB_PASSWORD и POSTGRES_PASSWORD в .env.docker не совпадают, или в docker-compose.yml у сервиса db есть блок environment с дефолтными значениями ${DB_PASSWORD:-postgres}.
Решение:
- Откройте
/Volume1/DockerAppsData/mixapp/app/myproject/docker/.env.docker - Убедитесь, что
DB_PASSWORDиPOSTGRES_PASSWORDОДИНАКОВЫЕ - Проверьте
docker-compose.yml— у сервисаdbдолжно быть толькоenv_file, БЕЗ блокаenvironment:db: image: postgres:15-alpine env_file: - /Volume1/DockerAppsData/mixapp/app/myproject/docker/.env.docker # НЕ ДОЛЖНО БЫТЬ: # environment: # - POSTGRES_PASSWORD=${DB_PASSWORD:-postgres} - Пересоздайте базу данных:
cd /Volume1/DockerYAML/mix docker-compose down rm -rf /Volume1/DockerAppsData/mixapp/postgres docker-compose up -d --build - Проверьте, что пароли совпадают внутри контейнера:
Оба должны показывать одинаковое значение.
docker exec -it mix_postgres env | grep -E 'POSTGRES_PASSWORD|DB_PASSWORD'
6. Ошибка "Permission denied" для /app/manage.py
Причина: Файлы проекта на хосте принадлежат не тому пользователю (не UID 1000).
Решение:
cd /Volume1/DockerAppsData/mixapp/app
chown -R 1000:1000 myproject
chmod -R u+rwX myproject
cd /Volume1/DockerYAML/mix
docker-compose restart web celery-worker celery-beat
7. Новый тенант создан, но его поддомен возвращает HTTP 404
Причина: Чаще всего — контейнер web постоянно перезапускается из-за Permission denied на /app/manage.py, и Django не успевает запуститься.
Диагностика:
-
Проверьте, что домен создан в базе:
docker exec -it mix_web python manage.py shellfrom tenants.models import Client, Domain for domain in Domain.objects.all(): print(f"Domain: {domain.domain}, Tenant: {domain.tenant.schema_name}")Если домен есть — проблема не в базе.
-
Посмотрите логи контейнера:
docker logs -f mix_webЕсли видите множество повторяющихся сообщений:
python: can't open file '/app/manage.py': [Errno 13] Permission denied Waiting for PostgreSQL...Это значит, что контейнер падает и перезапускается.
Решение:
cd /Volume1/DockerAppsData/mixapp/app
chown -R 1000:1000 myproject
chmod -R u+rwX myproject
cd /Volume1/DockerYAML/mix
docker-compose restart web celery-worker celery-beat
После этого контейнер перестанет падать, Django запустится, и поддомен тенанта станет доступен.