Skip to content

Repository files navigation

ТЗ проекту "Сервер зображень"

0. Організація роботи над проектом

Зустрічі та розробка:

  • У тебе буде 3 консультації з ментором, де ви разом розберете важливі частини проекту.
  • Ментор допоможе визначити комфортний дедлайн для завершення роботи.
  • Основний функціонал ви напишете разом на консультаціях.

Здача проекту:

  • Завантаж проект у Git-репозиторій
  • Надішли посилання через форму

Успіхів у роботі 💪

1. Вступ

Що ми будемо робити?

Наше завдання — створити сервіс для перегляду та зберігання зображень у вигляді веб-додатку. Суть проста: користувач заходить на сайт, завантажує фотки чи картинки, а натомість отримує прямі посилання на них. Ці посилання можна використовувати де завгодно — у соцмережах, блогах або просто надіслати друзям.

Які технології використовуємо?

  • Бекенд пишемо на Python — він чудово підходить для таких завдань.
  • Для швидкої роздачі зображень використовуємо Nginx — він просто створений для цього.
  • Все запакуємо в Docker-контейнери, щоб проект легко запускався на будь-якому комп'ютері.
  • Docker Compose допоможе керувати всіма компонентами як єдиним цілим.

Навіщо цей проект?

Наш сервіс — це не просто сховище зображень. Це місце, де користувачі можуть:

  • Завантажувати фотки в популярних форматах (.jpg, .png, .gif).
  • Бути впевненими, що їхні зображення надійно збережені.
  • Отримувати зручні прямі посилання на завантажені зображення.

Ну а ми, розробники, будемо стежити за всім процесом через систему логів, щоб знати, що робити, якщо щось піде не так.

А для навчання цей проект — чудовий шанс покращити свої навички в Python-розробці, налаштуванні веб-серверів, роботі з Docker та взаємодії різних компонентів системи один з одним.

Основні завдання:

  1. Розробити Python-бекенд для обробки запитів, завантаження зображень та логування дій користувачів.
  2. Налаштувати Nginx для роздачі завантажених зображень.
  3. Запакувати проект у Docker-контейнери, з використанням Docker Compose для керування.
  4. Налаштувати Docker Volumes для довготривалого зберігання зображень та логів.
  5. Реалізувати інтерфейс для взаємодії з користувачем (завантаження зображень та доступ до файлів).

Design & Code:

  1. Макет сайту - https://www.figma.com/design/ivhGgfIBMDsA2xF3qospb6/image-hosting?node-id=0-1&p=f
  2. HTML Template - https://github.com/MagicCodeGit/image-hosting.git

2. Функціональні вимоги

Основний функціонал:

1. Головна сторінка

  • Маршрут: /
  • Функціональність:
    • Зустрічає користувача вітальним повідомленням та розповідає про сервіс.
    • Містить посилання на основні маршрути:
    • Сторінка завантаження зображень (/upload).
    • Каталог завантажених зображень (/images/).

2. Завантаження зображень

  • Маршрут: /upload
  • Метод: POST
  • Функціональність:
    • Приймає файл зображення від користувача через HTTP-запит.
    • Підтримувані формати: .jpg, .png, .gif.
    • Обмеження розміру файлу: до 5 МБ.
    • Генерує унікальне ім'я для кожного завантажуваного зображення.
    • Зберігає зображення в папку /images на сервері.
    • Повертає користувачу унікальний ідентифікатор файлу та посилання на зображення.

3. Доступ до завантажених зображень

  • Маршрут: /images/<ім'я_файлу>
  • Функціональність:
    • Всі завантажені зображення мають бути доступні для перегляду та завантаження за прямими посиланнями.
    • Nginx обслуговує цей маршрут, роздаючи файли з папки /images.

4. Логування дій

  • Функціональність:
    • Записує кожну дію користувача в лог-файл app.log.
  • Формат запису:
    [Дата/час] Дія: повідомлення

Приклади записів:

[2025-01-24 14:00:00] Успіх: зображення img1.jpg завантажено.
[2025-01-24 14:01:00] Помилка: непідтримуваний формат файлу (user_file.txt).
  • Логи потрібно зберігати в окремому томі Docker.

Користувацькі сценарії

