3

I am attempting to build an environment, using Docker, Django, gunicorn, postgres and nginx. In this environment Dockerfile and docker-compose sits one level above src folder

My idea of folder structure is as follows:

"NN Project" folder within my "Documents/repositories"
└── / config (to place nginx settings within)
└── / deployment (to place environment "secrets" within)
└── / src (folder containing Django project)
    └── / config (Django project name)
        ├── wsgi.py
        ├── settings.py
├── Dockerfile
├── docker-compose
├── license, readme ...
├── build_script.sh

The reason I want to put Dockerfile and docker-compose at top-level and not under the sub-folder /src is because I want the ability to access env "secrets" when working in a container with Django and its relative import

NON_VERSION_PATH = Path(__file__).resolve().parent.parent.parent

with open(NON_VERSION_PATH / 'deployment/etc/application/.env_vars', 'r') as f:
    secrets = json.loads(f.read())

Problem I have is that I cannot get web (the "src" container) to start (it cannot find it). However, it works fine if I place Dockerfile and docker-compose within the /src folder but I would like to have the docker-compose one level up. I understand it is about relative import, however, I cannot figure out how to tell it to look in ./code

docker-compose

version: "3.9"

services:
  db:
    container_name: db
    image: postgres:alpine
    restart: always
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    environment:
      - POSTGRES_DB=postgres
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
  web:
    container_name: src
    build: .
    # command: python /code/src/manage.py runserver 0.0.0.0:8000 # works as intended !
    command: gunicorn config.setting.wsgi:application --bind 0.0.0.0:8000 --chdir ./src/
    volumes: 
      - .:/code
    ports:
      - 8000:8000
    depends_on:
      - db
    environment:
      - "DJANGO_SECRET_KEY= *** "
      - "DJANGO_DEBUG=True"

volumes:
  postgres_data:

Dockerfile

FROM python:3.8.5
# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
WORKDIR /code
COPY /src/requirements/requirements.txt /code/
RUN pip install -r requirements.txt
COPY . /code

Error

When my docker-compose using:

command: gunicorn config.setting.wsgi:application --bind 0.0.0.0:8000 --chdir ./src/

It produces the following error:

Successfully built 8473888f804
Successfully tagged web:latest
Creating src ... done
Attaching to src
src    | [2021-03-09 15:10:44 +0000] [1] [INFO] Starting gunicorn 20.0.4
src    | [2021-03-09 15:10:44 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
src    | [2021-03-09 15:10:44 +0000] [1] [INFO] Using worker: sync
src    | [2021-03-09 15:10:44 +0000] [8] [INFO] Booting worker with pid: 8
src    | [2021-03-09 15:10:44 +0000] [8] [ERROR] Exception in worker process
src    | Traceback (most recent call last):
src    |   File "/usr/local/lib/python3.8/site-packages/gunicorn/arbiter.py", line 583, in spawn_worker
src    |     worker.init_process()
src    |   File "/usr/local/lib/python3.8/site-packages/gunicorn/workers/base.py", line 119, in init_process
src    |     self.load_wsgi()
src    |   File "/usr/local/lib/python3.8/site-packages/gunicorn/workers/base.py", line 144, in load_wsgi
src    |     self.wsgi = self.app.wsgi()
src    |   File "/usr/local/lib/python3.8/site-packages/gunicorn/app/base.py", line 67, in wsgi
src    |     self.callable = self.load()
src    |   File "/usr/local/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 49, in load
src    |     return self.load_wsgiapp()
src    |   File "/usr/local/lib/python3.8/site-packages/gunicorn/app/wsgiapp.py", line 39, in load_wsgiapp
src    |     return util.import_app(self.app_uri)
src    |   File "/usr/local/lib/python3.8/site-packages/gunicorn/util.py", line 358, in import_app
src    |     mod = importlib.import_module(module)
src    |   File "/usr/local/lib/python3.8/importlib/__init__.py", line 127, in import_module
src    |     return _bootstrap._gcd_import(name[level:], package, level)
src    |   File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
src    |   File "<frozen importlib._bootstrap>", line 991, in _find_and_load
src    |   File "<frozen importlib._bootstrap>", line 961, in _find_and_load_unlocked
src    |   File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
src    |   File "<frozen importlib._bootstrap>", line 1014, in _gcd_import
src    |   File "<frozen importlib._bootstrap>", line 991, in _find_and_load
src    |   File "<frozen importlib._bootstrap>", line 973, in _find_and_load_unlocked
src    | ModuleNotFoundError: No module named 'config.setting'
src    | [2021-03-09 15:10:44 +0000] [8] [INFO] Worker exiting (pid: 8)
src    | [2021-03-09 15:10:44 +0000] [1] [INFO] Shutting down: Master
src    | [2021-03-09 15:10:44 +0000] [1] [INFO] Reason: Worker failed to boot.

Q: How do I get the project to start gunicorn?

Solution: In addition to accepted solution, this SO post also did the trick.

command: gunicorn -w 2 -b 0.0.0.0:8000 --chdir ./src/ config.wsgi:application --reload --timeout 900
Jaco
  • 1,564
  • 2
  • 9
  • 33

1 Answers1

4

use the --chdir flag. for example, gunicorn config.wsgi:application --bind 0.0.0.0:8000 --chdir /path/to/project/root/

mr blu
  • 400
  • 5
  • 8
  • Hi, should it be on a certain format. I have tried 'command: gunicorn config.setting.wsgi:application --bind 0.0.0.0:8000 --chdir /code/src' but still get " ModuleNotFoundError: No module named 'config.setting'" – Jaco Mar 09 '21 at 14:39
  • 1
    try changing the directive to be ./src/ – mr blu Mar 09 '21 at 14:53
  • found what you were looking for? – mr blu Mar 09 '21 at 15:05
  • 1
    ok, here is a solution that can help avoid having to change directories. so, in the Dockerfile, copy your src folder to current like this, `COPY ./src .` Then serve the apps like `gunicorn config.wsgi:application --bind 0.0.0.0:8000` note, i have dropped settings after `config.` because the wsgi file is located under config – mr blu Mar 09 '21 at 15:37