Docker compose not installing django or not finding Django after installation

Docker-Compose.yml

version: '3.9'

services:
  nginx:
    restart: unless-stopped
    build:
      context: .
      dockerfile: ./docker/nginx/Dockerfile
    ports:
      - 80:80
      - 443:443
    volumes:
      - dev-static_volume:/vol/static
      - dev-media_volume:/vol/media
      - ./docker/nginx:/etc/nginx/conf.d
    depends_on:
      - app
    command: "/bin/sh -c 'while :; do sleep 6h & wait $${!}; nginx -s reload; done & nginx -g \"daemon off;\"'"

  app:
    restart: unless-stopped
    build:
      context: .
      dockerfile: ./docker/server/Dockerfile

    entrypoint: /app/docker/server/entrypoint.sh
    volumes:
      - dev-static_volume:/vol/static
      - dev-media_volume:/vol/media
    expose:
      - 8000
    environment:
      - DB_HOST=db
      - DB_NAME=devdb
      - DB_USER=devuser
      - DB_PASS=changeme
      - DEBUG=1
    depends_on:
      - db

  db:
    image: postgres:13-alpine
    volumes:
      - dev-db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=devdb
      - POSTGRES_USER=devuser
      - POSTGRES_PASSWORD=changeme

volumes:
  dev-static_volume:
  dev-media_volume:
  dev-db-data:

Dockerfile:

FROM python:3.10-alpine
MAINTAINER = 'Me'

ENV PYTHONUNBUFFERED 1

COPY ./fp-backend/requirements.txt /tmp/requirements.txt
COPY ./fp-backend/requirements.dev.txt /tmp/requirements.dev.txt
COPY ./fp-backend/app /app
COPY ./docker /app/docker
WORKDIR /app
EXPOSE 8000

ARG DEV=false
RUN python -m venv /py && \
    /py/bin/pip install --upgrade pip && \
    apk add --update --no-cache nodejs npm && \
    apk add --update --no-cache postgresql-client jpeg-dev && \
    apk add --update --no-cache --virtual .tmp-build-deps \
        build-base postgresql-dev musl-dev zlib zlib-dev linux-headers && \
    /py/bin/pip install -r /tmp/requirements.txt && \
    /py/bin/pip install Django && \
    if [ $DEV = "true" ]; \
        then /py/bin/pip install -r /tmp/requirements.dev.txt ; \
    fi && \
    rm -rf /tmp && \
    apk del .tmp-build-deps && \
    adduser \
        --disabled-password \
        --no-create-home \
        django-user && \
    mkdir -p /vol/web/media && \
    mkdir -p /vol/web/static && \
    chown -R django-user:django-user /app && \
    chmod -R 755 /app && \
    chmod -R +x /app/docker/server/entrypoint.sh


USER django-user

CMD ["entrypoint.sh"]

Contingency Script 'entrypoint.sh':

#!/bin/sh

set -e

until cd /app
do
    echo "Waiting for server volume..."
done


until python manage.py migrate
do
    echo "Waiting for db to be ready..."
    sleep 2
done

python manage.py collectstatic --noinput

python manage.py createsuperuser --noinput

gunicorn app.wsgi --bind 0.0.0.0:8000 --workers 4 --threads 4

Error Traceback:

 Traceback (most recent call last):
app_1    |   File "/app/manage.py", line 11, in main
app_1    |     from django.core.management import execute_from_command_line
app_1    | ModuleNotFoundError: No module named 'django'
app_1    |
app_1    | The above exception was the direct cause of the following exception:
app_1    |
app_1    | Traceback (most recent call last):
app_1    |   File "/app/manage.py", line 22, in <module>
app_1    |     main()
app_1    |   File "/app/manage.py", line 13, in main
app_1    |     raise ImportError(
app_1    | ImportError: Couldn't import Django. Are you sure it's installed and available on your PYTHONPATH environment variable? Did you forget to act
ivate a virtual environment?

I have no idea why this is failing to build, and it only started failing after i added NGINX, which is this:

server {
    listen 80;
    server_name _;
    server_tokens off;

    client_max_body_size 20M;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }

    location /api {
        try_files $uri @proxy_api;
    }
    location /admin {
        try_files $uri @proxy_api;
    }

    location @proxy_api {
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass   http://server:8000;
    }

    location /vol/static {
        autoindex on;
        alias /vol/static;
    }
    
    location /vol/media/ {
        autoindex on;
        alias /vol/media/;
    }
    
}

I have no idea why this would be failing. Why the server would not be able to find the django installation? I mean the code is fairly self explanatory, but i'm adding some lorem ipsum because apparently i cannot post this as mostly code.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum

In the Dockerfile, python -m venv /py creates a virtual environment in the /py directory, and then the subsequent calls to /py/bin/pip install ... install packages into that virtual environment. This means Django is installed in the virtual environment.

The ImportError: Couldn't import Django error is happening because entrypoint.sh doesn't use the virtual environment. Adding source /py/bin/activate toward the top of the file should fix it:

#!/bin/sh

set -e

source /py/bin/activate

until cd /app
do
    echo "Waiting for server volume..."
done


until python manage.py migrate
do
    echo "Waiting for db to be ready..."
    sleep 2
done

python manage.py collectstatic --noinput

python manage.py createsuperuser --noinput

gunicorn app.wsgi --bind 0.0.0.0:8000 --workers 4 --threads 4
Back to Top