1. Завантаження зображення

  1. Користувач переходить на маршрут /upload.
  2. Завантажує файл через HTTP-запит (наприклад, за допомогою форми або програми curl).
  3. Бекенд перевіряє формат та розмір файлу.
  4. Якщо файл успішно завантажено:
    • Він зберігається в папці /images.
    • Користувачу повертається повідомлення з унікальним посиланням на файл (наприклад, /images/img1.jpg).
  5. Якщо файл не відповідає вимогам:
    • Користувачу повертається повідомлення про помилку (наприклад, "Непідтримуваний формат файлу").

2. Перегляд завантажених зображень

  1. Користувач переходить за посиланням /images/<ім'я_файлу>.
  2. Nginx повертає запитане зображення для перегляду або завантаження.

3. Нефункціональні вимоги

1. Продуктивність

  • Багатозадачність: сервер легко справляється з 10 користувачами, які завантажують картинки одночасно. Жодних гальмувань та зависань!
  • Швидкість завантаження: час обробки завантаження одного зображення (включаючи збереження та генерацію імені) не повинен перевищувати 1 секунди.
  • Миттєвий перегляд: Nginx роздає картинки зі швидкістю світла (ну гаразд, менше 100 мілісекунд). Відкрили посилання — відразу побачили картинку, жодного "завантажується...". Коротше кажучи, все має працювати швидко та без затримок! ⚡

2. Обмеження

  • Розмір файлів: максимальний розмір завантажуваного зображення — 5 МБ.
  • Підтримувані формати: тільки .jpg, .png та .gif. Спроба завантажити непідтримуваний формат має повертати повідомлення про помилку.
  • Обсяг зберігання: сховище зображень не повинно перевищувати доступний простір тому Docker (за замовчуванням обмежень на обсяг не вводиться, але передбачається розумне використання дискового простору).

3. Надійність

  • Система має коректно обробляти некоректні запити:
  • Завантажені файли, що не відповідають формату або розміру, мають викликати повернення помилки (400 Bad Request).
  • У разі збою сервер має автоматично перезапускатися (мається на увазі використання Docker для автоматичного відновлення).

4. Масштабованість

  • Проект орієнтований на навчальні цілі, але має бути спроектований таким чином, щоб за необхідності:
  • Збільшити кількість бекенд-серверів для обробки завантажень.
  • Розширити сховище зображень.
  • Додати нові маршрути або функціональність (наприклад, базу даних).

5. Технології

  • Мова програмування: Python (версія 3.12 або вище).
  • Сервер для статичних файлів: Nginx.
  • Контейнеризація: Docker та Docker Compose.
  • Бібліотеки Python:
  • Обов'язково: Pillow (для роботи з зображеннями, якщо потрібно).
  • Додатково: тільки стандартна бібліотека для обробки запитів (наприклад, http.server).

6. Контейнеризація

  • Усі сервіси (бекенд та Nginx) потрібно запакувати в окремі Docker-контейнери.
  • Керування контейнерами потрібно організувати за допомогою Docker Compose.
  • Мають бути використані два томи:
  • images: для зберігання завантажених зображень.
  • logs: для збереження логів.

7. Зручність розгортання

Щоб запустити проект достатньо однієї команди:

docker compose up --build
  • Усі залежності мають бути включені в Dockerfile та compose.yaml.

8. Безпека проекту

Звісно, нам потрібно захистити сервіс від усіляких неприємностей! Що для цього робимо? Перевіряємо все, що завантажують:

  • Приймаємо тільки картинки (jpg, png, gif) — жодних шкідливих файлів
  • Стежимо за розміром - великі файли можуть перевантажити сервер
  • Якщо хтось намагається завантажити щось дивне — відразу кажемо "ні" і пояснюємо причину

Захищаємо доступ до файлів:

  • Картинки доступні тільки за спеціальними посиланнями виду /images/назва_файлу
  • Весь доступ до файлів йде через Nginx — він у нас як надійний охоронець
  • Жодних обхідних шляхів - безпека понад усе! 🛡️

9. Сховище даних

  • Зображення: зберігаються в папці /images, монтованій як volume.
  • Логи: зберігаються в папці /logs, монтованій як volume.
  • Довготривалість даних: том Docker зберігає всі файли між перезапусками контейнерів.

10. Логування

  • Логи мають бути читабельними та інформативними.
  • Формат логів:
[Дата/час] Дія: повідомлення
  • Логи зберігаються в текстовий файл app.log в папці /logs.

