簡體   English   中英

在使用 redis 對項目進行 docker-compose 后,Django 通道無法連接(查找)websocket

[英]Django channels unable to connect(find) websocket after docker-compose of project using redis

我目前已經使用 redis 層通過 django 通道實現了 websocket 連接。

我是 docker 新手,不知道我可能在哪里犯了錯誤。 docker-compose up -d --build "靜態文件、媒體、數據庫和gunicorn wsgi"所有功能后,redis 連接不上。 即使它在后台運行。

在嘗試使用 docker 將應用程序容器化之前,它適用於:

python manage.py runserver

使用 redis 層的以下 settings.py 設置:

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("0.0.0.0", 6379)],
        },
    },
}

並通過調用 redis 層的 docker 容器:

docker run -p 6379:6379 -d redis:5

但是在嘗試將整個應用程序容器化之后,它無法找到 websocket

docker-compose 的新設置如下:

version: '3.10'

services:
  web:
    container_name: web
    build: 
      context: ./app
      dockerfile: Dockerfile
    command: bash -c "gunicorn core.wsgi:application --bind 0.0.0.0:8000"
    volumes:
      - ./app/:/usr/src/app/
      - static_volume:/usr/src/app/staticfiles/
      - media_volume:/usr/src/app/media/
    ports:
      - 8000:8000
    env_file:
      - ./.env.dev
    depends_on:
      - db
    networks:
      - app_network


  redis:
    container_name: redis
    image: redis:5
    ports:
      - 6379:6379
    networks:
      - app_network
    restart: on-failure


  db:
    container_name: db
    image: postgres
    volumes:
      - postgres_data:/var/lib/postgresql/data/
    environment:
      - ./.env.psql
    ports:
      - 5432:5432
    networks:
      - app_network


volumes:
  postgres_data:
  static_volume:
  media_volume:

networks:
  app_network:

使用此 settings.py:

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("redis", 6379)],
        },
    },
}

成功構建容器並運行docker-compose logs -f后:

