Search code examples
djangodockernginxgunicornsupervisord

Gunicorn service stopping under supervisor with docker


I've using supervisor, nginx and gunicorn to deploy Django project with Docker. I'm running docker-compose up to build the project and nginx image.

Going through other similar issues, it is recommended to use absolute path such as /home/ubuntu/... But since I'm using docker containers to run the project where I'm copying project in /app with COPY . /app/. I'm confused as to what write in directory in supervisor file.

gunicorn installation is being done while installing requirements.txt

Below is my supervisor configuration.

[supervisord]
nodaemon=true

[program:gunicorn]
command=gunicorn trade_calls.wsgi:application --bind 0.0.0.0:8000
directory=/app
user=root
autostart=true
autorestart=true
stderr_logfile=/var/log/gunicorn.err.log
stdout_logfile=/var/log/gunicorn.out.log

[program:nginx]
command=nginx -g "daemon off;"
autostart=true
autorestart=true
stderr_logfile=/var/log/nginx.err.log
stdout_logfile=/var/log/nginx.out.log

The error I'm facing is

docker-compose logs -f web
web-1  | 2024-06-26 21:41:45,768 CRIT Supervisor is running as root.  Privileges were not dropped because no user is specified in the config file.  If you intend to run as root, you can set user=root in the config file to avoid this message.
web-1  | 2024-06-26 21:41:45,771 INFO supervisord started with pid 1
web-1  | 2024-06-26 21:41:46,775 INFO spawned: 'gunicorn' with pid 7
web-1  | 2024-06-26 21:41:46,779 INFO spawned: 'nginx' with pid 8
web-1  | 2024-06-26 21:41:47,365 WARN exited: gunicorn (exit status 3; not expected)
web-1  | 2024-06-26 21:41:48,368 INFO spawned: 'gunicorn' with pid 11
web-1  | 2024-06-26 21:41:48,368 INFO success: nginx entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
web-1  | 2024-06-26 21:41:50,031 INFO success: gunicorn entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
web-1  | 2024-06-26 21:41:50,031 WARN exited: gunicorn (exit status 1; not expected)
web-1  | 2024-06-26 21:41:51,034 INFO spawned: 'gunicorn' with pid 15
web-1  | 2024-06-26 21:41:51,612 WARN exited: gunicorn (exit status 3; not expected)
web-1  | 2024-06-26 21:41:52,615 INFO spawned: 'gunicorn' with pid 17
web-1  | 2024-06-26 21:41:53,181 WARN exited: gunicorn (exit status 3; not expected)
web-1  | 2024-06-26 21:41:55,185 INFO spawned: 'gunicorn' with pid 19
web-1  | 2024-06-26 21:41:55,753 WARN exited: gunicorn (exit status 3; not expected)
web-1  | 2024-06-26 21:41:58,758 INFO spawned: 'gunicorn' with pid 21
web-1  | 2024-06-26 21:41:59,320 WARN exited: gunicorn (exit status 3; not expected)
web-1  | 2024-06-26 21:42:00,321 INFO gave up: gunicorn entered FATAL state, too many start retries too quickly

Specific gunicorn error from gunicorn.err.log

Traceback (most recent call last):
  File "/usr/local/bin/gunicorn", line 8, in <module>
    sys.exit(run())
             ^^^^^
  File "/usr/local/lib/python3.11/site-packages/gunicorn/app/wsgiapp.py", line 67, in run
    WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]", prog=prog).run()
  File "/usr/local/lib/python3.11/site-packages/gunicorn/app/base.py", line 236, in run
    super().run()
  File "/usr/local/lib/python3.11/site-packages/gunicorn/app/base.py", line 72, in run
    Arbiter(self).run()
  File "/usr/local/lib/python3.11/site-packages/gunicorn/arbiter.py", line 229, in run
    self.halt(reason=inst.reason, exit_status=inst.exit_status)
  File "/usr/local/lib/python3.11/site-packages/gunicorn/arbiter.py", line 342, in halt
    self.stop()
  File "/usr/local/lib/python3.11/site-packages/gunicorn/arbiter.py", line 396, in stop
    time.sleep(0.1)
  File "/usr/local/lib/python3.11/site-packages/gunicorn/arbiter.py", line 242, in handle_chld
    self.reap_workers()
  File "/usr/local/lib/python3.11/site-packages/gunicorn/arbiter.py", line 530, in reap_workers
    raise HaltServer(reason, self.WORKER_BOOT_ERROR)
gunicorn.errors.HaltServer: <HaltServer 'Worker failed to boot.' 3>

Dockerfile

FROM python:3.11.9-slim

ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

WORKDIR /app

RUN apt-get update \
    && apt-get install -y --no-install-recommends \
        gcc \
        python3-dev \
        musl-dev \
        postgresql-client \
        libpq-dev \
        nginx \
        supervisor \
    && rm -rf /var/lib/apt/lists/*

RUN rm /etc/nginx/nginx.conf
COPY nginx.conf /etc/nginx/nginx.conf

COPY requirements.txt /app/
RUN pip install --no-cache-dir -r requirements.txt

COPY . /app/

RUN python manage.py collectstatic --no-input
RUN python manage.py makemigrations
RUN python manage.py migrate

COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf

EXPOSE 80

CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]

docker-compose

services:
  web:
    build: .
    command: /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
    environment:
      DATABASE_NAME: ###
      DATABASE_USER: ###
      DATABASE_PASSWORD: ###
      DATABASE_HOST: ###
      DATABASE_PORT: 5432
    volumes:
      - /path_to_static:/app/static #edited for stackoverflow
      - /path_to_static:/app/media #edited for stackoverflow
    networks:
      - backend

  nginx:
    build:
      context: .
      dockerfile: Dockerfile.nginx
    ports:
      - "80:80"
    volumes:
      - /path_to_static:/app/static #edited for stackoverflow
      - /path_to_static:/app/media #edited for stackoverflow
    networks:
      - backend
    depends_on:
      - web

networks:
  backend:

Dockerfile.nginx

FROM nginx:latest
RUN rm /etc/nginx/nginx.conf
COPY nginx.conf /etc/nginx/nginx.conf

Solution

  • Since I placed Dockerfile and other files including supervisor conf outside root django project. Gunicorn was unable to look for wsgi. I had to point directory=/app/trade_calls which is the root of django project.