Python在Docker容器中使用Gunicorn运行时未解析主机(超时)(weasyprint需要这样做)

Python在Docker容器中使用Gunicorn运行时未解析主机(超时)(weasyprint需要这样做),python,django,docker,gunicorn,weasyprint,Python,Django,Docker,Gunicorn,Weasyprint,我有一个Django应用程序在docker容器中运行,它使用Gunicorn为应用程序提供服务。 此应用程序使用Weasyprint生成PDF,动态加载CSS。 此CSS由应用程序提供,它工作正常(并立即加载): host\u指向同一个\u machine.com/dynamic\u css\u path.css的\u (它不是一个静态文件,实际上是一个在django URL中定义的路径,用于输出CSS) 这就是weasyprint代码: css = weasyprint.CSS(url=req

我有一个Django应用程序在docker容器中运行,它使用Gunicorn为应用程序提供服务。 此应用程序使用Weasyprint生成PDF,动态加载CSS。 此CSS由应用程序提供,它工作正常(并立即加载):
host\u指向同一个\u machine.com/dynamic\u css\u path.css的\u

(它不是一个静态文件,实际上是一个在django URL中定义的路径,用于输出CSS)

这就是weasyprint代码:

css = weasyprint.CSS(url=request.build_absolute_uri(reverse('dynamic_css_path')))
        response = HttpResponse(pdf.write_pdf(stylesheets=[css]), content_type='application/pdf')
这会正确创建URL,如果我在开发机器和docker内部的远程服务器中使用django内置服务器(python manage.py runserver),而不是gunicorn,那么一切都会正常工作

但当我通过gunicorn提供应用程序时:
gunicorn项目。wsgi:application--bind 0.0.0.0:8000

然后python无法解析主机名,我通过以下操作证明了这一点:

1) 进入docker的应用程序控制台并尝试:

docker exec -it container_name /bin/ash
# ping host_pointing_to_that_same_machine.com
# ping any_other_host_pointing_an_external_machine.com
一切都很好

2) 进入docker容器内的Django控制台:

# python manage.py shell
>>> import urllib
>>> r = urllib.request.urlopen(url='http://host_pointing_to_that_same_machine.com', timeout=10)
>>> print('status: '+str(r.status))
# python
>>> from urllib import request
>>> r = request.urlopen(url='http://host_pointing_to_that_same_machine.com', timeout=10)
>>> print('status: '+str(r.status))
status: 200
返回200;一切都好

3) 在docker容器中输入python外壳:

# python manage.py shell
>>> import urllib
>>> r = urllib.request.urlopen(url='http://host_pointing_to_that_same_machine.com', timeout=10)
>>> print('status: '+str(r.status))
# python
>>> from urllib import request
>>> r = request.urlopen(url='http://host_pointing_to_that_same_machine.com', timeout=10)
>>> print('status: '+str(r.status))
status: 200
4) 在脚本中执行以下代码行,并由Gunicorn提供服务:

# docker logs container_name
Internal Server Error: /admin/app_name/path_to_pdf_generating_script/
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 128, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/utils/decorators.py", line 142, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/views/decorators/cache.py", line 44, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/django/contrib/admin/sites.py", line 223, in inner
    return view(request, *args, **kwargs)
  File "/srv/apps/project/admin/PdfMakingAdmin.py", line 125, in method_called_by_the_view
    timeout=10)
  File "/usr/local/lib/python3.6/urllib/request.py", line 223, in urlopen
    return opener.open(url, data, timeout)
  File "/usr/local/lib/python3.6/urllib/request.py", line 526, in open
    response = self._open(req, data)
  File "/usr/local/lib/python3.6/urllib/request.py", line 544, in _open
    '_open', req)
  File "/usr/local/lib/python3.6/urllib/request.py", line 504, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python3.6/urllib/request.py", line 1346, in http_open
    return self.do_open(http.client.HTTPConnection, req)
  File "/usr/local/lib/python3.6/urllib/request.py", line 1321, in do_open
    r = h.getresponse()
  File "/usr/local/lib/python3.6/http/client.py", line 1331, in getresponse
    response.begin()
  File "/usr/local/lib/python3.6/http/client.py", line 297, in begin
    version, status, reason = self._read_status()
  File "/usr/local/lib/python3.6/http/client.py", line 258, in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
  File "/usr/local/lib/python3.6/socket.py", line 586, in readinto
    return self._sock.recv_into(b)