11. Доступність

  • Додаток має бути доступний:
  • Бекенд за адресою: http://localhost:8000.
  • Статичні зображення через Nginx за адресою: http://localhost:8080/images/<ім'я_файлу>.

12. Підтримуваність

Ми пишемо код не тільки для комп'ютера, але й для людей! Тому:

Код має бути зрозумілим:

  • Використовуємо змістовні імена змінних та функцій
  • Додаємо коментарі до складних місць
  • Дотримуємось єдиного стилю оформлення

API робимо гнучким:

  • Кожен маршрут (/upload, /images та інші) детально документуємо
  • Залишаємо можливість легко додати нові функції
  • Пишемо код так, щоб його можна було розширювати, а не переписувати

Загалом, робимо так, щоб навіть через півроку будь-який розробник міг розібратися і щось додати! 👨‍💻


4. Архітектура та структура

1. Загальна архітектура

Система складається з двох основних компонентів:

  1. Python-бекенд:
  • Відповідає за обробку HTTP-запитів, завантаження зображень, валідацію даних та логування.
  • Виконує бізнес-логіку додатку, пов'язану з керуванням завантаженими файлами.
  • Працює всередині Docker-контейнера, слухаючи запити на порту 8000.
  1. Nginx-сервер:
  • Роздає статичні файли та завантажені зображення за маршрутом /images/.
  • Проксує запити на Python-бекенд для інших маршрутів.
  • Працює в окремому Docker-контейнері, слухаючи запити на порту 80.

Компоненти взаємодіють через локальну мережу, створену за допомогою Docker Compose.

2. Взаємодія компонентів

Коли користувач завантажує картинку:

  1. Користувач надсилає файл через POST /upload на Python-бекенд.
  2. Бекенд бере всю роботу на себе:
    • Перевіряє, чи все гаразд з файлом
    • Придумує йому унікальне ім'я
    • Зберігає в папку /images через Docker volume
    • Записує в лог, що і коли завантажили
    • Віддає користувачу посилання на його картинку

Коли користувач хоче подивитися картинку:

  1. Запитує картинку через GET /images/<ім'я_файлу> у Nginx
  2. Nginx шукає файл у папці /images
  3. Якщо знайшов - віддає картинку користувачу

Хто за що відповідає:

  • Python-бекенд — "розумна" частина: перевіряє файли, обробляє завантаження
  • Nginx — "швидка" частина: роздає картинки і працює як проксі

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

Директорії та файли:

project/
├── app.py                # Основний Python-бекенд
├── requirements.txt      # Залежності Python
├── Dockerfile            # Dockerfile для Python-бекенду
├── docker-compose.yml    # Конфігурація Docker Compose
├── nginx.conf           # Конфігурація Nginx
├── images/              # Папка для зберігання завантажених зображень (volume)
├── logs/                # Папка для логів (volume)
└── static/              # Додаткові статичні файли (CSS/JS, якщо застосовно)

Опис ключових компонентів:

  1. app.py:
  • Реалізує обробку HTTP-запитів:
    • GET / — головна сторінка.
    • POST /upload — завантаження зображення.
  • Виконує:
    • Валідацію завантажуваного файлу (формат, розмір).
    • Збереження файлу в папку /images.
    • Логування дій у файл app.log.
  1. nginx.conf:
  • Роздає вміст папки /images за маршрутом /images/<ім'я_файлу>.
  • Проксує запити, не пов'язані зі статикою, на Python-бекенд.
  1. compose.yaml:
  • Визначає два сервіси:
    • app — Python-бекенд.
    • nginx — Nginx-сервер.
  • Створює два томи:
    • images — для зберігання завантажених зображень.
    • logs — для зберігання логів.
  1. images/:
  • Каталог, у який зберігаються всі завантажені файли.
  • Підключається як volume для довготривалого зберігання.
  1. logs/:
  • Каталог, що містить лог-файли (app.log).
  • Підключається як volume для збереження даних між перезапусками.

4. Взаємодія через мережу

  • Порти та маршрути:
    • Python-бекенд:
    • Зовнішній порт: 8000 (для локального налагодження).
    • Nginx:
    • Зовнішній порт: 8080 (для користувачів).
    • Внутрішня мережа Docker зв'язує два контейнери:
    • Nginx звертається до Python-бекенду за адресою http://app:8000.

5. Логічна схема

  1. Користувацький запит: Користувач взаємодіє з системою через маршрути:

    • / — головна сторінка (обробляється бекендом).
    • /upload — завантаження зображення (обробляється бекендом).
    • /images/<ім'я_файлу> — доступ до зображення (обробляється Nginx).
  2. Обробка запитів:

    • Nginx:
      • Роздає статичні файли та завантажені зображення.
      • Переадресовує запити на Python-бекенд, якщо маршрут не пов'язаний з інтерфейсом та зображеннями.
    • Python-бекенд:
      • Приймає і обробляє запити / та /upload.
      • Зберігає зображення та записує логи.
  3. Зберігання даних:

    • Зображення:
      • зберігаються в volume, підключеному як /images.
    • Логи:
      • зберігаються в volume, підключеному як /logs.

6. Потік даних

  1. Завантаження зображення:

    • Користувач надсилає файл на маршрут /upload.
    • Python-бекенд:
      • Перевіряє файл.
      • Зберігає файл в /images.
      • Логує дію.
    • Користувачу повертається посилання виду /images/<ім'я_файлу>.
  2. Доступ до зображення:

    • Користувач надсилає запит на /images/<ім'я_файлу>.
    • Nginx перевіряє файл у папці /images і повертає його.

5. Технічні вимоги

1. Мова програмування та бібліотеки

  • Мова програмування: Python 3.12 або вище.
  • Бібліотеки Python:
  • Стандартна бібліотека: для роботи з HTTP-запитами (http.server), файловою системою (os), логуванням (logging) та JSON.
  • Pillow: для роботи з зображеннями (за необхідності, якщо знадобиться перевірка або обробка зображень).

2. Сервер для роздачі статичних файлів

  • Nginx:
  • Має бути налаштований для роздачі зображень з папки /images.
  • Має проксувати всі запити, що не стосуються статики, на Python-бекенд.
  • Порт для зовнішнього доступу: 8080.

3. Контейнеризація

  • Docker:
    • Усі компоненти додатку мають бути запаковані в контейнери:
      • Python-бекенд.
      • Nginx-сервер.
    • Мають бути використані два Docker Volumes:
      • images — для зберігання завантажених зображень.
      • logs — для зберігання логів.
    • Для керування контейнерами використовується Docker Compose.
  • Docker Compose:
    • Конфігурація має містити:
      • Сервіс для Python-бекенду:
        • Назва: app.
        • Порт: 8000.
        • Підключення томів для зображень та логів.
      • Сервіс для Nginx:
        • Назва: nginx.
        • Порт: 8080.
        • Підключення тому для зображень.
        • Проксування запитів на Python-бекенд.

4. Сховище даних

  • Зображення:
    • зберігаються в локальній папці /images, підключеній через volume.
    • кожне зображення має мати унікальне ім'я, що генерується Python-бекендом.
    • обмеження:
      • Підтримувані формати: .jpg, .png, .gif.
      • Максимальний розмір файлу: 5 МБ.
  • Логи:
    • логи пишуться в файл app.log, розташований у папці /logs.
    • лог-файл має бути доступний для читання між перезапусками контейнера.

5. Мережеві налаштування

  • Взаємодія контейнерів:
  • Python-бекенд (app) та Nginx (nginx) мають бути зв'язані через внутрішню мережу Docker.
  • Nginx проксує запити до Python-бекенду за адресою http://app:8000.
  • Порти:
  • Nginx: доступний на порту 8080 для користувачів.
  • Python-бекенд: слухає запити на порту 8000 (всередині контейнера).

6. Як забезпечуємо безпеку?

  • Перевіряємо кожен файл перед завантаженням:

  • "Це точно картинка?" — приймаємо тільки підтримувані формати

  • "Не занадто велика?" — стежимо за розміром файлу

  • Захищаємо доступ до файлів:

  • Жодних "обхідних шляхів" — тільки прямі посилання від бекенду

  • Всі посилання виду /images/назва_файлу

Тобто спочатку переконуємося, що файл безпечний, а потім даємо до нього доступ тільки через перевірений маршрут.


7. Продуктивність

  • Бекенд має обробляти до 10 одночасних запитів.
  • Середній час завантаження файлу (включаючи валідацію та збереження) не повинен перевищувати 1 секунди для файлу розміром 5 МБ.

