Python Django OSError:[Errno 99]地址不可用

问题描述 投票:0回答:1

我正在使用

Django Rest Framework
创建一个应用程序,并正在努力解决使用
Djoser
发送电子邮件时出现的奇怪问题。当我尝试在生产环境中的
Docker
容器内的主机上重现此错误时,我没有任何错误,所有电子邮件均已成功发送,但是当我尝试在
Docker
下的生产服务器上执行此操作时,我得到
 OsError
,这是完整的回溯:

Traceback (most recent call last):
  File "/usr/local/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/contextlib.py", line 81, in inner
    return func(*args, **kwds)
           ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view
    return view_func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/rest_framework/viewsets.py", line 125, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
    ^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/rest_framework/mixins.py", line 19, in create
    self.perform_create(serializer)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/djoser/views.py", line 140, in perform_create
    settings.EMAIL.activation(self.request, context).send(to)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/templated_mail/mail.py", line 78, in send
    super(BaseEmailMessage, self).send(*args, **kwargs)
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/django/core/mail/message.py", line 298, in send
    return self.get_connection(fail_silently).send_messages([self])
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/django/core/mail/backends/smtp.py", line 127, in send_messages
    new_conn_created = self.open()
                       ^^^^^^^^^^^
  File "/usr/local/lib/python3.12/site-packages/django/core/mail/backends/smtp.py", line 85, in open
    self.connection = self.connection_class(
                      
  File "/usr/local/lib/python3.12/smtplib.py", line 255, in __init__
    (code, msg) = self.connect(host, port)
                  ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/smtplib.py", line 341, in connect
    self.sock = self._get_socket(host, port, self.timeout)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/smtplib.py", line 312, in _get_socket
    return socket.create_connection((host, port), timeout,
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/socket.py", line 852, in create_connection
    raise exceptions[0]
    ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.12/socket.py", line 837, in create_connection
    sock.connect(sa)
    ^^^^^^^^^^^^^^^^

Exception Type: OSError at /api/auth/users/
Exception Value: [Errno 99] Address not available
Raised during: djoser.views.UserViewSet
Request information:

这是我的

docker-compose.yaml

version: '3.8'

services:
  # PostgreSQL
  db:
    image: postgres:12.18-alpine
    restart: always
    networks:
      - backend-network
    env_file:
      - .env
    expose:
      - '5432'
    volumes:
      - db_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 10s
      timeout: 3s
      retries: 3

  # BackEnd
  backend:
    build:
      context: .
      target: prod
    networks:
      - backend-network
    ports:
      - '8000:8000'
    env_file:
      - .env
    volumes:
      - .:/backend
    restart: always
    depends_on:
      db:
        condition: service_healthy

networks:
  backend-network:
    driver: bridge

volumes:
  db_data:

SMTP 服务器设置:

EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
EMAIL_HOST = env("EMAIL_HOST")
EMAIL_USE_TLS = True
EMAIL_PORT = env("EMAIL_PORT")
EMAIL_HOST_USER = env("EMAIL_HOST_USER")
EMAIL_HOST_PASSWORD = env("EMAIL_HOST_PASSWORD")

我确信我使用的

SMTP
服务器没有问题,因为在我的计算机上它工作正常,电子邮件已发送。此外,当我尝试从生产服务器上的
SMTP
容器 ping
Docker
服务器时,我收到了一些从中收到的字节。另外,我认为这个问题与
Djoser
无关。

我好几天都无法解决问题,也不知道出了什么问题。 我将非常感谢任何帮助

python django docker smtp
1个回答
0
投票

错误消息

[Errno 99] Address not available
表示在 Docker 容器内运行的 Django 应用程序无法与您配置的 SMTP 服务器建立网络连接。虽然服务器似乎可以从您的开发计算机访问,并且可能可以从容器 ping 通,但可能存在一些配置差异,导致 Docker 内出现问题。

一些潜在的解决方案:

  1. 验证 Docker 网络: 确保您的

    backend
    中的
    docker-compose.yaml
    服务可以访问 SMTP 服务器所在的网络。默认情况下,Docker 在同一
    docker-compose.yaml
    文件中为服务创建桥接网络。如果 SMTP 服务器位于单独的网络上,您可能需要配置自定义网络或使用主机名解析技术。

  2. 检查 DNS 解析:在 Docker 容器内,尝试使用

    ping <SMTP_server_hostname>.
    解析 SMTP 服务器的主机名。如果主机名未解析为 IP 地址,则您的容器可能使用与开发计算机不同的 DNS 服务器。您可以尝试在
    docker-compose.yaml
    中为后端服务指定自定义 DNS 服务器。

  3. 验证环境变量:仔细检查

    .env
    文件是否已正确安装在后端服务的
    docker-compose.yaml
    中。确保环境变量(
    EMAIL_HOST
    EMAIL_PORT
    等)在
    .env
    文件中正确设置,并且可以在容器内访问。您可以在 Django 应用程序中使用
    print(os.environ.get('EMAIL_HOST'))
    来验证它们。

  4. 手动检查 SMTP 连接: 不要依赖 Djoser 发送电子邮件,而是尝试显式创建电子邮件对象并使用 Django 的

    EmailMessage
    模块中的
    django.core.mail
    发送它。这将有助于确定问题是否出在 Djoser 或底层 SMTP 连接上。

  5. 网络安全组(如果适用):如果您的生产服务器使用安全组来限制网络流量,请确保 Docker 容器的子网或 SMTP 服务器使用的端口(通常为 TLS 的端口 587)允许出站流量IP地址。

© www.soinside.com 2019 - 2024. All rights reserved.