socket.timeout: timed out
但是,如果我更改代码,而不是主机指向,那么\u same\u machine.com会尝试加载任何不指向该计算机的域,比如:

# docker logs container_name
status: 200
我会用其他一千种方法中的任何一种来实现我想要的结果,但是,这仍然困扰着我,我想知道这个问题和潜在的答案是否会对其他面对这个问题的人有用,无论他们是试图使用Weasyprint还是任何其他需要进行http查询的脚本

我将留下weasyprint在尝试原始代码时抛出的完整回溯:

Environment:


Request Method: GET
Request URL: http://host_pointing_to_that_same_machine.com/admin/path-to-app/

Django Version: 2.0
Python Version: 3.6.8

Traceback:

File "/usr/local/lib/python3.6/site-packages/weasyprint/urls.py" in fetch
  284.         result = url_fetcher(url)

File "/usr/local/lib/python3.6/site-packages/weasyprint/urls.py" in default_url_fetcher
  248.                            timeout=timeout, context=ssl_context)

File "/usr/local/lib/python3.6/urllib/request.py" in urlopen
  223.     return opener.open(url, data, timeout)

File "/usr/local/lib/python3.6/urllib/request.py" in open
  526.         response = self._open(req, data)

File "/usr/local/lib/python3.6/urllib/request.py" in _open
  544.                                   '_open', req)

File "/usr/local/lib/python3.6/urllib/request.py" in _call_chain
  504.             result = func(*args)

File "/usr/local/lib/python3.6/urllib/request.py" in http_open
  1346.         return self.do_open(http.client.HTTPConnection, req)

File "/usr/local/lib/python3.6/urllib/request.py" in do_open
  1321.             r = h.getresponse()

File "/usr/local/lib/python3.6/http/client.py" in getresponse
  1331.                 response.begin()

File "/usr/local/lib/python3.6/http/client.py" in begin
  297.             version, status, reason = self._read_status()

File "/usr/local/lib/python3.6/http/client.py" in _read_status
  258.         line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")

File "/usr/local/lib/python3.6/socket.py" in readinto
  586.                 return self._sock.recv_into(b)

During handling of the above exception (timed out), another exception occurred:

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  35.             response = get_response(request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  128.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  126.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/local/lib/python3.6/site-packages/django/utils/decorators.py" in _wrapped_view
  142.                     response = view_func(request, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
  44.         response = view_func(request, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/django/contrib/admin/sites.py" in inner
  223.             return view(request, *args, **kwargs)

File "/srv/apps/app_name/admin/PdfAdmin.py" in attendee_list
  134.         css = weasyprint.CSS(url=request.build_absolute_uri(reverse('view_to_dynamic_css')))

File "/usr/local/lib/python3.6/site-packages/weasyprint/__init__.py" in __init__
  322.         with result as (source_type, source, base_url, protocol_encoding):

File "/usr/local/lib/python3.6/contextlib.py" in __enter__
  81.             return next(self.gen)

File "/usr/local/lib/python3.6/site-packages/weasyprint/__init__.py" in _select_source
  407.         with fetch(url_fetcher, url) as result:

File "/usr/local/lib/python3.6/contextlib.py" in __enter__
  81.             return next(self.gen)

File "/usr/local/lib/python3.6/site-packages/weasyprint/urls.py" in fetch
  286.         raise URLFetchingError('%s: %s' % (type(exc).__name__, str(exc)))

Exception Type: URLFetchingError at /admin/app_name/path-to-pdf-generator/
Exception Value: timeout: timed out

在本例中,您正在命中,但在错误日志中,我看到您试图命中
http://host_pointing_to_that_same_machine.com/admin/path-to-app/

你好,阿卜杜勒,谢谢你的评论。此URL是一个正在执行脚本的URL,该脚本试图生成PDF,但在此过程中无法解析指向同一机器的主机。因此,它在浏览器中打开并完美解决(以及整个应用程序的其余部分),但在出现问题的地方,它在脚本中执行。