I have a Django REST framework API that I’m trying to run in Docker. The project uses Poetry 1.1.12. When running, I can see that Poetry is installed correctly, and that Poetry installs the packages in my pyproject.toml
, including Django. I’m using supervisor to run the API using Daphne, as well as some other tasks (like collecting static files).
However, when supervisor runs the app, I get:
Traceback (most recent call last):
File "/home/docker/api/manage.py", line 22, in <module>
main()
File "/home/docker/api/manage.py", line 13, in main
raise ImportError(
ImportError: Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to activate a virtual environment?
Traceback (most recent call last):
File "/home/docker/api/manage.py", line 11, in main
from django.core.management import execute_from_command_line
ModuleNotFoundError: No module named 'django'
Notice how I set POETRY_VIRTUALENVS_CREATE=false
and ENV PATH="/root/.local/bin:${PATH}"
. According to the poetry installation script, that is the path that needs to be added to PATH.
Here is an abridged versioned of my Dockerfile:
FROM python:3.9-slim-buster
ENV PATH="/root/.local/bin:${PATH}"
RUN apt-get update && apt-get install -y --no-install-recommends
...
curl
supervisor
&& curl -sSL 'https://install.python-poetry.org' | python - && poetry --version
&& apt-get remove -y curl
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false
&& apt-get clean -y && rm -rf /var/lib/apt/lists/*
&& rm -rf /var/lib/apt/lists/*
COPY poetry.lock pyproject.toml /home/docker/api/
WORKDIR /home/docker/api
RUN if [ "$DEBUG" = "false" ]
; then POETRY_VIRTUALENVS_CREATE=false poetry install --no-dev --no-interaction --no-ansi -vvv --extras "production"
; else POETRY_VIRTUALENVS_CREATE=false poetry install --no-interaction --no-ansi -vvv --extras "production"
; fi
COPY . /home/docker/api/
COPY .docker/services/api/files/supervisor.conf /etc/supervisor/conf.d/
CMD ["supervisord", "-n"]
Which is pretty much how I see others doing it. Any ideas?
2
Answers
Could it be because of a missing
DJANGO_SETTINGS_MODULE
environment variable?Poetry documents itself as trying very very hard to always run inside a virtual environment. However, a Docker container is itself isolation from other Pythons, and it’s normal (and easiest) to install packages in the "system" Python.
There is a
poetry export
command that can convert Poetry’s files to a normal piprequirements.txt
file, and from there you canRUN pip install
in your Dockerfile. You could use a multi-stage Dockerfile to generate that file without actually including Poetry in your main image.django
should show up in the generatedrequirements.txt
file, and sincepip install
installs it as a "normal" "system" Python package, your application should be able to see it normally, without tweaking environment variables or other settings.