Развертывание dockerized Django с каналами + Nginx + Daphne - PullRequest
1 голос
/ 08 апреля 2020

У меня есть приложение django, работающее в Docker, которое использует каналы 2 (для приложения чата). При запуске docker -compose на локальном сайте и чат веб-сокета работает как шарм.

Теперь я попытался развернуть проект: я хочу запустить весь проект только на ASGI с daphne (вместо Daphne для Websocket и gunicorn для стандартных запросов). Ну, я пробовал это в течение трех дней, у меня не получается. Я полностью потерян.

Веб-сайт со «стандартными» http-запросами через https работает отлично, чат с веб-сокетами выдает ошибку 500, но сообщение об ошибке чудо для меня. Я действительно понятия не имею, что делать дальше.

(должен сказать, я новичок в django, nginx и websockets)

Моя настройка: Django , Django Каналы, Redis, Nginx, Docker, Дафна

Django Имя проекта - xtools

Это мое производство docker -составить:

version: '3.7'

services:
  web:
    container_name: 'web'
    build: 
      context: ./app
      dockerfile: Dockerfile.prod
    command: daphne -b 0.0.0.0 -p 8000 xtools.asgi:application
    volumes:
      - static_volume:/home/app/web/static
      - media_volume:/home/app/web/mediafiles
    expose:
      - 8000
    env_file:
      - ./.env.prod
    depends_on:
      - db
    networks:
      - docker-network

  redis:
    image: redis:latest
    command: ["redis-server", "--bind", "redis", "--port", "6379"]

  db:
    image: postgres:12.0-alpine
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    env_file:
      - ./.env.prod.db
    networks:
      - docker-network
  nginx:
    build: ./nginx
    volumes:
      - static_volume:/home/app/web/staticfiles
      - media_volume:/home/app/web/mediafiles
      - ./dhparam/dhparam-2048.pem:/etc/ssl/certs/dhparam-2048.pem
      - /docker-volumes/etc/letsencrypt/live/example.com/fullchain.pem:/etc/letsencrypt/live/example.com/fullchain.pem
      - /docker-volumes/etc/letsencrypt/live/example.com/privkey.pem:/etc/letsencrypt/live/example.com/privkey.pem
      - /docker-volumes/data/letsencrypt:/data/letsencrypt
    ports:
      - 80:80
      - 443:443
    depends_on:
      - web
    networks:
      - docker-network

volumes:
  postgres_data:
  static_volume:
  media_volume:

networks:
  docker-network:
    driver: bridge

Это мой nginx conf:

upstream toolbox {
    server web:8000;
}


proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=tool_cache:10m max_size=10g inactive=60m use_temp_path=off;

server {
        listen 443 ssl;
        listen [::]:443 ssl;
        server_name xtools.com;

        server_tokens off;

        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

        ssl_buffer_size 8k;

        ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;

        ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
        ssl_prefer_server_ciphers on;

        ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;

        ssl_ecdh_curve secp384r1;
        ssl_session_tickets off;

        ssl_stapling on;
        ssl_stapling_verify on;
        resolver 8.8.8.8;


        location /ws/ {
            try_files $uri @proxy_to_ws;
        }

        location @proxy_to_ws {
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_redirect off;

            proxy_pass   http://toolbox;
        }

        location / {
            proxy_pass http://toolbox;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_redirect off;
            proxy_cache tool_cache;
            proxy_cache_valid any 48h;


            add_header X-Cached $upstream_cache_status;

            # Simple requests
            if ($request_method ~* "(GET|POST)") {
              add_header "Access-Control-Allow-Origin"  *;
            }

        }

        location /static/ {
            alias /home/app/web/staticfiles/;
        }

        location /mediafiles/ {
            alias /home/app/web/mediafiles/;
        }

}

И это сообщение об ошибке:

2020-04-08 14:40:11,802 ERROR    Exception inside application: [Errno -2] Name does not resolve
File "/usr/local/lib/python3.8/site-packages/channels/sessions.py", line 183, in __call__
  return await self.inner(receive, self.send)
File "/usr/local/lib/python3.8/site-packages/channels/middleware.py", line 41, in coroutine_call
  await inner_instance(receive, send)
