@@ -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
|
||||
Reference in New Issue
Block a user