skip to Main Content

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


  1. Could it be because of a missing DJANGO_SETTINGS_MODULE environment variable?

    Login or Signup to reply.
  2. 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 pip requirements.txt file, and from there you can RUN pip install in your Dockerfile. You could use a multi-stage Dockerfile to generate that file without actually including Poetry in your main image.

    FROM python:3.9-slim-buster AS poetry
    RUN pip install poetry
    WORKDIR /app
    COPY pyproject.toml poetry.lock .
    RUN poetry export -f requirements.txt --output requirements.txt
    
    FROM python:3.9-slim-buster
    WORKDIR /app
    COPY --from=poetry /app/requirements.txt .
    RUN pip install -r requirements.txt
    COPY . .
    CMD ["./manage.py", "runserver", "0.0.0.0:8000"]
    

    django should show up in the generated requirements.txt file, and since pip 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search