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
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.