Attaching to web, db, redis
db       | The files belonging to this database system will be owned by user "postgres".
db       | This user must also own the server process.
db       | 
db       | The database cluster will be initialized with locale "en_US.utf8".
db       | The default database encoding has accordingly been set to "UTF8".
db       | The default text search configuration will be set to "english".
db       | 
db       | Data page checksums are disabled.
db       | 
db       | fixing permissions on existing directory /var/lib/postgresql/data ... ok
db       | creating subdirectories ... ok
db       | selecting dynamic shared memory implementation ... posix
db       | selecting default max_connections ... 100
db       | selecting default shared_buffers ... 128MB
db       | selecting default time zone ... Etc/UTC
db       | creating configuration files ... ok
db       | running bootstrap script ... ok
db       | performing post-bootstrap initialization ... ok
db       | initdb: warning: enabling "trust" authentication for local connections
db       | You can change this by editing pg_hba.conf or using the option -A, or
db       | --auth-local and --auth-host, the next time you run initdb.
db       | syncing data to disk ... ok
db       | 
db       | 
db       | Success. You can now start the database server using:
db       | 
db       |     pg_ctl -D /var/lib/postgresql/data -l logfile start
db       | 
db       | waiting for server to start....2022-06-27 16:18:30.303 UTC [48] LOG:  starting PostgreSQL 14.4 (Debian 14.4-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
db       | 2022-06-27 16:18:30.310 UTC [48] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db       | 2022-06-27 16:18:30.334 UTC [49] LOG:  database system was shut down at 2022-06-27 16:18:29 UTC
db       | 2022-06-27 16:18:30.350 UTC [48] LOG:  database system is ready to accept connections
db       |  done
db       | server started
db       | CREATE DATABASE
db       | 
db       | 
db       | /usr/local/bin/docker-entrypoint.sh: ignoring /docker-entrypoint-initdb.d/*
db       | 
db       | 2022-06-27 16:18:31.587 UTC [48] LOG:  received fast shutdown request
db       | waiting for server to shut down....2022-06-27 16:18:31.596 UTC [48] LOG:  aborting any active transactions
db       | 2022-06-27 16:18:31.601 UTC [48] LOG:  background worker "logical replication launcher" (PID 55) exited with exit code 1
db       | 2022-06-27 16:18:31.602 UTC [50] LOG:  shutting down
db       | 2022-06-27 16:18:31.650 UTC [48] LOG:  database system is shut down
db       |  done
db       | server stopped
db       | 
db       | PostgreSQL init process complete; ready for start up.
db       | 
db       | 2022-06-27 16:18:31.800 UTC [1] LOG:  starting PostgreSQL 14.4 (Debian 14.4-1.pgdg110+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 10.2.1-6) 10.2.1 20210110, 64-bit
db       | 2022-06-27 16:18:31.804 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
db       | 2022-06-27 16:18:31.804 UTC [1] LOG:  listening on IPv6 address "::", port 5432
db       | 2022-06-27 16:18:31.810 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db       | 2022-06-27 16:18:31.818 UTC [62] LOG:  database system was shut down at 2022-06-27 16:18:31 UTC
db       | 2022-06-27 16:18:31.825 UTC [1] LOG:  database system is ready to accept connections
redis    | 1:C 27 Jun 2022 16:18:29.080 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis    | 1:C 27 Jun 2022 16:18:29.080 # Redis version=5.0.14, bits=64, commit=00000000, modified=0, pid=1, just started
redis    | 1:C 27 Jun 2022 16:18:29.080 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis    | 1:M 27 Jun 2022 16:18:29.082 * Running mode=standalone, port=6379.
redis    | 1:M 27 Jun 2022 16:18:29.082 # Server initialized
redis    | 1:M 27 Jun 2022 16:18:29.082 * Ready to accept connections
web      | Waiting for postgres...
web      | PostgreSQL started
web      | Waiting for redis...
web      | redis started
web      | [2022-06-27 16:18:33 +0000] [1] [INFO] Starting gunicorn 20.1.0
web      | [2022-06-27 16:18:33 +0000] [1] [INFO] Listening at: http://0.0.0.0:8000 (1)
web      | [2022-06-27 16:18:33 +0000] [1] [INFO] Using worker: sync
web      | [2022-06-27 16:18:33 +0000] [8] [INFO] Booting worker with pid: 8
web      | [2022-06-27 16:19:18 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:8)
web      | [2022-06-27 18:19:18 +0200] [8] [INFO] Worker exiting (pid: 8)
web      | [2022-06-27 16:19:18 +0000] [9] [INFO] Booting worker with pid: 9
web      | Not Found: /ws/user_consumer/1/
web      | Not Found: /ws/accueil/accueil/
web      | Not Found: /ws/user_consumer/1/
web      | Not Found: /ws/accueil/accueil/

docker ps

CONTAINER ID   IMAGE                     COMMAND                  CREATED          STATUS          PORTS                                       NAMES
cb3e489e0831   dermatology-project_web   "/usr/src/app/entryp…"   35 minutes ago   Up 35 minutes   0.0.0.0:8000->8000/tcp, :::8000->8000/tcp   web
aee14c8665d0   postgres                  "docker-entrypoint.s…"   35 minutes ago   Up 35 minutes   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   db
94c29591b352   redis:5                   "docker-entrypoint.s…"   35 minutes ago   Up 35 minutes   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp   redis

構建 Dockerfile:

# set work directory

WORKDIR /usr/src/app

# set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1

# install psycopg2 dependencies
RUN apt-get update
RUN apt-get install -y libpq-dev python3-pip python-dev postgresql postgresql-contrib netcat

# install dependencies
RUN pip install --upgrade pip
COPY ./requirements.txt .
RUN pip install -r requirements.txt

# copy entrypoint.sh
COPY ./entrypoint.sh .
RUN sed -i 's/\r$//g' /usr/src/app/entrypoint.sh
RUN chmod +x /usr/src/app/entrypoint.sh


# create the appropriate directories for staticfiles

# copy project
COPY . .

# staticfiles
RUN python manage.py collectstatic --no-input --clear


# run entrypoint.sh
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]

以及檢查連接的入口點:

#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $SQL_HOST $SQL_PORT; do
        sleep 0.1
    done

    echo "PostgreSQL started"
fi

if [ "$CHANNEL" = "redis" ]
then
    echo "Waiting for redis..."

    while ! nc -z $REDIS_HOST $REDIS_PORT; do
        sleep 0.1
    done

    echo "redis started"
fi
#python manage.py flush --no-input
#python manage.py migrate

exec "$@"

我還嘗試像以前一樣單獨運行 redis 容器並維護工作容器,但這也不起作用。 我也在不同的端口上運行 daphne 並傳遞 asgi:application ( daphne -p 8001 myproject.asgi:application )時嘗試過它,它也沒有工作。

謝謝

最終管理了一個解決方案

為了使其工作,我需要將 wsgi 和 asgi 服務器彼此分開運行,每個服務器都有自己的容器。 此外,將端口暴露給應用程序的先前服務“web”也需要為每個容器運行兩次,其中 nginx 代理上游到每個相應的端口。

這一切都歸功於這個天才:

https://github.com/pplonski/simple-tasks

在這里,他解釋了我需要什么以及更多。 他還使用 celery workers 來管理基於分布式消息傳遞的異步任務隊列/作業隊列,這對我的項目來說有點矯枉過正,但很漂亮。

新的碼頭工人撰寫:

version: '2'

services:

    nginx:
        container_name: nginx
        restart: always
        build: ./nginx
        ports:
            - 1337:80
        volumes:
            - static_volume:/usr/src/app/staticfiles/
            - media_volume:/usr/src/app/media/
        depends_on:
            - wsgiserver
            - asgiserver

    postgres:
        container_name: postgres
        restart: always
        image: postgres
        volumes:
            - postgres_data:/var/lib/postgresql/data/
        ports:
            - 5433:5432
        expose:
            - 5432
        environment:
            - ./.env.db

    redis:
        container_name: redis
        image: redis:5
        restart: unless-stopped
        ports:
            - 6378:6379


    wsgiserver:
        build:            
            context: ./app
            dockerfile: Dockerfile
        container_name: wsgiserver
        command: gunicorn core.wsgi:application --bind 0.0.0.0:8000 
        env_file:
            - ./.env.dev
        volumes:
            - ./app/:/usr/src/app/
            - static_volume:/usr/src/app/staticfiles/
            - media_volume:/usr/src/app/media/
        links:
            - postgres
            - redis
        expose:
            - 8000


    asgiserver:
        build:            
            context: ./app
            dockerfile: Dockerfile
        container_name: asgiserver
        command: daphne core.asgi:application -b 0.0.0.0 -p 9000
        env_file:
            - ./.env.dev
        volumes:
            - ./app/:/usr/src/app/
        links:
            - postgres
            - redis
        expose:
            - 9000


volumes:
    static_volume: 
    media_volume:
    postgres_data:

新入口點.sh:

#!/bin/sh

if [ "$DATABASE" = "postgres" ]
then
    echo "Waiting for postgres..."

    while ! nc -z $SQL_HOST $SQL_PORT; do
        sleep 0.1
    done

    echo "PostgreSQL started"
fi

#python manage.py flush --no-input
#python manage.py migrate

exec "$@"

新的 nginx

nginx.conf:

server {
    listen 80;


    # gunicon wsgi server
    location / {
        try_files $uri @proxy_api;
    }

    location @proxy_api {
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Url-Scheme $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass   http://wsgiserver:8000;
    }


    # ASGI
    # map websocket connection to daphne
    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://asgiserver:9000;
    }
    
    # static and media files 
    location /static/ {
        alias /usr/src/app/staticfiles/;
    }
    location /media/ {
        alias /usr/src/app/media/;
    }
}

用於 nginx 的 Dockerfile:

FROM nginx:1.21

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

筆記

如果有人將此作為參考,這不是生產容器,還需要進一步的步驟。

本文解釋了另一個步驟: https ://testdriven.io/blog/dockerizing-django-with-postgres-gunicorn-and-nginx/#conclusion

,以及在結論鏈接中使用 Docker 和 Let's Encrypt 使用 AWS 保護應用程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM