Представьте, что вы присоединились к проекту. Вам передали исходный код веб-приложения книги контактов, и ваша первая задача — понять, как его запустить
Представим ситуацию - одногруппник вас подбивает в свой пет-проект под гордым названием "Блокнотик". Функционально - это простая книга контактов, но вам не столь важно как это выглядит, ваша цель - освоить на практике какие-то технологии, а затем загрузить на гитхаб, распечатать его в рамочку и спустя года смотреть и горечно вспоминать свои первые шаги...
И вот вы соглашаетесь, вам присылают репозиторий, в котором ничего не понятно. Ни документаций, ни гайдов как запустить - вполне типичный пет-проект
На этом этапе ваша задача - не запустить проект, а понять его требования. Изучите код: Откройте директорию app, файлы config.py и manage.py. Как приложение получает настройки для подключения к базе данных?
рекомендую пройти хотя-бы несколько этапов, прежде чем переходить к сладенькому
Разворачивать приложение вручную на своем компьютере — долго и неудобно. У вашего друга может быть другая версия ОС или Python, и все сломается.
Но попробовать же стоит, да?
Чек-лист:
- Установить Python нужной версии
- Установить все зависимости
pip install -r requirements.txt - Установить, настроить и запустить сервер PostgreSQL. Достать из кода схему, создать там базу, пользователя, выдать права
- Создать
.envфайл, прописать туда переменнные окружения
Наверняка ваше приложение упало, сначала из-за конфликта пакетов, затем не смогло подключиться к базе данных. Если вы починили все эти проблему, то оно, скорее всего, упало снова, но уже с ошибкой relation "contact" does not exist.
Сколько времени ушло на решение проблем?
А теперь представьте, что вам нужно передать этот проект второму другу. Ему придется пройти тот же путь страданий, задавая вам новую пачку вопросов.
Вот бы был способ упаковать приложение вместе со всеми его зависимостями в единую, предсказуемую и изолированную среду, которая запускается одной командой и не зависит от текущего окружения.
Именно эту проблему решает Docker, позволяя нам описать всю нашу сложную систему в парочку текстовых файлов конфигураций
Ваша задача — заставить проект работать, создав два файла: Dockerfile и docker-compose.yml.
подробнее об этих файлах, как из заполнять и что они делают - узнаете на лекциях
Важно: Никакой установки PostgreSQL, Python и пакетов на ваш хост! Все должно работать исключительно внутри Docker
Наше приложение состоит из двух сервисов, которые должны работать вместе: веб-приложение (web) и база данных (db). Файл docker-compose.yml — это "схема" всей нашей системы.
Вам нужно описать в нем оба сервиса. Для сервиса db используйте готовый образ postgres:13-alpine. Чтобы он заработал, ему нужно передать переменные окружения, которые он использует для первоначальной настройки:
POSTGRES_DB=...
POSTGRES_USER=...
POSTGRES_PASSWORD=...
Ваш сервис web должен собираться из Dockerfile, который вы напишете, и также получать эти переменные, чтобы знать, как подключиться к базе.
Не забудьте открыть порт 5555 для доступа к приложению из браузера и настроить volumes, чтобы данные в базе не терялись.
Просто скопировать файлы и установить зависимости в "тонкий" образ python-slim не получится — некоторые пакеты, как psycopg2, требуют компиляции из исходного кода, для которой в slim-образе нет инструментов.
Решение этой проблемы — мультистейдж-сборка. Идея в том, чтобы разделить процесс на два этапа:
-
Этап сборки (builder): Используется полноценный образ (например,
python:3.9-buster), собранный на базе Debian Buster, в который устанавливаются все необходимые для компиляции инструменты. Здесь вы устанавливаете все зависимости. -
Финальный этап (runner): Используется "тонкий" образ (
python:3.9-slim-buster) - минимальный необходимый набор для работы. В него вы копируете только результат работы первого этапа (скомпилированные пакеты) и исходный код приложения. Таким образом, в финальном образе не остается ничего лишнего (и вы не переиспользуете драгоценные ресурсы)
Команда для запуска - CMD ["gunicorn", "--bind", "0.0.0.0:5555", "manage:app"]
если при сборке возникает ошибка вида 404: ip not found - добавьте
RUN echo "deb http://archive.debian.org/debian/ buster main" > /etc/apt/sources.list && \ echo "deb http://archive.debian.org/debian-security buster/updates main" >> /etc/apt/sources.list
Даже если все соберется и запустится, вы столкнетесь с "гонкой состояний": ваше веб-приложение стартует и пытается подключиться к базе данных, которая еще не успела полностью загрузиться и подготовиться. Приложение упадет.
Чтобы решить это, используется ENTRYPOINT — специальная инструкция в Dockerfile, которая назначает исполняемый файл "точкой входа" для контейнера.
Этот скрипт запускается перед основной командой (CMD) и отвечает за подготовку окружения.
Вам не нужно писать этот скрипт с нуля — он уже есть в проекте под именем entrypoint.sh. Его задача — циклически проверять, готова ли база данных принимать подключения, затем выполнить команду для создания таблиц, и только после этого передать управление основной команде запуска веб-сервера.
Ваша же задача - правильно интегрировать его в Dockerfile
-
Сам по себе скрипт работать не будет. Во-первых, он использует утилиты, которых может не быть в вашем минималистичном образе. и как же их туда установить?...
-
Во-вторых, скрипт нужно скопировать в образ, сделать его исполняемым и назначить той самой "точкой входа"
И наконец, чтобы команды flask внутри скрипта работали корректно, не забудьте указать в Dockerfile переменную окружения ENV FLASK_APP=manage.py.
-
Чем контейнеризация отличается от виртуализации?
-
Разница между контейнером и образом.
-
Зачем нужен entrypoint.sh? Какую проблему "гонки состояний" (race condition) он решает?
-
Объясните роль секции
environmentвdocker-compose.yml. Как сервисwebузнает, как получить доступ кdb? -
Почему важно использовать минимальные рабочие образы?
-
Расскажите о слоях в Docker. Почему по-хорошему команда
COPY requirements.txt .должна идти доCOPY . .?