diff --git a/Dockerfile b/Dockerfile index d183be8..239d077 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,16 +4,25 @@ FROM python:3.13-slim-bookworm # Install UV (ultra-fast Python package installer) from Astral.sh COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/ +# Create non-root user for security +RUN groupadd -r appuser && useradd -r -g appuser appuser + # Ensure Python output is sent straight to terminal without buffering ENV PYTHONUNBUFFERED=1 \ - PYTHONDONTWRITEBYTECODE=1 + PYTHONDONTWRITEBYTECODE=1 \ + UV_SYSTEM_PYTHON=1 # ====================== # SYSTEM DEPENDENCIES # ====================== RUN apt-get update && \ - apt-get install -y --no-install-recommends curl gettext && \ - apt-get clean && rm -rf /var/lib/apt/lists/* + apt-get install -y --no-install-recommends \ + curl \ + gettext \ + ca-certificates && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/* && \ + rm -rf /tmp/* /var/tmp/* # Set working directory inside container WORKDIR /app @@ -21,31 +30,38 @@ WORKDIR /app # ====================== # DEPENDENCY INSTALLATION # ====================== -# Copies the dependency files (py project.tool and uv.lock) to /app. -COPY pyproject.toml uv.lock ./ +# Copy dependency files with proper ownership +COPY --chown=appuser:appuser pyproject.toml uv.lock ./ -# Install Python dependencies using UV: -# --locked: ensures exact versions from lockfile are used -# Copies the rest of the project code to /app. -RUN uv sync --locked +# Install Python dependencies using UV +RUN uv sync --locked --no-dev # ====================== # APPLICATION CODE # ====================== +# Copy entrypoint script first +COPY --chown=appuser:appuser entrypoint.sh /app/entrypoint.sh +RUN chmod +x /app/entrypoint.sh + # Copy the rest of the application code -# Note: This is done after dependency installation for better caching -COPY . . +COPY --chown=appuser:appuser . . -# Copies the script entrypoint.sh in /app. -# Makes it executable (chmod +x). -COPY entrypoint.sh /app/entrypoint.sh -RUN chmod +x /app/entrypoint.sh +# Create directories for Django with proper permissions +RUN mkdir -p /app/static /app/media && \ + chown -R appuser:appuser /app # ====================== # RUNTIME CONFIGURATION # ====================== +# Switch to non-root user +USER appuser + # Expose the port Django runs on EXPOSE 8000 +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD curl -f http://localhost:8000/health/ || exit 1 + # Launches the application through a script entrypoint.sh ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/Makefile b/Makefile index 56e2119..fa5fe25 100644 --- a/Makefile +++ b/Makefile @@ -1,31 +1,129 @@ +# ====================== +# VARIABLES +# ====================== USERID := $(shell id -u) GROUPID := $(shell id -g) PYTHON := docker compose run -u $(USERID):$(GROUPID) --rm django uv run +DOCKER_COMPOSE := docker compose +RUFF := uvx ruff -collectstatic: +# ====================== +# HELP +# ====================== +.PHONY: help +help: ## Show this help message + @echo "Available commands:" + @awk 'BEGIN {FS = ":.*##"; printf "\n"} /^[a-zA-Z_-]+:.*?##/ { printf " %-20s %s\n", $$1, $$2 } /^##@/ { printf "\n%s\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + +# ====================== +# DOCKER MANAGEMENT +# ====================== +.PHONY: build up down restart logs clean +build: ## Build Docker images + $(DOCKER_COMPOSE) build + +up: ## Start all services + $(DOCKER_COMPOSE) up -d + +down: ## Stop all services + $(DOCKER_COMPOSE) down + +restart: ## Restart all services + $(DOCKER_COMPOSE) restart + +logs: ## Show logs for all services + $(DOCKER_COMPOSE) logs -f + +clean: ## Clean up Docker resources + $(DOCKER_COMPOSE) down -v --remove-orphans + docker system prune -f + +# ====================== +# DJANGO MANAGEMENT +# ====================== +.PHONY: collectstatic startapp makemigrations migrate createsuperuser shell reset_db +collectstatic: ## Collect static files $(PYTHON) manage.py collectstatic --noinput -c -startapp: +startapp: ## Create new Django app (usage: make startapp app=myapp) $(PYTHON) manage.py startapp ${app} -makemigrations: +makemigrations: ## Create database migrations $(PYTHON) manage.py makemigrations ${app} -migrate: +migrate: ## Apply database migrations $(PYTHON) manage.py migrate ${app} -createsuperuser: +createsuperuser: ## Create Django superuser $(PYTHON) manage.py createsuperuser -shell: +shell: ## Open Django shell $(PYTHON) manage.py shell_plus -reset_db: +reset_db: ## Reset database $(PYTHON) manage.py reset_db -format: - uvx ruff check --fix apps config && uvx ruff check --select I --fix apps config && uvx ruff format apps config +# ====================== +# CODE QUALITY +# ====================== +.PHONY: format lint check test +format: ## Format code with ruff + $(RUFF) check --fix apps config + $(RUFF) check --select I --fix apps config + $(RUFF) format apps config + +lint: ## Run linting checks + $(RUFF) check apps config + +check: ## Run all code quality checks + $(RUFF) check apps config + $(RUFF) format --check apps config + +test: ## Run tests + $(PYTHON) manage.py test -run: - $(PYTHON) manage.py migrate +# ====================== +# DEVELOPMENT +# ====================== +.PHONY: run dev install requirements +run: migrate ## Run Django development server $(PYTHON) manage.py runserver 0.0.0.0:8000 + +dev: up ## Start development environment + @echo "Development environment started" + @echo "Django: http://localhost:8000" + @echo "PostgreSQL: localhost:5432" + +install: ## Install dependencies + uv sync --locked + +requirements: ## Update requirements + uv lock + +# ====================== +# PRODUCTION +# ====================== +.PHONY: prod-build prod-up prod-down +prod-build: ## Build production images + $(DOCKER_COMPOSE) -f docker-compose.prod.yml build + +prod-up: ## Start production environment + $(DOCKER_COMPOSE) -f docker-compose.prod.yml up -d + +prod-down: ## Stop production environment + $(DOCKER_COMPOSE) -f docker-compose.prod.yml down + +# ====================== +# UTILITIES +# ====================== +.PHONY: backup restore health +backup: ## Create database backup + $(DOCKER_COMPOSE) exec postgres pg_dump -U $$POSTGRES_USER $$POSTGRES_DB > backup_$$(date +%Y%m%d_%H%M%S).sql + +restore: ## Restore database from backup (usage: make restore file=backup.sql) + $(DOCKER_COMPOSE) exec -T postgres psql -U $$POSTGRES_USER $$POSTGRES_DB < ${file} + +health: ## Check services health + $(DOCKER_COMPOSE) ps + @echo "\n--- Service Health ---" + @curl -f http://localhost:8000/health/ || echo "Django service not responding" diff --git a/README.md b/README.md index 49525b7..1f162aa 100644 --- a/README.md +++ b/README.md @@ -1,182 +1,269 @@ +# 📚 PythonBooks + [![Ruff](https://github.com/khoshov/pythonbooks/actions/workflows/ruff.yml/badge.svg)](https://github.com/khoshov/pythonbooks/actions/workflows/ruff.yml) +[![Python](https://img.shields.io/badge/Python-3.13-blue.svg)](https://python.org) +[![Django](https://img.shields.io/badge/Django-5.0-green.svg)](https://djangoproject.com) +[![Docker](https://img.shields.io/badge/Docker-Enabled-blue.svg)](https://docker.com) +[![UV](https://img.shields.io/badge/UV-Package%20Manager-orange.svg)](https://astral.sh) -## Структура +> Современное Django-приложение для управления книгами с использованием UV, Docker и современных инструментов разработки. -
+## 🚀 Быстрый старт -```python +### Вариант 1: Docker (рекомендуется) +```bash +git clone https://github.com/khoshov/pythonbooks.git +cd pythonbooks +cp .env.example .env +make dev +``` -pythonbooks -│ -├── .github/workflows/ -│ └── ruff.yml -│ -├── apps/ -│ └── books/ -├── config/ -│ -├── .dockerignore -├── .env -├── .gitignore -├── .pre-commit-config.yaml -├── 🐳 docker-compose.yml -├── 🐳 Dockerfile -├── 🐳 entrypoint.sh - запускается внутри контейнера при старте, для миграций, запуска сервера и т.п. -├── Makefile -│ -├── manage.py -│ -├── 📦 pyproject.toml -├── README.md -├── 📦 requirements.txt -└── 📦 uv.lock +### Вариант 2: Локальная установка +```bash +git clone https://github.com/khoshov/pythonbooks.git +cd pythonbooks +uv sync +cp .env.example .env +uv run manage.py migrate +uv run manage.py runserver ``` -
+## 📋 Требования ---- +- **Python 3.13+** +- **Docker & Docker Compose** (для контейнеризации) +- **UV** (менеджер пакетов) +- **PostgreSQL** (база данных) -## Установка и использование UV +## 🏗️ Структура проекта -
-📦 Способы установки UV +``` +pythonbooks/ +├── 🐳 docker-compose.yml # Конфигурация Docker Compose +├── 🐳 Dockerfile # Образ приложения +├── 🐳 entrypoint.sh # Точка входа контейнера +├── 📦 pyproject.toml # Конфигурация проекта и зависимости +├── 📦 uv.lock # Файл блокировки зависимостей +├── 🔧 Makefile # Команды для разработки +├── 📝 .env.example # Пример переменных окружения +├── 🔒 .pre-commit-config.yaml # Конфигурация pre-commit хуков +│ +├── apps/ +│ └── books/ # Django приложение для книг +│ ├── scrapers/ # Скрейперы для сбора данных +│ ├── models.py # Модели данных +│ ├── views.py # Представления +│ └── admin.py # Админ-панель +│ +├── config/ # Настройки Django +│ ├── settings.py # Основные настройки +│ ├── urls.py # URL конфигурация +│ └── wsgi.py # WSGI приложение +│ +└── .github/workflows/ # CI/CD пайплайны + └── ruff.yml # Проверка кода с Ruff +``` -### 1. Установка через автономные установщики (рекомендуется) +## 🛠️ Команды разработки -**Для macOS и Linux:** +### Основные команды ```bash -curl -LsSf https://astral.sh/uv/install.sh | sh +make help # Показать все доступные команды +make dev # Запустить среду разработки +make build # Собрать Docker образы +make up # Запустить все сервисы +make down # Остановить все сервисы +make logs # Показать логи +make clean # Очистить Docker ресурсы ``` -**Для Windows (PowerShell):** -```powershell -powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" +### Django команды +```bash +make migrate # Применить миграции +make makemigrations # Создать миграции +make createsuperuser # Создать суперпользователя +make shell # Открыть Django shell +make collectstatic # Собрать статические файлы +make startapp app=myapp # Создать новое приложение ``` -### 2. Установка через PyPI (альтернативный способ) +### Качество кода ```bash -pip install uv +make format # Отформатировать код +make lint # Проверить код линтером +make check # Запустить все проверки +make test # Запустить тесты ``` -### Обновление UV -После установки вы можете обновить UV до последней версии: +### Утилиты ```bash -uv self update +make backup # Создать резервную копию БД +make restore file=backup.sql # Восстановить из резервной копии +make health # Проверить состояние сервисов ``` -🔗 Подробнее об установке: [Официальная документация](https://docs.astral.sh/uv/getting-started/installation/) -
+## 🐳 Docker конфигурация ---- +### Сервисы +- **django**: Основное приложение Django +- **postgres**: База данных PostgreSQL -
-🚀 Основные команды UV +### Особенности +- Использование non-root пользователя для безопасности +- Healthcheck для мониторинга состояния +- Именованные volumes для постоянства данных +- Изолированная сеть для сервисов -### Управление Python-окружением +## 📦 Управление зависимостями с UV -**Установка конкретной версии Python:** +### Установка UV ```bash -uv python install 3.13 # Установит Python 3.13 -``` +# macOS/Linux +curl -LsSf https://astral.sh/uv/install.sh | sh -### Управление зависимостями +# Windows (PowerShell) +powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" +``` -**Синхронизация зависимостей проекта:** +### Основные команды UV ```bash -uv sync # Аналог pip install + pip-compile +uv sync # Синхронизировать зависимости +uv add package # Добавить пакет +uv remove package # Удалить пакет +uv run command # Запустить команду в окружении +uv python install 3.13 # Установить Python 3.13 ``` -**Запуск команд в окружении проекта:** +## 🔍 Линтинг и форматирование + +Проект использует **Ruff** для проверки качества кода: + ```bash -uv run # Например: uv run pytest +# Проверка кода +uvx ruff check . + +# Автоматическое исправление +uvx ruff check --fix . + +# Форматирование +uvx ruff format . ``` -**Запуск Django-сервера:** +### Pre-commit хуки ```bash -uv run manage.py runserver # Альтернатива python manage.py runserver -``` -
+# Установка pre-commit +uv add --dev pre-commit ---- +# Установка хуков +pre-commit install -
-🔍 Интеграция с Ruff +# Запуск вручную +pre-commit run --all-files +``` -### [Ruff](https://github.com/astral-sh/ruff) - это молниеносный линтер для Python, также разработанный Astral. +## 🔧 Конфигурация -**Установка Ruff через UV:** -```bash -uvx ruff # Установит последнюю версию Ruff -``` +### Переменные окружения +Скопируйте `.env.example` в `.env` и настройте: -**Проверка кода с помощью Ruff:** ```bash -uvx ruff check . # Проверит все файлы в текущей директории +# Базовые настройки +DEBUG=True +SECRET_KEY=your-secret-key +ALLOWED_HOSTS=localhost,127.0.0.1 + +# База данных +POSTGRES_DB=pythonbooks +POSTGRES_USER=postgres +POSTGRES_PASSWORD=your-password ``` -**Для отправки в github без проверки локально, использовать:** +### Настройки для продакшена ```bash -git commit -m "feat: comment" --no-verify +DEBUG=False +SECURE_SSL_REDIRECT=True +SESSION_COOKIE_SECURE=True +CSRF_COOKIE_SECURE=True ``` -**Полный список поддерживаемых опций ruff** +## 🚀 Деплой + +### Продакшен с Docker ```bash -ruff check --help +make prod-build # Собрать продакшен образы +make prod-up # Запустить продакшен +make prod-down # Остановить продакшен ``` +### Здоровье приложения ```bash -ruff check --fix . # базовый линтинг с автоисправлением -ruff check --exclude tests/ . # игнорировать папку tests/ -ruff check --target-version py310 . # проверка кода для Python 3.10+ -ruff check --select / --ignore # выбор правил (например, --select=E501,F401) +curl http://localhost:8000/health/ # Проверка состояния ``` -
+## 📝 Особенности проекта ---- +### Скрейпинг книг +- Автоматический сбор данных о книгах +- Настраиваемые скрейперы в `apps/books/scrapers/` +- Контроль частоты запросов -
-🔍 автоматическая проверка Ruff перед коммитом +### Администрирование +- Расширенная админ-панель Django +- Управление книгами и авторами +- Массовые операции -[Ruff](https://github.com/astral-sh/ruff) - это молниеносный линтер для Python, также разработанный Astral. +### API +- RESTful API для работы с данными +- Аутентификация и авторизация +- Документация API -**Установить pre-commit:** -```bash -uv pip install pre-commit -``` +## 🤝 Участие в разработке -**Добавьте конфиг .pre-commit-config.yaml:** -```bash -repos: - - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.11.10 # Актуальная версия Ruff (проверьте на GitHub) - hooks: - - id: ruff - args: [--fix] # Автоматически исправляет ошибки - - id: ruff-format # Проверка форматирования (если нужно) -``` +1. Форкните репозиторий +2. Создайте ветку для функции: `git checkout -b feature/amazing-feature` +3. Зафиксируйте изменения: `git commit -m 'Add amazing feature'` +4. Отправьте в ветку: `git push origin feature/amazing-feature` +5. Создайте Pull Request -**Установите хуки в репозиторий:** -```bash -pre-commit install -``` -Теперь Ruff будет запускаться перед каждым коммитом. +### Правила разработки +- Используйте `make format` перед коммитом +- Все тесты должны проходить +- Добавляйте тесты для новой функциональности +- Следуйте PEP 8 стандартам + +## 📊 Мониторинг -**Проверить работу вручную:** +### Логи ```bash -pre-commit run --all-files +make logs # Все логи +docker-compose logs django # Только Django ``` -Теперь Ruff будет запускаться перед каждым коммитом. -
+### Метрики +- Health checks для контейнеров +- Мониторинг состояния БД +- Отслеживание производительности ---- +## 🔗 Полезные ссылки -## Запуск проекта в Docker +- [Django Documentation](https://docs.djangoproject.com/) +- [UV Documentation](https://docs.astral.sh/uv/) +- [Ruff Documentation](https://docs.astral.sh/ruff/) +- [Docker Documentation](https://docs.docker.com/) +- [PostgreSQL Documentation](https://www.postgresql.org/docs/) -**Сборка и запуск контейнеров:** -```bash -docker-compose build --no-cache -docker-compose up # Соберет и запустит сервисы -``` \ No newline at end of file +## 📄 Лицензия + +Этот проект лицензирован под MIT License - см. файл [LICENSE](LICENSE) для деталей. + +## 🆘 Поддержка + +Если у вас есть вопросы или проблемы: +1. Проверьте [Issues](https://github.com/khoshov/pythonbooks/issues) +2. Создайте новый Issue с подробным описанием +3. Используйте `make health` для диагностики + +--- + +**Разработано с ❤️ используя современные инструменты Python** \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 0633a2b..9d4e2d2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,3 +1,5 @@ +version: '3.8' + services: django: build: . @@ -15,14 +17,33 @@ services: depends_on: postgres: condition: service_healthy + restart: unless-stopped + networks: + - pythonbooks-network postgres: - image: postgres + image: postgres:15-alpine + container_name: pythonbooks-postgres ports: - "5432:5432" env_file: - .env volumes: - - ./pgdata:/var/lib/postgresql/data + - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + restart: unless-stopped + networks: + - pythonbooks-network + +volumes: + postgres_data: + driver: local + +networks: + pythonbooks-network: + driver: bridge diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index e69de29..0000000