Как настроить NGINX для обслуживания ASGI из сокета UNIX?
Я не могу подключить приложение, работающее на ASGI + Gunicorn, через сокет Unix на NGINX на локальном хосте через докер-контейнер.
При условии, что я нахожусь в докере контейнера и запускаю NGINX:
/usr/sbin/nginx
Я могу открыть http://localhost/api/v1/items и получить 404 от NGINX, что означает, что он по крайней мере работает.
Запустив сервис Docker, я могу запустить Gunicorn с помощью следующей команды:
gunicorn app.main:app --name asgi --workers 3 --user=root --group=root --bind=unix:///tmp/asgi.sock --log-level=debug --log-file=- -k uvicorn.workers.UvicornWorker -c /gunicorn_conf.py
Gunicorn запускается правильно, и с помощью другого exec я могу свернуть сокет UNIX, к которому я привязан, и получить ответ 200.
curl --unix-socket ///tmp/asgi.sock http://localhost/api/v1/items
Я думаю, это означает, что у меня есть некоторые расхождения в конфигурации NGINX, направляющей трафик на http://localhost/api/v1/items.
nginx.conf
daemon off;
user nginx;
worker_processes 1;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
access_log /dev/stdout;
upstream asgi {
server unix:/tmp/asgi.sock fail_timeout=0;
}
server {
listen 80;
server_name localhost;
client_max_body_size 4G;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://asgi;
}
}
}
gunicorn_conf.py
import json
import multiprocessing
import os
workers_per_core_str = os.getenv("WORKERS_PER_CORE", "1")
web_concurrency_str = os.getenv("WEB_CONCURRENCY", None)
host = os.getenv("HOST", "unix")
port = os.getenv("PORT", "///tmp/asgi.sock")
bind_env = os.getenv("BIND", None)
use_loglevel = os.getenv("LOG_LEVEL", "info")
if bind_env:
use_bind = bind_env
else:
use_bind = f"{host}:{port}"
cores = multiprocessing.cpu_count()
workers_per_core = float(workers_per_core_str)
default_web_concurrency = workers_per_core * cores
if web_concurrency_str:
web_concurrency = int(web_concurrency_str)
assert web_concurrency > 0
else:
web_concurrency = max(int(default_web_concurrency), 2)
# Gunicorn config variables
loglevel = use_loglevel
workers = web_concurrency
bind = use_bind
keepalive = 120
errorlog = "-"
# For debugging and testing
log_data = {
"loglevel": loglevel,
"workers": workers,
"bind": bind,
# Additional, non-gunicorn variables
"workers_per_core": workers_per_core,
"host": host,
"port": port,
}
print(json.dumps(log_data))
ОБНОВЛЕНИЕ:
Однако мне удалось решить мою проблему, оставив это здесь с запиской. В моем исходном посте в моей конфигурации NGINX не было сервера внутри блока http, и я обновил свои журналы для записи в консоль, хотя это и не имеет большого значения, если предположить, что расположение файла существует.
Я также запускаю NGINX и Gunicorn через Supervisord, который изначально не был заявлен, так как я чувствовал, что это выходит за рамки проблемы. Тем не менее, теперь я могу запустить оба процесса с Supervisord, но мне пришлось daemon off;
в конфигурацию NGINX, чтобы заставить это работать; без этого процесс сказал бы, что порт уже используется.
Я обновил свой пост своей последней версией моего конфига, включая supervisor.ini
supervisor.ini
[supervisord]
nodaemon=true
[program:asgi]
command=gunicorn app.main:app --name asgi --workers 3 --user=root --group=root --bind=unix:/tmp/asgi.sock --log-level=debug --log-file=- -k uvicorn.workers.UvicornWorker -c /gunicorn_conf.py
user = root ; User to run as
autostart=true
autorestart=true
stdout_logfile=/dev/stdout ; Where to write log messages
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8 ; Set UTF-8 as default encoding
[program:nginx]
command=/usr/sbin/nginx -c /etc/nginx/conf.d/nginx.conf
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
# Graceful stop, see http://nginx.org/en/docs/control.html
stopsignal=QUIT
Для запуска супервизора: /usr/bin/supervisord -c /etc/supervisor.d/supervisord.ini
Попробуйте сами, посмотрите репозиторий github, который я сделал для этого приложения.
1 ответ
Решил мою проблему и обновил оригинальный вопрос с измененными файлами. Основной проблемой было использование демона off для supervisord, позволяющего запускать NGINX и Gunicorn, и размещение конфигурации сервера NGINX внутри html-блока.