first commit

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-06 21:59:09 +03:00
commit 79b37d1891
14 changed files with 1478 additions and 0 deletions
+383
View File
@@ -0,0 +1,383 @@
# PhotoHost — Фото-хостинг
Современный фото-хостинг на **Python (Flask)**, **PostgreSQL** и **Docker Compose**.
- Красивая главная страница с drag-and-drop загрузкой
- Галерея загруженных фото
- Копирование прямых ссылок на изображения
- Хранение метаданных в PostgreSQL, файлов — в Docker volume
---
## Структура проекта
```
фотохостинг/
├── app/
│ ├── __init__.py # Flask-приложение и модель Photo
│ ├── routes.py # Маршруты (загрузка, галерея, API)
│ ├── templates/ # HTML-шаблоны
│ └── static/ # CSS и JavaScript
├── uploads/ # Локальная папка (в Docker — volume)
├── docker-compose.yml # Оркестрация web + PostgreSQL
├── Dockerfile
├── wsgi.py # Точка входа для Gunicorn
├── requirements.txt
├── .env.example
└── README.md
```
---
## Развёртывание на Ubuntu 24.04
Подробная пошаговая инструкция для чистого сервера Ubuntu 24.04 LTS.
### 1. Подключение к серверу
```bash
ssh user@YOUR_SERVER_IP
```
Замените `user` на имя пользователя и `YOUR_SERVER_IP` на IP-адрес сервера.
### 2. Обновление системы
```bash
sudo apt update && sudo apt upgrade -y
```
### 3. Установка необходимых пакетов
```bash
sudo apt install -y ca-certificates curl gnupg git
```
### 4. Установка Docker
Docker официально поддерживается на Ubuntu 24.04.
```bash
# Добавить GPG-ключ Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# Добавить репозиторий Docker
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Установить Docker Engine и Compose plugin
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
```
Проверка установки:
```bash
sudo docker run hello-world
docker compose version
```
### 5. Добавить пользователя в группу docker (опционально)
Чтобы не использовать `sudo` перед каждой командой docker:
```bash
sudo usermod -aG docker $USER
newgrp docker
```
### 6. Копирование проекта на сервер
**Вариант A — через Git:**
```bash
cd ~
git clone https://github.com/YOUR_USER/photohost.git фотохостинг
cd фотохостинг
```
**Вариант B — через SCP с локального компьютера:**
```bash
# Выполнить на локальной машине (Windows PowerShell / Linux)
scp -r ./фотохостинг user@YOUR_SERVER_IP:~/
```
```bash
# На сервере
cd ~/фотохостинг
```
**Вариант C — создать файлы вручную** — скопируйте содержимое проекта в каталог `~/фотохостинг`.
### 7. Настройка переменных окружения
```bash
cp .env.example .env
nano .env
```
Измените значения в `.env`:
```env
POSTGRES_USER=photohost
POSTGRES_PASSWORD=ВАШ_НАДЁЖНЫЙ_ПАРОЛЬ_БД
POSTGRES_DB=photohost
DATABASE_URL=postgresql://photohost:ВАШ_НАДЁЖНЫЙ_ПАРОЛЬ_БД@db:5432/photohost
SECRET_KEY=случайная_строка_минимум_32_символа
MAX_UPLOAD_MB=10
APP_PORT=8080
```
Сгенерировать случайный `SECRET_KEY`:
```bash
python3 -c "import secrets; print(secrets.token_hex(32))"
```
### 8. Запуск приложения
```bash
docker compose up -d --build
```
Проверка статуса контейнеров:
```bash
docker compose ps
```
Ожидаемый результат — оба сервиса `running`:
| Сервис | Контейнер | Порт |
|--------|----------------|-------------|
| web | photohost-web | 8080 → 8000 |
| db | photohost-db | 5432 (внутр.) |
Просмотр логов:
```bash
docker compose logs -f web
```
### 9. Проверка работы
Откройте в браузере:
```
http://YOUR_SERVER_IP:8080
```
Загрузите тестовое изображение — оно должно появиться в галерее.
### 10. Открытие порта в файрволе (UFW)
Если включён UFW:
```bash
sudo ufw allow 8080/tcp
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
```
### 11. Автозапуск при перезагрузке сервера
Docker Compose с `restart: unless-stopped` уже перезапускает контейнеры. Убедитесь, что Docker включён:
```bash
sudo systemctl enable docker
sudo systemctl start docker
```
---
## Полезные команды
| Действие | Команда |
|-----------------------|----------------------------------|
| Остановить | `docker compose down` |
| Перезапустить | `docker compose restart` |
| Пересобрать | `docker compose up -d --build` |
| Логи web | `docker compose logs -f web` |
| Логи БД | `docker compose logs -f db` |
| Зайти в контейнер web | `docker compose exec web bash` |
| Зайти в PostgreSQL | `docker compose exec db psql -U photohost -d photohost` |
---
## Резервное копирование
### База данных
```bash
docker compose exec db pg_dump -U photohost photohost > backup_$(date +%Y%m%d).sql
```
Восстановление:
```bash
cat backup_20250606.sql | docker compose exec -T db psql -U photohost -d photohost
```
### Загруженные фото
Фото хранятся в Docker volume `uploads_data`. Список volumes:
```bash
docker volume ls
```
Бэкап volume:
```bash
docker run --rm -v photohost_uploads_data:/data -v $(pwd):/backup alpine tar czf /backup/uploads_backup.tar.gz -C /data .
```
---
## Настройка домена и HTTPS (Nginx + Let's Encrypt)
### Установка Nginx и Certbot
```bash
sudo apt install -y nginx certbot python3-certbot-nginx
```
### Конфиг Nginx
```bash
sudo nano /etc/nginx/sites-available/photohost
```
```nginx
server {
listen 80;
server_name photos.example.com;
client_max_body_size 15M;
location / {
proxy_pass http://127.0.0.1:8080;
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;
}
}
```
```bash
sudo ln -s /etc/nginx/sites-available/photohost /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
### SSL-сертификат
```bash
sudo certbot --nginx -d photos.example.com
```
Откройте порты 80 и 443:
```bash
sudo ufw allow 'Nginx Full'
```
---
## Локальная разработка (без Docker)
```bash
# Установить PostgreSQL локально или запустить только БД:
docker compose up -d db
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
# Измените DATABASE_URL на localhost:
# DATABASE_URL=postgresql://photohost:photohost_secret@localhost:5432/photohost
export FLASK_APP=wsgi.py
python wsgi.py
```
Приложение будет доступно на `http://localhost:8000`.
> Для локального запуска только БД добавьте в `docker-compose.yml` для сервиса `db` строку `ports: - "5432:5432"`.
---
## API
| Метод | URL | Описание |
|-------|---------------|-----------------------------|
| GET | `/` | Главная страница |
| POST | `/upload` | Загрузка фото (form-data) |
| GET | `/uploads/<filename>` | Прямая ссылка на файл |
| GET | `/api/photos` | JSON-список всех фото |
| POST | `/delete/<id>` | Удаление фото |
Пример ответа `/api/photos`:
```json
[
{
"id": 1,
"url": "/uploads/abc123.jpg",
"original_name": "photo.jpg",
"file_size": 245760,
"size_human": "240.0 КБ",
"created_at": "2025-06-06T12:00:00+00:00"
}
]
```
---
## Устранение неполадок
**Контейнер web не запускается**
```bash
docker compose logs web
```
Частая причина — БД ещё не готова. Healthcheck в `docker-compose.yml` решает это; подождите 30 секунд и перезапустите:
```bash
docker compose restart web
```
**Ошибка подключения к PostgreSQL**
Проверьте, что пароли в `.env` совпадают в `POSTGRES_PASSWORD` и `DATABASE_URL`.
**Фото не загружаются (413 Request Entity Too Large)**
Увеличьте `MAX_UPLOAD_MB` в `.env` и `client_max_body_size` в Nginx.
**Порт 8080 занят**
Измените `APP_PORT=9090` в `.env` и перезапустите:
```bash
docker compose down && docker compose up -d
```
---
## Технологии
- Python 3.12, Flask 3, Gunicorn
- PostgreSQL 16
- SQLAlchemy, Pillow
- Docker & Docker Compose