File "/usr/local/lib/python3.8/site-packages/channels/consumer.py", line 58, in __call__
  await await_many_dispatch(
File "/usr/local/lib/python3.8/site-packages/channels/utils.py", line 58, in await_many_dispatch
  await task
File "/usr/local/lib/python3.8/site-packages/channels_redis/core.py", line 434, in receive
  message_channel, message = await self.receive_single(
File "/usr/local/lib/python3.8/site-packages/channels_redis/core.py", line 489, in receive_single
  content = await self._brpop_with_clean(
File "/usr/local/lib/python3.8/site-packages/channels_redis/core.py", line 330, in _brpop_with_clean
  async with self.connection(index) as connection:
File "/usr/local/lib/python3.8/site-packages/channels_redis/core.py", line 835, in __aenter__
  self.conn = await self.pool.pop()
File "/usr/local/lib/python3.8/site-packages/channels_redis/core.py", line 73, in pop
  conns.append(await aioredis.create_redis(**self.host, loop=loop))
File "/usr/local/lib/python3.8/site-packages/aioredis/commands/__init__.py", line 168, in create_redis
  conn = await create_connection(address, db=db,
File "/usr/local/lib/python3.8/site-packages/aioredis/connection.py", line 111, in create_connection
  reader, writer = await asyncio.wait_for(open_connection(
File "/usr/local/lib/python3.8/asyncio/tasks.py", line 455, in wait_for
  return await fut
File "/usr/local/lib/python3.8/site-packages/aioredis/stream.py", line 23, in open_connection
  transport, _ = await get_event_loop().create_connection(
File "/usr/local/lib/python3.8/asyncio/base_events.py", line 978, in create_connection
  infos = await self._ensure_resolved(
File "/usr/local/lib/python3.8/asyncio/base_events.py", line 1350, in _ensure_resolved
  return await loop.getaddrinfo(host, port, family=family, type=type,
File "/usr/local/lib/python3.8/asyncio/base_events.py", line 817, in getaddrinfo
  return await self.run_in_executor(
File "/usr/local/lib/python3.8/concurrent/futures/thread.py", line 57, in run
  result = self.fn(*self.args, **self.kwargs)
File "/usr/local/lib/python3.8/socket.py", line 914, in getaddrinfo
  for res in _socket.getaddrinfo(host, port, family, type, proto, flags):

Redis говорит мне, что работает

redis_1  | 1:M 08 Apr 2020 14:37:56.433 * Ready to accept connections

Дафна принимает подключения, веб-сайт работает, как упоминалось ранее:

web      | 2020-04-08 14:38:01,587 INFO     Starting server at tcp:port=8000:interface=0.0.0.0
web      | 2020-04-08 14:38:01,588 INFO     HTTP/2 support not enabled (install the http2 and tls Twisted extras)
web      | 2020-04-08 14:38:01,589 INFO     Configuring endpoint tcp:port=8000:interface=0.0.0.0
web      | 2020-04-08 14:38:01,590 INFO     Listening on TCP address 0.0.0.0:8000
web      | 2020-04-08 14:38:05,597 ERROR    Exception inside application: [Errno -2] Name does not resolve

Я понятия не имею, к чему относится это «Имя не разрешается». Мой потребительский код отлично работает в моей местной среде. В производстве потребитель даже не вызывается (я поместил в него много операторов print, просто чтобы посмотреть, есть ли где-то ошибка).

Nginx В журналах ошибок повторяется эта ошибка при открытии страница чата с веб-сокетами:

2020/04/08 17:36:12 [emerg] 18725#18725: bind() to 0.0.0.0:80 failed (98: Address already in use)
 25 2020/04/08 17:36:12 [emerg] 18725#18725: still could not bind()
 26 2020/04/08 17:36:17 [notice] 18736#18736: signal process started
 27 2020/04/08 17:36:20 [notice] 18741#18741: signal process started

Мой клиент Websocket Call

var ws_scheme = window.location.protocol == "https:" ? "wss://" : "ws://";
var chatSocket = new ReconnectingWebSocket(
        ws_scheme + window.location.host +
        '/ws/chat/' + roomName + '/'
        );

что еще я могу сделать? Я проверил сервер Redis, который работает. Дафна работает и обслуживает страницы, как и должно быть.

Любая помощь приветствуется! Спасибо, Бомби

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...