Установка через requirements.txt означает использование этой команды шага сборки образа «RUN pip3 install -r requirements.txt». Редактируемая установка означает использование команды «RUN pip3 install -e .». Я столкнулся с тем, что установка через requirements.txt приводит к тому, что образы не запускаются, в то время как использование редактируемой установки приводит к тому, что образы работают, как ожидалось. Я представляю свои выводы в этом посте.
Первый учебник по Docker, который я прошел, был Learn to build and deploy your distributed applications easily to the cloud with Docker, это отличный учебник, и я успешно прошел его до конца. Затем я сделал это Build your Python image — только эту первую часть.
Что общего между ними — по моим наблюдениям:
- Проекты Python имеют только один файл Python. Я просмотрел некоторые другие учебники, в проектах также есть один файл Python.
- В файле Dockerfile они оба используют RUN pip3 install -r requirements.txt для установки необходимых пакетов.
Я хотел бы попробовать собрать образ для проекта, который имеет более одного модуля: большинство реальных проектов будут иметь более одного модуля. Код для Synology DS218: подготовка среды разработки Python 3.9 Beta compelete devepment. довольно прост, и будет хорошей первой попыткой.
Это репозиторий https://github.com/behai-nguyen/app-demo для кода. Для приведенного выше сообщения тег v1.0.0. Его можно клонировать с помощью:
git clone -b v1.0.0 https://github.com/behai-nguyen/app-demo.git
Обратите внимание, все сборки Docker, обсуждаемые в этом посте, были выполнены на Windows 10 Pro, с использованием docker CLI версии 20.10.12, build e91ed57.
Напомним, что схема проекта app-demo с тегом v1.0.0.0 выглядит следующим образом:
D:app_demo
|
|-- .env
|-- app.py
|-- setup.py
|
|-- src
| |
| |-- app_demo
| |
| |-- __init__.py
| |-- config.py
|
|-- venv
Я создал virtualenv venv для этого проекта в Windows 10.
Сборка с помощью команды «RUN pip3 install -r requirements.txt».
Обратите внимание, что эта команда шага сборки изображения отображает setup.py, который не используется.
Сгенерируйте файл requirements.txt:
D:app_demo>venvScriptspip.exe freeze > requirements.txt
Затем вручную удалите все, кроме пакетов, указанных в секции install_requires в файле setup.py.
File D:app_demorequirements.txt
Flask==2.1.2
python-dotenv==0.20.0
File D:app_demoDockerfile
# syntax=docker/dockerfile:1
FROM python:3.10.5-slim-buster
WORKDIR /app_demo
COPY requirements.txt requirements.txt
RUN pip3 install -r requirements.txt
COPY . .
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0" ]
File D:app_demo.dockerignore
__pycache__
*.pyc
*.pyo
*.pyd
.Python
venv
pip-log.txt
pip-delete-this-directory.txt
.tox
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.log
.git
.mypy_cache
.pytest_cache
.hypothesis
FlaskApp.wsgi
Working
Теперь это корневой уровень макета проекта:
D:app_demo
|
|-- .env
|-- app.py
|-- setup.py
|-- requirements.txt
|-- Dockerfile
|-- .dockerignore
|
...
Команда для сборки:
D:app_demo>docker build --tag app-demo .
Сборка успешно завершена. Чтобы запустить новый собранный образ:
D:app_demo>docker run --publish 8000:5000 --rm app-demo
Это не работает, как видно на снимке экрана ниже:
Ошибка ModuleNotFoundError: No module named ‘app_demo’.
Изменения для этой нерабочей сборки можно клонировать с помощью:
git clone -b v1.0.1 https://github.com/behai-nguyen/app-demo.git
✿✿✿
Поиск в Google предполагает, что другие также сталкивались с подобной ошибкой. Предлагается использовать абсолютный импорт — например, смотрите Module not found error with Python in Docker.
Я попробовал использовать абсолютный импорт, поскольку проект небольшой, изменения незначительны, и полученный образ действительно запускается. Однако это кажется неправильным… Я не должен этого делать…
Изменения для использования абсолютного импорта могут быть клонированы с помощью:
git clone -b v1.0.2 https://github.com/behai-nguyen/app-demo.git
В принципе, соответствующие операторы импорта в:
File D:app_demoapp.py
File D:app_demosrcapp_demo__init__.py
были снабжены префиксом src., чтобы стать соответственно:
from src.app_demo import create_app
from src.app_demo.config import get_config
Сборка и запуск, соответственно, с:
D:app_demo>docker build --tag app-demo .
D:app_demo>docker run --publish 8000:5000 --rm app-demo
Запуск прошел успешно. http://localhost:8000 отображает ожидаемый вывод Hello, World!
Сборка с помощью команды «RUN pip3 install -e .».
Обратите внимание на этот шаг сборки образа:
❶ Оба:
File D:app_demoapp.py
File D:app_demosrcapp_demo__init__.py
операторы импорта возвращаются к относительному импорту:
from app_demo import create_app
from app_demo.config import get_config
То есть префикс src., добавленный в последней сборке, был удален.
❷ Эта команда шага сборки образа делает файл requirements.txt устаревшим.
✿✿✿
Я делал еще один образ Docker для другого проекта Python, и подумал, что вместо этого попробую установить редактируемый образ RUN pip3 install -e . Я подумал, что мне все равно придется изменить исходные коды для абсолютного импорта, так почему бы просто не использовать setup.py, который уже есть. Сборка прошла без проблем. Я запустил ее, чтобы получить первый сбой импорта… Не сбой!
Он работает! Я до сих пор не знаю, почему он работает!
Поэтому я возвращаюсь к этому проекту, и отсюда этот пост. Изменения следующие:
File D:app_demoDockerfile
# syntax=docker/dockerfile:1
FROM python:3.10.5-slim-buster
WORKDIR /app_demo
COPY . .
RUN /usr/local/bin/python -m pip install --upgrade pip &&
pip3 install -e .
CMD [ "python3", "-m" , "flask", "run", "--host=0.0.0.0" ]
requirements.txt устарел; он добавлен в D:app_demo.dockerignore.
File D:app_demo.dockerignore
...
requirements.txt
Клонируйте новые изменения с помощью следующей команды, пожалуйста, выбросьте файл requirements.txt:
git clone -b v1.0.3 https://github.com/behai-nguyen/app-demo.git
Соберите и запустите, соответственно, с помощью:
D:app_demo>docker build --tag app-demo .
D:app_demo>docker run --publish 8000:5000 --rm app-demo
Запуск проходит успешно:
http://localhost:8000 отображает ожидаемый вывод Hello, World!
✿✿✿
Я не знаю, почему RUN pip3 install -e . работает… Пожалуйста, скажите мне, если вы знаете, я буду вам очень признателен.
С тех пор, как я принял решение использовать setup.py, этот шаг сборки образа Docker просто отлично работает. Я доволен. Спасибо, что прочитали, и я надеюсь, что вы найдете этот пост полезным.