Django в production окружении
Production развертывание Django требует специальных настроек безопасности, производительности и мониторинга. Правильная конфигурация критически важна для стабильной работы сайта в реальных условиях.
Структура production настроек
Создай отдельный файл настроек для production. Раздели настройки на несколько файлов:
Основные production настройки
Создай файл settings/production.py
:
1import os
2 from pathlib import Path
3 from .base import *
4
5 # Базовые production настройки
6 DEBUG = False
7 TEMPLATE_DEBUG = False
8
9 # Безопасность
10 SECRET_KEY = os.environ.get('SECRET_KEY')
11 if not SECRET_KEY:
12 raise ValueError('SECRET_KEY environment variable is required')
13
14 # Разрешенные хосты
15 ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '').split(',')
16 if not ALLOWED_HOSTS or ALLOWED_HOSTS == ['']:
17 raise ValueError('ALLOWED_HOSTS environment variable is required')
18
19 # HTTPS настройки
20 SECURE_SSL_REDIRECT = True
21 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
22 SESSION_COOKIE_SECURE = True
23 CSRF_COOKIE_SECURE = True
24 SECURE_HSTS_SECONDS = 31536000 # 1 год
25 SECURE_HSTS_INCLUDE_SUBDOMAINS = True
26 SECURE_HSTS_PRELOAD = True
27
28 # Безопасность заголовков
29 SECURE_CONTENT_TYPE_NOSNIFF = True
30 SECURE_BROWSER_XSS_FILTER = True
31 X_FRAME_OPTIONS = 'DENY'
32
33 # CSRF защита
34 CSRF_COOKIE_HTTPONLY = True
35 CSRF_COOKIE_AGE = 31449600 # 1 год
36 CSRF_TRUSTED_ORIGINS = os.environ.get('CSRF_TRUSTED_ORIGINS', '').split(',')
37
38 # База данных PostgreSQL
39 DATABASES = {
40 'default': {
41 'ENGINE': 'django.db.backends.postgresql',
42 'NAME': os.environ.get('DB_NAME'),
43 'USER': os.environ.get('DB_USER'),
44 'PASSWORD': os.environ.get('DB_PASSWORD'),
45 'HOST': os.environ.get('DB_HOST', 'localhost'),
46 'PORT': os.environ.get('DB_PORT', '5432'),
47 'OPTIONS': {
48 'sslmode': 'require',
49 'connect_timeout': 10,
50 },
51 'CONN_MAX_AGE': 600, # 10 минут
52 'CONN_HEALTH_CHECKS': True,
53 }
54 }
55
56 # Кэширование Redis
57 CACHES = {
58 'default': {
59 'BACKEND': 'django_redis.cache.RedisCache',
60 'LOCATION': os.environ.get('REDIS_URL', 'redis://localhost:6379/1'),
61 'OPTIONS': {
62 'CLIENT_CLASS': 'django_redis.client.DefaultClient',
63 'CONNECTION_POOL_KWARGS': {
64 'max_connections': 50,
65 'retry_on_timeout': True,
66 },
67 'SERIALIZER': 'django_redis.serializers.json.JSONSerializer',
68 },
69 'KEY_PREFIX': 'django_cache',
70 'TIMEOUT': 300, # 5 минут по умолчанию
71 },
72 'sessions': {
73 'BACKEND': 'django_redis.cache.RedisCache',
74 'LOCATION': os.environ.get('REDIS_URL', 'redis://localhost:6379/1'),
75 'OPTIONS': {
76 'CLIENT_CLASS': 'django_redis.client.DefaultClient',
77 },
78 'KEY_PREFIX': 'session',
79 }
80 }
81
82 # Сессии в Redis
83 SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
84 SESSION_CACHE_ALIAS = 'sessions'
85
86 # Статические файлы
87 STATIC_ROOT = BASE_DIR / 'staticfiles'
88 STATIC_URL = '/static/'
89
90 # Медиа файлы
91 MEDIA_ROOT = BASE_DIR / 'media'
92 MEDIA_URL = '/media/'
93
94 # Логирование
95 LOGGING = {
96 'version': 1,
97 'disable_existing_loggers': False,
98 'formatters': {
99 'verbose': {
100 'format': '{levelname} {asctime} {module} {process:d} {thread:d} {message}',
101 'style': '{',
102 },
103 'simple': {
104 'format': '{levelname} {message}',
105 'style': '{',
106 },
107 },
108 'handlers': {
109 'file': {
110 'level': 'INFO',
111 'class': 'logging.handlers.RotatingFileHandler',
112 'filename': BASE_DIR / 'logs' / 'django.log',
113 'maxBytes': 1024 * 1024 * 10, # 10 MB
114 'backupCount': 5,
115 'formatter': 'verbose',
116 },
117 'console': {
118 'level': 'INFO',
119 'class': 'logging.StreamHandler',
120 'formatter': 'simple',
121 },
122 },
123 'loggers': {
124 'django': {
125 'handlers': ['file', 'console'],
126 'level': 'INFO',
127 'propagate': False,
128 },
129 'django.db.backends': {
130 'handlers': ['file'],
131 'level': 'WARNING',
132 'propagate': False,
133 },
134 'myapp': {
135 'handlers': ['file', 'console'],
136 'level': 'INFO',
137 'propagate': False,
138 },
139 },
140 'root': {
141 'handlers': ['console'],
142 'level': 'WARNING',
143 },
144 }
Настройка email
Настрой отправку email для production:
1# Email настройки
2 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
3 EMAIL_HOST = os.environ.get('EMAIL_HOST', 'smtp.gmail.com')
4 EMAIL_PORT = int(os.environ.get('EMAIL_PORT', 587))
5 EMAIL_USE_TLS = True
6 EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER')
7 EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD')
8 EMAIL_USE_SSL = False
9
10 # Настройки по умолчанию
11 DEFAULT_FROM_EMAIL = os.environ.get('DEFAULT_FROM_EMAIL', 'noreply@yourdomain.com')
12 SERVER_EMAIL = os.environ.get('SERVER_EMAIL', 'server@yourdomain.com')
13
14 # Админы для получения ошибок
15 ADMINS = [
16 ('Admin Name', 'admin@yourdomain.com'),
17 ]
18
19 # Менеджеры для получения 404 ошибок
20 MANAGERS = ADMINS
Настройка Celery для фоновых задач
Настрой Celery для production:
1# Celery настройки
2 CELERY_BROKER_URL = os.environ.get('CELERY_BROKER_URL', 'redis://localhost:6379/0')
3 CELERY_RESULT_BACKEND = os.environ.get('CELERY_RESULT_BACKEND', 'redis://localhost:6379/0')
4
5 # Настройки производительности
6 CELERY_WORKER_CONCURRENCY = int(os.environ.get('CELERY_WORKER_CONCURRENCY', 4))
7 CELERY_TASK_ACKS_LATE = True
8 CELERY_WORKER_PREFETCH_MULTIPLIER = 1
9 CELERY_TASK_REJECT_ON_WORKER_LOST = True
10
11 # Мониторинг задач
12 CELERY_TASK_SOFT_TIME_LIMIT = 300 # 5 минут
13 CELERY_TASK_TIME_LIMIT = 600 # 10 минут
14
15 # Роутинг задач
16 CELERY_TASK_ROUTES = {
17 'myapp.tasks.*': {'queue': 'default'},
18 'myapp.tasks.heavy_tasks.*': {'queue': 'heavy'},
19 'myapp.tasks.email_tasks.*': {'queue': 'email'},
20 }
21
22 # Очереди
23 CELERY_TASK_DEFAULT_QUEUE = 'default'
24 CELERY_TASK_DEFAULT_EXCHANGE = 'default'
25 CELERY_TASK_DEFAULT_ROUTING_KEY = 'default'
Настройка мониторинга Sentry
Интегрируй Sentry для отслеживания ошибок:
1import sentry_sdk
2 from sentry_sdk.integrations.django import DjangoIntegration
3 from sentry_sdk.integrations.redis import RedisIntegration
4 from sentry_sdk.integrations.celery import CeleryIntegration
5
6 # Sentry настройки
7 SENTRY_DSN = os.environ.get('SENTRY_DSN')
8 if SENTRY_DSN:
9 sentry_sdk.init(
10 dsn=SENTRY_DSN,
11 integrations=[
12 DjangoIntegration(),
13 RedisIntegration(),
14 CeleryIntegration(),
15 ],
16 traces_sample_rate=0.1, # 10% запросов
17 profiles_sample_rate=0.1,
18 environment=os.environ.get('ENVIRONMENT', 'production'),
19 release=os.environ.get('GIT_COMMIT_SHA', 'unknown'),
20 before_send=lambda event, hint: event,
21)
Настройка Gunicorn
Создай файл gunicorn.conf.py
:
1import multiprocessing
2import os
3
4# Базовые настройки
5bind = os.environ.get('GUNICORN_BIND', '0.0.0.0:8000')
6workers = int(os.environ.get('GUNICORN_WORKERS', multiprocessing.cpu_count() * 2 + 1))
7worker_class = os.environ.get('GUNICORN_WORKER_CLASS', 'sync')
8worker_connections = int(os.environ.get('GUNICORN_WORKER_CONNECTIONS', 1000))
9
10# Таймауты
11timeout = int(os.environ.get('GUNICORN_TIMEOUT', 30))
12keepalive = int(os.environ.get('GUNICORN_KEEPALIVE', 2))
13graceful_timeout = int(os.environ.get('GUNICORN_GRACEFUL_TIMEOUT', 30))
14
15# Логирование
16accesslog = os.environ.get('GUNICORN_ACCESS_LOG', '-')
17errorlog = os.environ.get('GUNICORN_ERROR_LOG', '-')
18loglevel = os.environ.get('GUNICORN_LOG_LEVEL', 'info')
19
20# Безопасность
21limit_request_line = 4094
22limit_request_fields = 100
23limit_request_field_size = 8190
24
25# Производительность
26max_requests = int(os.environ.get('GUNICORN_MAX_REQUESTS', 1000))
27max_requests_jitter = int(os.environ.get('GUNICORN_MAX_REQUESTS_JITTER', 100))
28preload_app = True
29
30# Мониторинг
31statsd_host = os.environ.get('STATSD_HOST', 'localhost:8125')
32statsd_prefix = os.environ.get('STATSD_PREFIX', 'gunicorn')
Docker конфигурация
Создай Dockerfile
для production:
1# Используй официальный Python образ
2FROM python:3.11-slim
3
4# Установи системные зависимости
5RUN apt-get update && apt-get install -y \
6 gcc \
7 postgresql-client \
8 && rm -rf /var/lib/apt/lists/*
9
10# Создай пользователя для безопасности
11RUN useradd --create-home --shell /bin/bash app
12
13# Установи рабочую директорию
14WORKDIR /app
15
16# Скопируй requirements
17COPY requirements.txt .
18
19# Установи Python зависимости
20RUN pip install --no-cache-dir -r requirements.txt
21
22# Скопируй код приложения
23COPY . .
24
25# Создай директории для логов и статики
26RUN mkdir -p logs staticfiles media && \
27 chown -R app:app logs staticfiles media
28
29# Переключись на пользователя app
30USER app
31
32# Собери статические файлы
33RUN python manage.py collectstatic --noinput
34
35# Открой порт
36EXPOSE 8000
37
38# Запусти приложение
39CMD ["gunicorn", "--config", "gunicorn.conf.py", "project.wsgi:application"]
Docker Compose для production
Создай docker-compose.prod.yml
:
1version: '3.8'
2
3 services:
4 web:
5 build: .
6 restart: unless-stopped
7 ports:
8 - "8000:8000"
9 environment:
10 - ENVIRONMENT=production
11 - SECRET_KEY=${SECRET_KEY}
12 - ALLOWED_HOSTS=${ALLOWED_HOSTS}
13 - DB_NAME=${DB_NAME}
14 - DB_USER=${DB_USER}
15 - DB_PASSWORD=${DB_PASSWORD}
16 - DB_HOST=db
17 - REDIS_URL=redis://redis:6379/1
18 - CELERY_BROKER_URL=redis://redis:6379/0
19 - CELERY_RESULT_BACKEND=redis://redis:6379/0
20 - SENTRY_DSN=${SENTRY_DSN}
21 depends_on:
22 - db
23 - redis
24 volumes:
25 - static_volume:/app/staticfiles
26 - media_volume:/app/media
27 - ./logs:/app/logs
28 networks:
29 - app_network
30
31 db:
32 image: postgres:15
33 restart: unless-stopped
34 environment:
35 - POSTGRES_DB=${DB_NAME}
36 - POSTGRES_USER=${DB_USER}
37 - POSTGRES_PASSWORD=${DB_PASSWORD}
38 volumes:
39 - postgres_data:/var/lib/postgresql/data
40 networks:
41 - app_network
42
43 redis:
44 image: redis:7-alpine
45 restart: unless-stopped
46 command: redis-server --appendonly yes
47 volumes:
48 - redis_data:/data
49 networks:
50 - app_network
51
52 celery:
53 build: .
54 restart: unless-stopped
55 command: celery -A project worker -l info
56 environment:
57 - ENVIRONMENT=production
58 - DB_NAME=${DB_NAME}
59 - DB_USER=${DB_USER}
60 - DB_PASSWORD=${DB_PASSWORD}
61 - DB_HOST=db
62 - REDIS_URL=redis://redis:6379/1
63 - CELERY_BROKER_URL=redis://redis:6379/0
64 - CELERY_RESULT_BACKEND=redis://redis:6379/0
65 depends_on:
66 - db
67 - redis
68 volumes:
69 - ./logs:/app/logs
70 networks:
71 - app_network
72
73 nginx:
74 image: nginx:alpine
75 restart: unless-stopped
76 ports:
77 - "80:80"
78 - "443:443"
79 volumes:
80 - ./nginx.conf:/etc/nginx/nginx.conf
81 - ./ssl:/etc/nginx/ssl
82 - static_volume:/app/staticfiles
83 - media_volume:/app/media
84 depends_on:
85 - web
86 networks:
87 - app_network
88
89 volumes:
90 postgres_data:
91 redis_data:
92 static_volume:
93 media_volume:
94
95 networks:
96 app_network:
97 driver: bridge
Nginx конфигурация
Создай nginx.conf
:
1events {
2 worker_connections 1024;
3 }
4
5http {
6 include /etc/nginx/mime.types;
7 default_type application/octet-stream;
8
9 # Логирование
10 log_format main '$remote_addr - $remote_user [$time_local] "$request" '
11 '$status $body_bytes_sent "$http_referer" '
12 '"$http_user_agent" "$http_x_forwarded_for"';
13
14 access_log /var/log/nginx/access.log main;
15 error_log /var/log/nginx/error.log warn;
16
17 # Основные настройки
18 sendfile on;
19 tcp_nopush on;
20 tcp_nodelay on;
21 keepalive_timeout 65;
22 types_hash_max_size 2048;
23 client_max_body_size 100M;
24
25 # Gzip сжатие
26 gzip on;
27 gzip_vary on;
28 gzip_min_length 1024;
29 gzip_proxied any;
30 gzip_comp_level 6;
31 gzip_types
32 text/plain
33 text/css
34 text/xml
35 text/javascript
36 application/json
37 application/javascript
38 application/xml+rss
39 application/atom+xml
40 image/svg+xml;
41
42 # Upstream для Django
43 upstream django {
44 server web:8000;
45 }
46
47 # HTTP -> HTTPS редирект
48 server {
49 listen 80;
50 server_name _;
51 return 301 https://$host$request_uri;
52 }
53
54 # HTTPS сервер
55 server {
56 listen 443 ssl http2;
57 server_name yourdomain.com;
58
59 # SSL сертификаты
60 ssl_certificate /etc/nginx/ssl/cert.pem;
61 ssl_certificate_key /etc/nginx/ssl/key.pem;
62 ssl_protocols TLSv1.2 TLSv1.3;
63 ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
64 ssl_prefer_server_ciphers off;
65 ssl_session_cache shared:SSL:10m;
66 ssl_session_timeout 10m;
67
68 # Безопасность
69 add_header X-Frame-Options DENY;
70 add_header X-Content-Type-Options nosniff;
71 add_header X-XSS-Protection "1; mode=block";
72 add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
73
74 # Статические файлы
75 location /static/ {
76 alias /app/staticfiles/;
77 expires 1y;
78 add_header Cache-Control "public, immutable";
79 access_log off;
80 }
81
82 # Медиа файлы
83 location /media/ {
84 alias /app/media/;
85 expires 1y;
86 add_header Cache-Control "public";
87 access_log off;
88 }
89
90 # Django приложение
91 location / {
92 proxy_pass http://django;
93 proxy_set_header Host $host;
94 proxy_set_header X-Real-IP $remote_addr;
95 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
96 proxy_set_header X-Forwarded-Proto $scheme;
97 proxy_redirect off;
98 proxy_connect_timeout 30s;
99 proxy_send_timeout 30s;
100 proxy_read_timeout 30s;
101 }
102
103 # Health check
104 location /health/ {
105 access_log off;
106 return 200 "healthy\n";
107 add_header Content-Type text/plain;
108 }
109 }
110}
Переменные окружения
Создай файл .env.production
:
1# Django настройки
2ENVIRONMENT=production
3SECRET_KEY=your-super-secret-key-here
4ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com
5DEBUG=False
6
7# База данных
8DB_NAME=django_prod
9DB_USER=django_user
10DB_PASSWORD=strong_password_here
11DB_HOST=localhost
12DB_PORT=5432
13
14# Redis
15REDIS_URL=redis://localhost:6379/1
16CELERY_BROKER_URL=redis://localhost:6379/0
17CELERY_RESULT_BACKEND=redis://localhost:6379/0
18
19# Email
20EMAIL_HOST=smtp.gmail.com
21EMAIL_PORT=587
22EMAIL_HOST_USER=your-email@gmail.com
23EMAIL_HOST_PASSWORD=your-app-password
24DEFAULT_FROM_EMAIL=noreply@yourdomain.com
25SERVER_EMAIL=server@yourdomain.com
26
27# Sentry
28SENTRY_DSN=https://your-sentry-dsn-here
29
30# Gunicorn
31GUNICORN_WORKERS=4
32GUNICORN_TIMEOUT=30
33GUNICORN_MAX_REQUESTS=1000
34
35# Celery
36CELERY_WORKER_CONCURRENCY=4
37
38# CSRF
39CSRF_TRUSTED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
Скрипты развертывания
Создай скрипт для автоматического развертывания:
1#!/bin/bash
2# deploy.sh
3
4set -e
5
6echo "🚀 Начинаем развертывание..."
7
8# Обновляем код
9echo "📥 Обновляем код..."
10git pull origin main
11
12# Активируем виртуальное окружение
13echo "🐍 Активируем Python окружение..."
14source venv/bin/activate
15
16# Устанавливаем зависимости
17echo "📦 Устанавливаем зависимости..."
18pip install -r requirements.txt
19
20# Применяем миграции
21echo "🗄️ Применяем миграции..."
22python manage.py migrate --noinput
23
24# Собираем статические файлы
25echo "📁 Собираем статические файлы..."
26python manage.py collectstatic --noinput
27
28# Перезапускаем сервисы
29echo "🔄 Перезапускаем сервисы..."
30sudo systemctl restart gunicorn
31sudo systemctl restart celery
32sudo systemctl restart nginx
33
34# Проверяем статус
35echo "✅ Проверяем статус сервисов..."
36sudo systemctl status gunicorn
37sudo systemctl status celery
38sudo systemctl status nginx
39
40echo "🎉 Развертывание завершено!"
Мониторинг и логирование
Настрой мониторинг production окружения:
1# settings/production.py - добавь в конец
2
3# Мониторинг производительности
4if os.environ.get('ENABLE_PROFILING'):
5 MIDDLEWARE.append('django_profiler.middleware.ProfilerMiddleware')
6 PROFILER = {
7 'enabled': True,
8 'storage': 'django_profiler.storage.FileStorage',
9 'base_dir': BASE_DIR / 'profiles',
10 }
11
12# Prometheus метрики
13if os.environ.get('ENABLE_METRICS'):
14 INSTALLED_APPS.append('django_prometheus')
15 MIDDLEWARE.insert(0, 'django_prometheus.middleware.PrometheusBeforeMiddleware')
16 MIDDLEWARE.append('django_prometheus.middleware.PrometheusAfterMiddleware')
17
18# Health check endpoint
19HEALTH_CHECK = {
20 'DISK_USAGE_MAX': 90, # Процент использования диска
21 'MEMORY_MIN': 100, # Минимум свободной памяти в MB
22}
Тестирование production настроек
Создай тесты для проверки production конфигурации:
1from django.test import TestCase, override_settings
2from django.conf import settings
3from django.core.cache import cache
4from django.db import connection
5
6class ProductionSettingsTest(TestCase):
7 @override_settings(DEBUG=False)
8 def test_debug_is_disabled(self):
9 """Проверяем, что DEBUG отключен в production"""
10 self.assertFalse(settings.DEBUG)
11
12 def test_secret_key_is_set(self):
13 """Проверяем, что SECRET_KEY установлен"""
14 self.assertIsNotNone(settings.SECRET_KEY)
15 self.assertNotEqual(settings.SECRET_KEY, 'your-secret-key-here')
16
17 def test_allowed_hosts_configured(self):
18 """Проверяем, что ALLOWED_HOSTS настроен"""
19 self.assertIsNotNone(settings.ALLOWED_HOSTS)
20 self.assertNotEqual(settings.ALLOWED_HOSTS, [])
21
22 def test_ssl_redirect_enabled(self):
23 """Проверяем, что SSL редирект включен"""
24 self.assertTrue(settings.SECURE_SSL_REDIRECT)
25
26 def test_csrf_cookies_secure(self):
27 """Проверяем, что CSRF куки защищены"""
28 self.assertTrue(settings.CSRF_COOKIE_SECURE)
29
30 def test_session_cookies_secure(self):
31 """Проверяем, что сессионные куки защищены"""
32 self.assertTrue(settings.SESSION_COOKIE_SECURE)
33
34 def test_database_connection(self):
35 """Проверяем подключение к базе данных"""
36 with connection.cursor() as cursor:
37 cursor.execute("SELECT 1")
38 result = cursor.fetchone()
39 self.assertEqual(result[0], 1)
40
41 def test_cache_connection(self):
42 """Проверяем подключение к кэшу"""
43 cache.set('test_key', 'test_value', 1)
44 self.assertEqual(cache.get('test_key'), 'test_value')
Лучшие практики production
- Безопасность: Всегда используй HTTPS, валидируй входные данные, обновляй зависимости
- Производительность: Кэшируй статику, используй CDN, оптимизируй запросы к БД
- Мониторинг: Настрой логирование, метрики, алерты для критических ошибок
- Резервное копирование: Автоматизируй бэкапы БД и файлов
- Масштабирование: Используй балансировщики нагрузки, горизонтальное масштабирование
- CI/CD: Автоматизируй тестирование и развертывание
- Документация: Веди документацию по развертыванию и настройкам
- Тестирование: Тестируй production настройки в staging окружении
Частые ошибки и их решения
Ошибка: "SECRET_KEY not set"
Решение: Убедись, что переменная окружения SECRET_KEY установлена
Ошибка: "ALLOWED_HOSTS not configured"
Решение: Настрой ALLOWED_HOSTS с правильными доменами
Ошибка: "Database connection failed"
Решение: Проверь настройки БД и доступность PostgreSQL
Ошибка: "Static files not found"
Решение: Запусти collectstatic и проверь STATIC_ROOT
Ошибка: "Permission denied"
Решение: Проверь права доступа к файлам и директориям
FAQ
Q: Как собрать статические файлы для production?
A: Используй python manage.py collectstatic --noinput
и настрой STATIC_ROOT в настройках.
Q: Нужно ли использовать виртуальное окружение в production?
A: Да, это изолирует зависимости проекта и предотвращает конфликты версий.
Q: Как мониторить производительность Django в production?
A: Используй Sentry для ошибок, Prometheus для метрик, и настрой логирование.
Q: Можно ли использовать SQLite в production?
A: Нет, SQLite не подходит для production. Используй PostgreSQL или MySQL.
Q: Как настроить автоматические бэкапы?
A: Используй cron для регулярных бэкапов БД и rsync для файлов.
Q: Нужно ли использовать Docker в production?
A: Docker упрощает развертывание и обеспечивает консистентность окружений.