8. Система логування

  • Логи мають бути читабельними і містити:

  • Дату та час дії.

  • Тип дії (наприклад, успішне завантаження або помилка).

  • Подробиці дії (наприклад, ім'я завантаженого файлу, причина помилки).

  • Приклад лог-запису:

[2025-01-24 14:00:00] Успіх: зображення img1.jpg завантажено.

9. Інструкція із запуску

Для запуску системи необхідно:

  1. Встановити Docker та Docker Compose.
  2. Виконати команду:
    docker-compose up --build
  3. Переконатися, що:
    • Бекенд доступний за адресою: http://localhost:8000.
    • Статичні файли роздаються за адресою: http://localhost:8080/images/<ім'я_файлу>.

10. Файли проекту

  • Dockerfile:
  • Для Python-бекенду з використанням multi-stage build.
  • compose.yaml:
  • Конфігурація для об'єднання контейнерів.
  • nginx.conf:
  • Конфігурація Nginx для роздачі зображень та проксування запитів.
  • app.py:
  • Основний скрипт Python-бекенду.
  • requirements.txt:
  • Список залежностей Python.

6. Етапи виконання

Проект потрібно буде реалізувати поетапно, щоб структурувати процес розробки та забезпечити послідовне виконання всіх вимог. Кожен етап включає ключові завдання та передбачає проміжну перевірку.

Етап 1. Підготовка оточення та структури проекту

  1. Встановити необхідні інструменти:

    • Docker та Docker Compose.
    • Python 3.12 або вище.
  2. Налаштувати базову структуру проекту:

project/
├── app.py                # Основний Python-бекенд
├── requirements.txt      # Залежності Python
├── Dockerfile            # Dockerfile для Python-бекенду
├── docker-compose.yml    # Конфігурація Docker Compose
├── nginx.conf            # Конфігурація Nginx
├── images/               # Папка для зберігання завантажених зображень (volume)
├── logs/                 # Папка для логів (volume)
└── static/               # Додаткові статичні файли (CSS/JS, якщо застосовно)
  1. Створити та протестувати віртуальне оточення Python:
    • Переконатися, що всі залежності, вказані в requirements.txt, встановлюються коректно.

Етап 2. Розробка Python-бекенду

  1. Реалізувати базовий HTTP-сервер з маршрутами:
    • GET /: повертає вітальне повідомлення.
    • POST /upload: обробляє завантаження файлів.
  2. Додати функціонал:
    • Перевірка формату файлу (.jpg, .png, .gif).
    • Перевірка розміру файлу (не більше 5 МБ).
    • Генерація унікального імені для кожного зображення.
    • Збереження зображень у папку /images.
    • Повернення посилання на завантажене зображення.
  3. Налаштувати логування:
    • Створити файл app.log для запису дій (успішних та помилкових).
    • Логи мають містити дату, час, дію та деталі.
  4. Протестувати роботу бекенду локально, без Docker.

Етап 3. Налаштування Nginx

  1. Написати конфігурацію nginx.conf:

    • Налаштувати роздачу файлів з папки /images.
    • Налаштувати проксування запитів до Python-бекенду для маршрутів, не пов'язаних із зображеннями.
  2. Протестувати конфігурацію локально:

  • Переконатися, що запити на /images/<ім'я_файлу> повертають статичні файли.
  • Переконатися, що запити на інші маршрути перенаправляються на Python-бекенд.

Етап 4. Контейнеризація

  1. Створити Dockerfile для Python-бекенду:

    • Реалізувати multi-stage build, щоб зменшити розмір образу.
    • Переконатися, що всі залежності встановлюються коректно.
  2. Налаштувати Docker Compose:

    • Створити файл compose.yaml.
    • Додати два сервіси:
      • app для Python-бекенду.
      • nginx для Nginx-сервера.
    • Налаштувати volume:
      • images для зберігання завантажених файлів.
      • logs для запису логів.
    • Налаштувати мережу для взаємодії контейнерів.
  3. Протестувати запуск контейнерів:

    • Переконатися, що сервіси запускаються командою:
    docker compose up --build
    • Перевірити доступність бекенду (http://localhost:8000) та статичних файлів (http://localhost:8080/images/<ім'я_файлу>).

Етап 5. Тестування функціональності

  1. Перевірити завантаження зображень:
    • завантажити зображення різних форматів та розмірів.
    • перевірити генерацію унікальних імен та збереження файлів у папці /images.
  2. Перевірити обробку помилок:
    • спроба завантаження непідтримуваного формату.
    • спроба завантаження файлу, що перевищує ліміт розміру.
  3. Перевірити роздачу файлів через Nginx:
    • доступ до завантажених зображень через маршрут /images/<ім'я_файлу>.
  4. Перевірити логування:
    • переконатися, що всі дії записуються в лог-файл app.log.

Етап 6. Документація

  1. Написати інструкцію з розгортання проекту:
    • Кроки для запуску за допомогою Docker Compose.
    • Опис структури проекту та функціональності.
  2. Додати опис ключових маршрутів API.

Етап 7. Підготовка до здачі

  1. Переконатися, що:
    • всі функціональні та нефункціональні вимоги виконано.
    • система успішно запускається через Docker Compose.
    • всі тести пройдено.
  2. Упакувати проект:
    • архівувати файли проекту.
    • підготувати README з коротким описом та інструкцією.

7. Критерії успішності

Проект буде оцінюватися в балах: максимум 60 балів.

1. Функціональність (10 балів)

  1. Робота маршрутів:
  • Головна сторінка (/) повертає коректне вітальне повідомлення.
  • Завантаження зображення через маршрут /upload працює без помилок:
    • Підтримуються формати .jpg, .png, .gif.
    • Перевіряється розмір файлу (до 5 МБ).
    • Файли успішно зберігаються з унікальними іменами в папку /images.
  • Завантажені зображення доступні через маршрути /images/<ім'я_файлу>.
  1. Логування:
    • Всі дії (успішні завантаження, помилки) записуються в лог-файл app.log у папці /logs.
    • Формат логів відповідає вимогам:
    [Дата/час] Дія: повідомлення
    

2. Контейнеризація (10 балів)

  1. Робота Docker-контейнерів:

Одна команда — і все готово до роботи:

 docker compose up --build
  • Сервіси працюють незалежно:
    • Python-бекенд у своєму контейнері - займається логікою
    • Nginx у своєму - роздає файли
  1. Сховище даних:

    • Завантажені зображення зберігаються в volume images.
    • Логи зберігаються в volume logs.
  2. Мережа:

    • Nginx коректно проксує запити на Python-бекенд.
    • Запити до статичних файлів (/images/<ім'я_файлу>) обробляються Nginx.

3. Продуктивність (5 балів)

  1. Обробка запитів:

    • завантаження одного зображення (включаючи перевірку, збереження та генерацію імені) займає не більше 1 секунди.
    • система коректно обробляє до 10 одночасних запитів.
  2. Роздача файлів:

    • Nginx повертає зображення без затримок (час відповіді не перевищує 100 мс для локальних запитів).

4. Тестування (5 балів)

  1. Завантаження зображень:

    • підтримуються всі вказані формати (.jpg, .png, .gif).
    • файли перевищуючого розміру (більше 5 МБ) відхиляються з повідомленням про помилку.
    • непідтримувані формати відхиляються з повідомленням про помилку.
  2. Роздача зображень:

    • всі завантажені зображення доступні через Nginx за маршрутом /images/<ім'я_файлу>.
  3. Логи:

    • успішні завантаження та помилки записуються коректно.
    • лог-файл зберігається між перезапусками контейнерів.

5. Зручність розгортання (5 балів)

  1. Проект повністю запускається за допомогою однієї команди:
docker compose up --build
  1. Всі залежності та конфігурації включені в проект.

6. Документація (5 балів)

  1. Написана інструкція з розгортання проекту, що включає:
    • вимоги до оточення.
    • команди для запуску та зупинки.
    • опис структури проекту.
    • опис маршрутів та їх функціональності.

Якщо всі вищезазначені критерії виконано, проект можна вважати успішно завершеним.

Сервер зображень

Простий веб-сервіс для завантаження та зберігання зображень: користувач завантажує картинку через веб-інтерфейс і отримує пряме посилання на неї.

Бекенд - Python (стандартна бібліотека + Pillow), роздача зображень і статики - Nginx, запуск - Docker Compose.

Можливості

  • завантаження .jpg, .png, .gif розміром до 5 МБ;
  • перевірка справжнього формату файлу через Pillow, а не за розширенням в імені;
  • унікальні імена файлів (UUID), тож завантаження не перезаписують одне одного;
  • прямі посилання виду /images/<ім'я_файлу>, які роздає Nginx;
  • каталог завантажених зображень;
  • логування всіх дій у app.log у форматі [Дата/час] Дія: повідомлення;
  • зображення та логи живуть у Docker-томах і переживають перезапуск контейнерів.

Вимоги

Для запуску через Docker:

  • Docker
  • Docker Compose

Для запуску без Docker:

  • Python 3.12 або новіший
  • Pillow (pip install -r requirements.txt)

Запуск

З кореня проєкту:

docker compose up --build

Після запуску доступні:

Адреса Що це
http://localhost:8080/ сайт (через Nginx) - основна точка входу
http://localhost:8080/images/<файл> пряме посилання на зображення
http://localhost:8000/ бекенд напряму, лише для локального налагодження

Зупинити контейнери (зображення та логи лишаються):

docker compose down

Зупинити та видалити томи разом із даними:

docker compose down -v

Запуск без Docker (сервер підніметься на http://localhost:8000, зображення й логи - у теках images/ та logs/ у корені проєкту):

python app.py

API

Маршрут Метод Що робить Хто обробляє
/ GET головна сторінка з описом сервісу та посиланнями бекенд
/upload GET сторінка-форма завантаження бекенд
/upload POST приймає файл, перевіряє, зберігає, повертає посилання бекенд
/images/ GET каталог завантажених зображень бекенд (Nginx проксує)
/gallery GET той самий каталог, прямий маршрут бекенду бекенд
/api/images GET JSON-список імен завантажених файлів бекенд
/api/images/<файл> DELETE видаляє зображення (кнопка "Видалити" в каталозі) бекенд
/images/<файл> GET віддача самого зображення Nginx

Успішна відповідь POST /upload:

{"id": "3f2a1c....png", "url": "/images/3f2a1c....png"}

Помилка (HTTP 400) - непідтримуваний формат, файл більший за 5 МБ, пошкоджений файл або запит не у форматі multipart/form-data:

{"error": "непідтримуваний формат файлу"}

Приклади запитів

Завантажити зображення:

curl -F "image=@cat.jpg" http://localhost:8080/upload

Забрати файл за посиланням:

curl -O http://localhost:8080/images/<унікальне>.jpg

Видалити зображення:

curl -X DELETE http://localhost:8080/api/images/<унікальне>.jpg

Перевірити обробку помилок:

curl -F "image=@document.txt" http://localhost:8080/upload
curl -F "image=@huge.png" http://localhost:8080/upload

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

app.py             Python-бекенд: маршрути, валідація, збереження, логування
requirements.txt   залежності Python (Pillow)
Dockerfile         образ бекенду (multi-stage build)
compose.yaml       опис сервісів app + nginx, томів і мережі
nginx.conf         роздача /images/ та статики, проксування решти на бекенд
static/            HTML, CSS, JS інтерфейсу
tests/             юніт-тести бекенду
images/            локальна тека для зображень (у Docker - том images)
logs/              локальна тека для логів (у Docker - том logs)

Як влаштована взаємодія

  • Nginx слухає :8080 і є єдиною зовнішньою точкою входу.
  • /images/<файл> Nginx віддає сам із тому images - Python при цьому не задіяний.
  • Статику (/css/, /js/, /img/) Nginx теж роздає сам із теки static/.
  • Решту маршрутів Nginx проксує на http://app:8000.
  • Тіло більше за 6 МБ Nginx відхиляє сам, підміняючи власний 413 на таку саму JSON-помилку 400, як у бекенду.

Логування

Лог пишеться у logs/app.log (том logs) у форматі з ТЗ:

[2026-01-24 14:00:00] Успіх: зображення 3f2a1c....png завантажено
[2026-01-24 14:01:00] Помилка: непідтримуваний формат файлу (document.txt)

Ті самі записи дублюються у docker compose logs app.

Тестування

pip install -r requirements.txt
python -m unittest discover -s tests

Тести перевіряють:

  • завантаження .jpg, .png, .gif;
  • відмову для непідтримуваних форматів і для файлів більших за 5 МБ;
  • відмову для файлу, який лише вдає із себе картинку розширенням;
  • нестандартні записи межі multipart (у лапках, із додатковим параметром);
  • роздачу збереженого зображення та список файлів у /api/images;
  • видалення файлу через DELETE /api/images/<файл>, зокрема відмову видаляти щось за межами теки зображень;
  • сторінки інтерфейсу, HEAD, коди 404;
  • захист від виходу за межі теки зображень.

Releases

Packages

Contributors

Languages