2026-06-06 21:59:09 +03:00
2026-06-06 21:59:09 +03:00
2026-06-06 21:59:09 +03:00
2026-06-06 21:59:09 +03:00
2026-06-06 21:59:09 +03:00
2026-06-06 21:59:09 +03:00
2026-06-06 21:59:09 +03:00
2026-06-06 21:59:09 +03:00

PhotoHost — Фото-хостинг

Современный фото-хостинг на Python (Flask), PostgreSQL и Docker Compose.

  • Красивая главная страница с drag-and-drop загрузкой
  • Галерея загруженных фото
  • Копирование прямых ссылок на изображения
  • Хранение метаданных в PostgreSQL, файлов — в Docker volume

Структура проекта

fotohost/
├── 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. Подключение к серверу

ssh user@YOUR_SERVER_IP

Замените user на имя пользователя и YOUR_SERVER_IP на IP-адрес сервера.

2. Обновление системы

sudo apt update && sudo apt upgrade -y

3. Установка необходимых пакетов

sudo apt install -y ca-certificates curl gnupg git

4. Установка Docker

Docker официально поддерживается на Ubuntu 24.04.

# Добавить 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

Проверка установки:

sudo docker run hello-world
docker compose version

5. Добавить пользователя в группу docker (опционально)

Чтобы не использовать sudo перед каждой командой docker:

sudo usermod -aG docker $USER
newgrp docker

6. Копирование проекта на сервер

Вариант A — через Git:

cd ~
git clone https://git.evilfox.cc/test2/fotohost.git fotohost
cd fotohost

Вариант B — через SCP с локального компьютера:

# Выполнить на локальной машине (Windows PowerShell / Linux)
scp -r ./fotohost user@YOUR_SERVER_IP:~/
# На сервере
cd ~/fotohost

Вариант C — создать файлы вручную — скопируйте содержимое проекта в каталог ~/fotohost.

7. Настройка переменных окружения

cp .env.example .env
nano .env

Измените значения в .env:

POSTGRES_USER=photohost
POSTGRES_PASSWORD=YOUR_STRONG_DB_PASSWORD
POSTGRES_DB=photohost
DATABASE_URL=postgresql://photohost:YOUR_STRONG_DB_PASSWORD@db:5432/photohost

SECRET_KEY=random_string_min_32_chars
MAX_UPLOAD_MB=10
APP_PORT=8080

Сгенерировать случайный SECRET_KEY:

python3 -c "import secrets; print(secrets.token_hex(32))"

8. Запуск приложения

docker compose up -d --build

Проверка статуса контейнеров:

docker compose ps

Ожидаемый результат — оба сервиса running:

Сервис Контейнер Порт
web photohost-web 8080 → 8000
db photohost-db 5432 (внутр.)

Просмотр логов:

docker compose logs -f web

9. Проверка работы

Откройте в браузере:

http://YOUR_SERVER_IP:8080

Загрузите тестовое изображение — оно должно появиться в галерее.

10. Открытие порта в файрволе (UFW)

Если включён UFW:

sudo ufw allow 8080/tcp
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status

11. Автозапуск при перезагрузке сервера

Docker Compose с restart: unless-stopped уже перезапускает контейнеры. Убедитесь, что Docker включён:

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

Резервное копирование

База данных

docker compose exec db pg_dump -U photohost photohost > backup_$(date +%Y%m%d).sql

Восстановление:

cat backup_20250606.sql | docker compose exec -T db psql -U photohost -d photohost

Загруженные фото

Фото хранятся в Docker volume uploads_data. Список volumes:

docker volume ls

Бэкап volume:

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

sudo apt install -y nginx certbot python3-certbot-nginx

Конфиг Nginx

sudo nano /etc/nginx/sites-available/photohost
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;
    }
}
sudo ln -s /etc/nginx/sites-available/photohost /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

SSL-сертификат

sudo certbot --nginx -d photos.example.com

Откройте порты 80 и 443:

sudo ufw allow 'Nginx Full'

Локальная разработка (без Docker)

# Установить 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:

[
  {
    "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 не запускается

docker compose logs web

Частая причина — БД ещё не готова. Healthcheck в docker-compose.yml решает это; подождите 30 секунд и перезапустите:

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 и перезапустите:

docker compose down && docker compose up -d

Технологии

  • Python 3.12, Flask 3, Gunicorn
  • PostgreSQL 16
  • SQLAlchemy, Pillow
  • Docker & Docker Compose
S
Description
No description provided
Readme 361 KiB
Languages
Python 47.6%
HTML 36.8%
CSS 10.5%
JavaScript 4.6%
Dockerfile 0.3%
Other 0.2%