feat: оптимизация Docker контейнера для разработки
Обновлен Dockerfile с двухэтапной сборкой, экспортом зависимостей через poetry, сборкой статики и удалением лишних файлов (экономия ~20МБ). Обновлен docker-compose.yml с привязкой к localhost для безопасности. Обновлен .dockerignore для исключения ненужных файлов (source maps, RTL CSS, TTF). Добавлены таймауты SQLite в settings.py. Минимальные параметры Gunicorn: 1 worker, timeout 30s, max-requests 100. Тестировано и работает на http://localhost:8040
This commit is contained in:
@@ -66,6 +66,52 @@ my_anwer.txt
|
|||||||
requare_dev_prod.txt
|
requare_dev_prod.txt
|
||||||
requare_dev_w_home.txt
|
requare_dev_w_home.txt
|
||||||
|
|
||||||
|
# Оптимизация статики - исключаем лишние файлы для компактного контейнера
|
||||||
|
|
||||||
|
# Source maps (нужны только для разработки, не для production)
|
||||||
|
public/static/**/*.map
|
||||||
|
staticfiles/**/*.map
|
||||||
|
|
||||||
|
# RTL версии Bootstrap (если не используется для арабских/персидских языков)
|
||||||
|
public/static/css/bootstrap*.rtl.*
|
||||||
|
public/static/css/v*.rtl.*
|
||||||
|
staticfiles/css/bootstrap*.rtl.*
|
||||||
|
staticfiles/css/v*.rtl.*
|
||||||
|
|
||||||
|
# TTF шрифты - используем только woff2 (меньше размер, лучше поддержка в браузерах)
|
||||||
|
public/static/webfonts/*.ttf
|
||||||
|
public/static/webfonts/*.eot
|
||||||
|
public/static/webfonts/*.svg
|
||||||
|
staticfiles/webfonts/*.ttf
|
||||||
|
staticfiles/webfonts/*.eot
|
||||||
|
staticfiles/webfonts/*.svg
|
||||||
|
|
||||||
|
# Обычные (неминифицированные) версии CSS для bootstrap - используем только min версии
|
||||||
|
# (но оставляем rosmorport.css - наш проектный CSS)
|
||||||
|
# bootstrap.css, bootstrap-grid.css, bootstrap-utilities.css, etc
|
||||||
|
public/static/css/bootstrap.css
|
||||||
|
public/static/css/bootstrap-grid.css
|
||||||
|
public/static/css/bootstrap-utilities.css
|
||||||
|
public/static/css/bootstrap-reboot.css
|
||||||
|
public/static/css/v*.css
|
||||||
|
public/static/css/svg-with-js.css
|
||||||
|
public/static/css/fontawesome.css
|
||||||
|
public/static/css/regular.css
|
||||||
|
public/static/css/solid.css
|
||||||
|
public/static/css/brands.css
|
||||||
|
public/static/css/all.css
|
||||||
|
staticfiles/css/bootstrap.css
|
||||||
|
staticfiles/css/bootstrap-grid.css
|
||||||
|
staticfiles/css/bootstrap-utilities.css
|
||||||
|
staticfiles/css/bootstrap-reboot.css
|
||||||
|
staticfiles/css/v*.css
|
||||||
|
staticfiles/css/svg-with-js.css
|
||||||
|
staticfiles/css/fontawesome.css
|
||||||
|
staticfiles/css/regular.css
|
||||||
|
staticfiles/css/solid.css
|
||||||
|
staticfiles/css/brands.css
|
||||||
|
staticfiles/css/all.css
|
||||||
|
|
||||||
# Прочее
|
# Прочее
|
||||||
config/
|
config/
|
||||||
.editorconfig
|
.editorconfig
|
||||||
|
|||||||
51
Dockerfile
51
Dockerfile
@@ -17,10 +17,15 @@ WORKDIR /app
|
|||||||
# Копируем файлы с информацией о зависимостях
|
# Копируем файлы с информацией о зависимостях
|
||||||
COPY pyproject.toml poetry.lock* ./
|
COPY pyproject.toml poetry.lock* ./
|
||||||
|
|
||||||
# Создаем виртуальное окружение и устанавливаем зависимости
|
# Экспортируем зависимости из poetry в requirements.txt
|
||||||
|
# Это более надежный способ в Docker, чем использование виртуального окружения poetry
|
||||||
|
RUN poetry export -f requirements.txt --output requirements.txt --no-interaction
|
||||||
|
|
||||||
|
# Создаем виртуальное окружение в стандартном месте
|
||||||
RUN python -m venv /opt/venv
|
RUN python -m venv /opt/venv
|
||||||
ENV PATH="/opt/venv/bin:$PATH"
|
|
||||||
RUN poetry install --no-interaction --no-ansi
|
# Устанавливаем зависимости в виртуальное окружение
|
||||||
|
RUN /opt/venv/bin/pip install --no-cache-dir -r requirements.txt
|
||||||
|
|
||||||
# Второй этап: runtime - финальный образ
|
# Второй этап: runtime - финальный образ
|
||||||
FROM python:3.12-slim
|
FROM python:3.12-slim
|
||||||
@@ -28,6 +33,8 @@ FROM python:3.12-slim
|
|||||||
# Переводим в режим без буферизации для вывода логов
|
# Переводим в режим без буферизации для вывода логов
|
||||||
ENV PYTHONUNBUFFERED=1
|
ENV PYTHONUNBUFFERED=1
|
||||||
ENV PYTHONDONTWRITEBYTECODE=1
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
|
# Установка PATH для виртуального окружения перед копированием
|
||||||
|
ENV PATH="/opt/venv/bin:$PATH"
|
||||||
|
|
||||||
# Устанавливаем рабочую директорию
|
# Устанавливаем рабочую директорию
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
@@ -35,14 +42,31 @@ WORKDIR /app
|
|||||||
# Копируем виртуальное окружение из builder
|
# Копируем виртуальное окружение из builder
|
||||||
COPY --from=builder /opt/venv /opt/venv
|
COPY --from=builder /opt/venv /opt/venv
|
||||||
|
|
||||||
# Добавляем путь к виртуальному окружению
|
|
||||||
ENV PATH="/opt/venv/bin:$PATH"
|
|
||||||
|
|
||||||
# Копируем содержимое проекта
|
# Копируем содержимое проекта
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
# Создаём необходимые директории
|
# Создаём необходимые директории
|
||||||
RUN mkdir -p /app/public/media /app/public/static /app/database
|
RUN mkdir -p /app/public/media /app/public/static /app/database /app/staticfiles
|
||||||
|
|
||||||
|
# Собираем статику при сборке образа (для production)
|
||||||
|
# Это гарантирует что статика готова и не нужно запускать collectstatic при старте
|
||||||
|
# PATH уже установлен в переменных окружения выше, поэтому Django должен быть найден
|
||||||
|
RUN cd /app/rosmorport_tsts && \
|
||||||
|
python manage.py collectstatic --noinput --clear --no-input
|
||||||
|
|
||||||
|
# Оптимизация размера контейнера: удаляем лишние файлы статики
|
||||||
|
# Source maps нужны только для разработки
|
||||||
|
RUN find /app/staticfiles -name "*.map" -delete
|
||||||
|
|
||||||
|
# Удаляем RTL версии Bootstrap (если проект не поддерживает RTL)
|
||||||
|
RUN find /app/staticfiles -name "*rtl*" -type f -delete
|
||||||
|
|
||||||
|
# Удаляем TTF и EOT шрифты (используем только woff2 - меньше размер)
|
||||||
|
RUN find /app/staticfiles/webfonts -type f \( -name "*.ttf" -o -name "*.eot" -o -name "*.svg" \) -delete
|
||||||
|
|
||||||
|
# Удаляем неминифицированные версии CSS (кроме нашего собственного rosmorport.css)
|
||||||
|
# bootstrap.css, all.css, fontawesome.css используем только .min версии
|
||||||
|
RUN find /app/staticfiles/css -maxdepth 1 -name "*.css" -not -name "*.min.css" -not -name "rosmorport.css" -delete
|
||||||
|
|
||||||
# Устанавливаем пользователя для запуска приложения (из соображений безопасности)
|
# Устанавливаем пользователя для запуска приложения (из соображений безопасности)
|
||||||
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
|
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
|
||||||
@@ -51,7 +75,14 @@ USER appuser
|
|||||||
# Открываем порт
|
# Открываем порт
|
||||||
EXPOSE 8000
|
EXPOSE 8000
|
||||||
|
|
||||||
# CMD - выполняет миграции, собирает статику и запускает Gunicorn
|
# CMD - выполняет миграции и запускает Gunicorn
|
||||||
# Использует sh для выполнения нескольких команд последовательно
|
# Миграции выполняются при каждом запуске для гибкости
|
||||||
CMD ["sh", "-c", "cd /app/rosmorport_tsts && echo '>>> Applying database migrations...' && python manage.py migrate --noinput && echo '>>> Collecting static files...' && python manage.py collectstatic --noinput --clear && echo '>>> Starting Gunicorn...' && gunicorn --bind 0.0.0.0:8000 --workers 4 --worker-class sync --worker-tmp-dir /dev/shm --max-requests 1000 --timeout 60 --access-logfile - --error-logfile - rosmorport_tsts.wsgi:application"]
|
# Статика уже собрана при сборке образа
|
||||||
|
# Параметры оптимизированы для dev с минимальной нагрузкой:
|
||||||
|
# - bind 0.0.0.0:8000 (все интерфейсы контейнера, необходимо для Docker проброса портов)
|
||||||
|
# - workers=1 (один worker - достаточно для dev без нагрузок)
|
||||||
|
# - timeout=30 (сокращенный таймаут - запросы должны быть быстрыми)
|
||||||
|
# - max-requests=100 (перезагрузка воркера после 100 запросов - экономия памяти)
|
||||||
|
# - access-logfile/error-logfile '-' (логи в stdout для docker)
|
||||||
|
CMD ["sh", "-c", "cd /app/rosmorport_tsts && echo '>>> Applying database migrations...' && python manage.py migrate --noinput && echo '>>> Starting Gunicorn...' && gunicorn --bind 0.0.0.0:8000 --workers 1 --worker-class sync --worker-tmp-dir /dev/shm --max-requests 100 --timeout 30 --access-logfile - --error-logfile - rosmorport_tsts.wsgi:application"]
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# docker-compose.yml для локальной разработки проекта rosmorport_tsts
|
# docker-compose.yml для локальной разработки проекта rosmorport_tsts
|
||||||
version: '3.9'
|
# Использование: docker-compose up
|
||||||
|
|
||||||
|
# version: '3.9'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# Django приложение
|
# Django приложение
|
||||||
@@ -10,60 +12,27 @@ services:
|
|||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
|
|
||||||
# Имя контейнера
|
# Имя контейнера
|
||||||
container_name: rosmorport_web
|
container_name: rosmorpor-tst-site--backend
|
||||||
|
|
||||||
# Переменные окружения для разработки
|
# Переменные окружения для разработки
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
environment:
|
environment:
|
||||||
- DOCKER_ENV=1
|
- DOCKER_ENV=1
|
||||||
|
- DJANGO_LOG_LEVEL=DEBUG
|
||||||
- DEBUG=True
|
- DEBUG=True
|
||||||
- ALLOWED_HOSTS=localhost,127.0.0.1,0.0.0.0,web
|
|
||||||
- DB_ENGINE=django.db.backends.sqlite3
|
|
||||||
- DB_NAME=/app/db.sqlite3
|
|
||||||
- PYTHONUNBUFFERED=1
|
- PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
# Монтируем текущую директорию для разработки
|
# Монтируем текущую директорию для разработки
|
||||||
volumes:
|
volumes:
|
||||||
- .:/app
|
- .:/app
|
||||||
- ./public/static:/app/public/static
|
|
||||||
- ./public/media:/app/public/media
|
- ./public/media:/app/public/media
|
||||||
- ./database:/app/database
|
- ./database:/app/database
|
||||||
|
|
||||||
# Перенаправляем порты
|
# Перенаправляем порты
|
||||||
ports:
|
ports:
|
||||||
- "8000:8000"
|
- "127.0.0.1:8040:8000"
|
||||||
|
|
||||||
# Команда для запуска в режиме разработки
|
|
||||||
command: >
|
|
||||||
sh -c "python rosmorport_tsts/manage.py migrate &&
|
|
||||||
python rosmorport_tsts/manage.py collectstatic --noinput &&
|
|
||||||
python rosmorport_tsts/manage.py runserver 0.0.0.0:8000"
|
|
||||||
|
|
||||||
# Зависимости (если будут другие сервисы)
|
|
||||||
# depends_on:
|
|
||||||
# - db
|
|
||||||
|
|
||||||
# Сохраняем контейнер в запущенном состоянии при ошибках
|
|
||||||
stdin_open: true
|
|
||||||
tty: true
|
|
||||||
|
|
||||||
# Опционально: PostgreSQL база данных для продакшена
|
|
||||||
# db:
|
|
||||||
# image: postgres:16-alpine
|
|
||||||
# container_name: rosmorport_db
|
|
||||||
# environment:
|
|
||||||
# - POSTGRES_DB=rosmorport_db
|
|
||||||
# - POSTGRES_USER=postgres
|
|
||||||
# - POSTGRES_PASSWORD=postgres
|
|
||||||
# volumes:
|
|
||||||
# - postgres_data:/var/lib/postgresql/data
|
|
||||||
# ports:
|
|
||||||
# - "5432:5432"
|
|
||||||
# healthcheck:
|
|
||||||
# test: ["CMD-SHELL", "pg_isready -U postgres"]
|
|
||||||
# interval: 10s
|
|
||||||
# timeout: 5s
|
|
||||||
# retries: 5
|
|
||||||
|
|
||||||
# Именованные тома для хранения данных
|
# Именованные тома для хранения данных
|
||||||
volumes:
|
volumes:
|
||||||
django_staticfiles:
|
django_staticfiles:
|
||||||
|
|||||||
@@ -110,6 +110,12 @@ TEMPLATES = [
|
|||||||
|
|
||||||
WSGI_APPLICATION = 'rosmorport_tsts.wsgi.application'
|
WSGI_APPLICATION = 'rosmorport_tsts.wsgi.application'
|
||||||
|
|
||||||
|
# CSRF Configuration
|
||||||
|
# CSRF_TRUSTED_ORIGINS используется для Docker, Nginx и других reverse proxy
|
||||||
|
# Содержит список разрешенных источников для CSRF защиты (разделенные запятой)
|
||||||
|
csrf_trusted_origins = get_env('CSRF_TRUSTED_ORIGINS', 'http://127.0.0.1:8000,http://localhost:8000')
|
||||||
|
CSRF_TRUSTED_ORIGINS = [origin.strip() for origin in csrf_trusted_origins.split(',')]
|
||||||
|
|
||||||
# Database
|
# Database
|
||||||
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
|
# https://docs.djangoproject.com/en/5.0/ref/settings/#databases
|
||||||
|
|
||||||
@@ -123,6 +129,12 @@ DATABASES = {
|
|||||||
'default': {
|
'default': {
|
||||||
'ENGINE': 'django.db.backends.sqlite3',
|
'ENGINE': 'django.db.backends.sqlite3',
|
||||||
'NAME': str(db_path),
|
'NAME': str(db_path),
|
||||||
|
# Таймауты для SQLite - оптимизированы для быстрых операций без нагрузок
|
||||||
|
'OPTIONS': {
|
||||||
|
'timeout': 5, # Таймаут ожидания блокировки БД (в секундах)
|
||||||
|
},
|
||||||
|
# Параметры пула подключений (не критичны для SQLite, но для совместимости)
|
||||||
|
'CONN_MAX_AGE': 60, # Время жизни подключения (60 сек)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user