无法访问Docker容器中的Flask应用程序

3
我一直在尝试在Docker容器内创建一个Flask app。当通过Flask开发服务器运行该应用程序时,包括从网络上的其他计算机访问网页,它完全正常工作。
我一直在尝试为该应用程序构建一个Docker容器。问题是我无法访问任何网页,我得到了500错误。
我的一些设置:

run.py

#!flask_v1/bin/python3
from app import app
app.run(debug=True, host='0.0.0.0')

其中 flask_v1 是虚拟环境目录。

dockerfile

FROM python:3.4
COPY . /site
workdir /site
RUN pip install -r requirements.txt
ENV NAME sitename
CMD ["python", "./run.py"]

我从这个版本中删除了EXPOSE 5000,但即使它存在,仍然发生了相同的问题。它最初是放在pip行下面的。

requirements.txt

click==6.7
CouchDB==1.1
docutils==0.14
Flask==0.12.2
Flask-CouchDB==0.2.1
flask-dynamo==0.1.2
Flask-Login==0.4.0
Flask-WTF==0.14.2
itsdangerous==0.24
Jinja2==2.9.6
jmespath==0.9.3
MarkupSafe==1.0
python-dateutil==2.6.1
PyYAML==3.12
s3transfer==0.1.11
six==1.11.0
Werkzeug==0.12.2
WTForms==2.1

我将以下命令作为生成命令运行(将dockername替换为实际名称):
docker build -t dockername .

构建完成后,我按照以下方式运行图像:

docker run -p 5000:5000 dockername

尝试连接到应用程序的主页,地址为localhost:5000/index、localhost:5000、127.0.0.1:5000/index、[host_ip]:5000/index或[container_ip]:5000/index都会产生相同的错误:
Traceback (most recent call last):
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1997, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.4/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1610, in full_dispatch_request
    rv = self.preprocess_request()
  File "/usr/local/lib/python3.4/site-packages/flask/app.py", line 1831, in preprocess_request
    rv = func()
  File "/usr/local/lib/python3.4/site-packages/flaskext/couchdb.py", line 154, in request_start
    self.sync(current_app)
  File "/usr/local/lib/python3.4/site-packages/flaskext/couchdb.py", line 131, in sync
    if db_name not in server:
  File "/usr/local/lib/python3.4/site-packages/couchdb/client.py", line 96, in __contains__
    self.resource.head(name)
  File "/usr/local/lib/python3.4/site-packages/couchdb/http.py", line 549, in head
    return self._request('HEAD', path, headers=headers, **params)
  File "/usr/local/lib/python3.4/site-packages/couchdb/http.py", line 581, in _request
    credentials=self.credentials)
  File "/usr/local/lib/python3.4/site-packages/couchdb/http.py", line 289, in request
    conn = self.connection_pool.get(url)
  File "/usr/local/lib/python3.4/site-packages/couchdb/http.py", line 507, in get
    conn.connect()
  File "/usr/local/lib/python3.4/http/client.py", line 871, in connect
    self.timeout, self.source_address)
  File "/usr/local/lib/python3.4/socket.py", line 516, in create_connection
    raise err
  File "/usr/local/lib/python3.4/socket.py", line 507, in create_connection
    sock.connect(sa)
OSError: [Errno 99] Cannot assign requested address

在阅读了一些类似的stackoverflow问题后,我使用-d选项运行容器,并通过以下方式访问容器:

docker exec -ti <container name> bash

一旦进入容器,我使用curl和wget尝试访问localhost:5000/index。Wget只返回500错误。Curl返回Werkzeug页面(请参见上面的错误转储),包括所有HTML格式。目录结构看起来没问题。
我知道我一定配置错了什么。但我看不出来哪里出了问题。应用程序在Docker外部可以正常工作,在Docker中则不能。我无法从容器内部访问页面,这告诉我设置有问题,但我可能缺乏专业知识或者陷入了“树木看不到森林”的时刻。请帮助一个相对新手。

在你的 Dockerfile 中,你需要 EXPOSE 端口,然后将其映射到本地端口。 - blakev
1
@blakev EXPOSE 不是必须的来映射一个端口,更多的是用于说明镜像将会暴露出来的端口。 - Matt
也许是因为您无法在容器内连接到couchdb,或者可能是因为您的app.run参数顺序有些奇怪。app.run('0.0.0.0', 5000, debug=True) - blakev
“Cannot assign requested address” 看起来像是您正在尝试将服务器绑定到容器中不可用的特定IP。您是否在应用程序的某个地方配置了侦听IP或主机名? - Matt
@Matt 是的。我在里面使用了公开方法,但结果没有改变,因此至少在这种情况下它似乎没有效果。 至于IP地址,所有docker和flask的例子都使用0.0.0.0,很多没有Docker的Flask例子也是如此,因为它允许从本地主机之外访问应用程序。 blakev 我会尝试重新排列参数,看看会发生什么。 - Brett
1个回答

2

如果你看到这个错误,首先这是一个应用程序异常。这意味着你的主机绑定和容器内部的绑定都已经工作正常。这与暴露端口无关。

如果我们再仔细看一下异常堆栈跟踪

File "/usr/local/lib/python3.4/site-packages/couchdb/http.py", line 289, in request
    conn = self.connection_pool.get(url)
  File "/usr/local/lib/python3.4/site-packages/couchdb/http.py", line 507, in get
    conn.connect()
  File "/usr/local/lib/python3.4/http/client.py", line 871, in connect
    self.timeout, self.source_address)

您正在连接Couch DB,但地址不正确,这就是导致错误的原因。错误OSError: [Errno 99] Cannot assign requested address有点误导人,但是这是因为您无法连接到可能已被错误配置或根本未运行的Couch DB服务。


谢谢。我也觉得可能与Matt的评论有关,所以在删除对couch的任何调用后重新构建了容器。我使用了一个本地的couch实例,但我没有将它构建到容器中,也没有给容器任何关于如何访问它的指示。 - Brett
1
我的声望太低,无法为您的答案点赞,但它是正确的,所以在精神上给您加一分。 - Brett

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接